Annotation of linux/kernel/blk_drv/scsi/aha1542.c, revision 1.1.1.4

1.1.1.3   root        1: /* $Id: aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $
1.1       root        2:  *  linux/kernel/aha1542.c
                      3:  *
1.1.1.3   root        4:  *  Copyright (C) 1992  Tommy Thorn
1.1       root        5:  */
                      6: 
                      7: #include <linux/config.h>
                      8: #include <linux/kernel.h>
                      9: #include <linux/head.h>
1.1.1.3   root       10: #include <linux/types.h>
1.1       root       11: #include <linux/string.h>
1.1.1.3   root       12: 
1.1       root       13: #include <asm/system.h>
                     14: #include <asm/io.h>
                     15: #include "scsi.h"
                     16: #include "hosts.h"
                     17: 
                     18: #include "aha1542.h"
                     19: #ifdef DEBUG
                     20: #define DEB(x) x
                     21: #else
                     22: #define DEB(x)
                     23: #endif
                     24: 
                     25: /*
1.1.1.3   root       26: static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
1.1       root       27: */
                     28: 
                     29: #define base 0x330
                     30: #define intr_chan 11
                     31: 
                     32: static struct mailbox mb[2];
                     33: static struct ccb ccb;
                     34: 
                     35: long WAITtimeout, WAITnexttimeout = 3000000;
                     36: 
1.1.1.3   root       37: void (*do_done)(int, int) = NULL;
                     38: int aha1542_host = 0;
1.1       root       39: extern void aha1542_interrupt();
                     40: 
                     41: #define aha1542_intr_reset()  outb(IRST, CONTROL)
                     42: #define aha1542_enable_intr() outb(inb_p(0xA1) & ~8, 0xA1)
                     43: #define aha1542_disable_intr() outb(inb_p(0xA1) | 8, 0xA1)
                     44: 
                     45: #define WAIT(port, mask, allof, noneof)                                        \
                     46:  { register WAITbits;                                                  \
                     47:    register WAITtimeout = WAITnexttimeout;                             \
                     48:    while (1) {                                                         \
                     49:      WAITbits = inb(port) & (mask);                                    \
                     50:      if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
                     51:        break;                                                          \
                     52:      if (--WAITtimeout == 0) goto fail;                                        \
                     53:    }                                                                   \
                     54:  }
                     55: 
                     56: static void aha1542_stat(void)
                     57: {
1.1.1.3   root       58: /*    int s = inb(STATUS), i = inb(INTRFLAGS);
                     59:   printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout); */
1.1       root       60: }
                     61: 
                     62: static int aha1542_out(unchar *cmdp, int len)
                     63: {
                     64:     while (len--)
                     65:       {
                     66:          WAIT(STATUS, CDF, 0, CDF);
                     67:          outb(*cmdp++, DATA);
                     68:       }
                     69:     return 0;
                     70:   fail:
                     71:     printk("aha1542_out failed(%d): ", len+1); aha1542_stat();
                     72:     return 1;
                     73: }
                     74: 
1.1.1.4 ! root       75: static int aha1542_in(unchar *cmdp, int len)
        !            76: {
        !            77:     while (len--)
        !            78:       {
        !            79:          WAIT(STATUS, DF, DF, 0);
        !            80:          *cmdp++ = inb(DATA);
        !            81:       }
        !            82:     return 0;
        !            83:   fail:
        !            84:     printk("aha1542_in failed(%d): ", len+1); aha1542_stat();
        !            85:     return 1;
        !            86: }
1.1       root       87: int makecode(unsigned hosterr, unsigned scsierr)
                     88: {
                     89:     switch (hosterr) {
                     90:       case 0x0:
                     91:       case 0xa: /* Linked command complete without error and linked normally */
                     92:       case 0xb: /* Linked command complete without error, interrupt generated */
                     93:        hosterr = 0;
                     94:        break;
                     95: 
                     96:       case 0x11: /* Selection time out-The initiator selection or target
                     97:                    reselection was not complete within the SCSI Time out period */
                     98:        hosterr = DID_TIME_OUT;
                     99:        break;
                    100: 
                    101:       case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
                    102:                    thean was allocated by the Data Length field or the sum of the
                    103:                    Scatter / Gather Data Length fields. */
                    104: 
                    105:       case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
                    106: 
                    107:       case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
                    108:                    invalid. This usually indicates a software failure. */
                    109: 
                    110:       case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
                    111:                    This usually indicates a software failure. */
                    112: 
                    113:       case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
                    114:                    of linked CCB's does not specify the same logical unit number as
                    115:                    the first. */
                    116:       case 0x18: /* Invalid Target Direction received from Host-The direction of a
                    117:                    Target Mode CCB was invalid. */
                    118: 
                    119:       case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
                    120:                    received to service data transfer between the same target LUN
                    121:                    and initiator SCSI ID in the same direction. */
                    122: 
                    123:       case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
                    124:                    length segment or invalid segment list boundaries was received.
                    125:                    A CCB parameter was invalid. */
                    126:        hosterr = DID_ERROR; /* Couldn't find any better */
                    127:        break;
                    128: 
                    129:       case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
                    130:                    phase sequence was requested by the target. The host adapter
                    131:                    will generate a SCSI Reset Condition, notifying the host with
                    132:                    a SCRD interrupt */
                    133:        hosterr = DID_RESET;
                    134:        break;
                    135:       default:
                    136:        printk("makecode: unknown hoststatus %x\n", hosterr);
                    137:        break;
                    138:     }
                    139:     return scsierr|(hosterr << 16);
                    140: }
                    141: 
                    142: int aha1542_test_port(void)
                    143: {
                    144:     volatile int debug = 0;
                    145:     
                    146:     /* Reset the adapter. I ought to make a hard reset, but it's not really nessesary */
                    147:     
                    148:     /*  DEB(printk("aha1542_test_port called \n")); */
                    149:     
                    150:     outb(SRST|IRST/*|SCRST*/, CONTROL);
                    151:     
                    152:     debug = 1;
                    153:     /* Expect INIT and IDLE, any of the others are bad */
                    154:     WAIT(STATUS, STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF);
                    155:     
                    156:     debug = 2;
                    157:     /* Shouldn't have generated any interrupts during reset */
                    158:     if (inb(INTRFLAGS)&INTRMASK) goto fail;
                    159:     
                    160:     debug = 3;
                    161:     /* Test the basic ECHO command */
                    162:     outb(CMD_ECHO, DATA);
                    163:     
                    164:     debug = 4;
                    165:     /* Wait for CDF=0. If any of the others are set, it's bad */
                    166:     WAIT(STATUS, STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF);
                    167:     
                    168:     debug = 5;
                    169:     /* The meaning of life */
                    170:     outb(42, DATA);
                    171:     
                    172:     debug = 6;
                    173:     /* Expect only DF, that is, data ready */
                    174:     WAIT(STATUS, STATMASK, DF, STST|DIAGF|CDF|INVDCMD);
                    175:     
                    176:     debug = 7;
                    177:     /* Is the answer correct? */
                    178:     if (inb(DATA) != 42) goto fail;
                    179:     
                    180:     debug = 8;
                    181:     /* Reading port should reset DF */
                    182:     if (inb(STATUS) & DF) goto fail;
                    183:     
                    184:     debug = 9;
                    185:     /* When HACC, command is completed, and we're though testing */
                    186:     WAIT(INTRFLAGS, HACC, HACC, 0);
                    187:     /* now initialize adapter */
                    188:     
                    189:     debug = 10;
                    190:     /* Clear interrupts */
                    191:     outb(IRST, CONTROL);
                    192:     
                    193:     debug = 11;
                    194:     
                    195:     return debug;                              /* 1 = ok */
                    196:   fail:
                    197:     return 0;                                  /* 0 = not ok */
                    198: }
                    199: 
                    200: /* What's this little function for? */
                    201: char *aha1542_info(void)
                    202: {
1.1.1.4 ! root      203:     static char buffer[] = "";                 /* looks nicer without anything here */
1.1       root      204:     return buffer;
                    205: }
                    206: 
                    207: /* A "high" level interrupt handler */
                    208: void aha1542_intr_handle(void)
                    209: {
1.1.1.3   root      210:     void (*my_done)(int, int) = do_done;
1.1       root      211:     int errstatus;
                    212: 
                    213:     do_done = NULL;
                    214: #ifdef DEBUG
1.1.1.4 ! root      215:     {
        !           216:     int flag = inb(INTRFLAGS);
1.1       root      217:     printk("aha1542_intr_handle: ");
                    218:     if (!(flag&ANYINTR)) printk("no interrupt?");
                    219:     if (flag&MBIF) printk("MBIF ");
                    220:     if (flag&MBOA) printk("MBOF ");
                    221:     if (flag&HACC) printk("HACC ");
                    222:     if (flag&SCRD) printk("SCRD ");
                    223:     printk("status %02x\n", inb(STATUS));
                    224:     if (ccb.tarstat|ccb.hastat)
                    225:       printk("aha1542_command: returning %x (status %d)\n", ccb.tarstat + ((int) ccb.hastat << 16), mb[1].status);
1.1.1.4 ! root      226:   };
1.1       root      227: #endif
                    228:     aha1542_intr_reset();
                    229:     if (!my_done) {
                    230:        printk("aha1542_intr_handle: Unexpected interrupt\n");
                    231:        return;
                    232:     }
                    233: 
                    234:     /* is there mail :-) */
                    235:        
                    236:     if (!mb[1].status) {
                    237:        DEB(printk("aha1542_intr_handle: strange: mbif but no mail!\n"));
1.1.1.3   root      238:        my_done(aha1542_host, DID_TIME_OUT << 16);
1.1       root      239:        return;
                    240:     }
                    241: 
                    242:     /* more error checking left out here */
                    243:     if (mb[1].status != 1)
                    244:       /* This is surely wrong, but I don't know what's right */
                    245:       errstatus = makecode(ccb.hastat, ccb.tarstat);
                    246:     else
                    247:       errstatus = 0;
                    248: 
                    249:     mb[1].status = 0;
                    250: 
                    251:     if (ccb.tarstat == 2) {
                    252:        int i;
                    253:        DEB(printk("aha1542_intr_handle: sense:"));
1.1.1.4 ! root      254: #ifdef DEBUG
1.1       root      255:        for (i = 0; i < 12; i++)
                    256:          printk("%02x ", ccb.cdb[ccb.cdblen+i]);
                    257:        printk("\n");
1.1.1.4 ! root      258: #endif
1.1       root      259: /*
                    260:        DEB(printk("aha1542_intr_handle: buf:"));
                    261:        for (i = 0; i < bufflen; i++)
                    262:          printk("%02x ", ((unchar *)buff)[i]);
                    263:        printk("\n");
                    264: */
                    265:     }
                    266:     DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
1.1.1.3   root      267:     my_done(aha1542_host, errstatus);
1.1       root      268:     return;
                    269: }
                    270: 
1.1.1.3   root      271: int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int, int))
1.1       root      272: {
                    273:     unchar ahacmd = CMD_START_SCSI;
1.1.1.4 ! root      274:     unchar direction;
1.1       root      275:     unchar *cmd = (unchar *) cmnd;
1.1.1.3   root      276:     DEB(int i);
1.1       root      277: 
1.1.1.3   root      278:     DEB(if (target > 1) {done(aha1542_host, DID_TIME_OUT << 16); return 0;});
1.1       root      279:     
1.1.1.4 ! root      280:     if(*cmd == REQUEST_SENSE){
        !           281:       memcpy(buff, &ccb.cdb[ccb.cdblen], bufflen);
        !           282:       done(aha1542_host, 0); 
        !           283:       return 0;
        !           284:     };
        !           285: 
1.1       root      286: #ifdef DEBUG
                    287:     if (*cmd == READ_10 || *cmd == WRITE_10)
                    288:       i = xscsi2int(cmd+2);
                    289:     else if (*cmd == READ_6 || *cmd == WRITE_6)
                    290:       i = scsi2int(cmd+2);
                    291:     else
                    292:       i = -1;
                    293:     if (done)
                    294:       printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
                    295:     else
                    296:       printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
                    297:     aha1542_stat();
                    298:     printk("aha1542_queuecommand: dumping scsi cmd:");
                    299:     for (i = 0; i < (*cmd<=0x1f?6:10); i++) printk("%02x ", cmd[i]);
                    300:     printk("\n");
                    301:     if (*cmd == WRITE_10 || *cmd == WRITE_6)
                    302:       return 0; /* we are still testing, so *don't* write */
                    303: #endif
                    304:     memset(&ccb, 0, sizeof ccb);
1.1.1.4 ! root      305: 
1.1       root      306:     ccb.cdblen = (*cmd<=0x1f)?6:10;    /* SCSI Command Descriptor Block Length */
1.1.1.4 ! root      307: 
        !           308:     direction = 0;
        !           309:     if (*cmd == READ_10 || *cmd == READ_6)
        !           310:        direction = 8;
        !           311:     else if (*cmd == WRITE_10 || *cmd == WRITE_6)
        !           312:        direction = 16;
        !           313: 
1.1       root      314:     memcpy(ccb.cdb, cmd, ccb.cdblen);
                    315:     ccb.op = 0;                                /* SCSI Initiator Command */
1.1.1.4 ! root      316:     ccb.idlun = (target&7)<<5 | direction;  /* SCSI Target Id */
1.1       root      317:     ccb.rsalen = 12;
                    318:     any2scsi(ccb.datalen, bufflen);
                    319:     any2scsi(ccb.dataptr, buff);
                    320:     ccb.linkptr[0] = ccb.linkptr[1] = ccb.linkptr[2] = 0;
                    321:     ccb.commlinkid = 0;
                    322:     
                    323:     mb[0].status = 1;
                    324:     mb[1].status = 0;
                    325:     
                    326: #ifdef DEBUGd
                    327:     printk("aha1542_command: sending.. ");
                    328:     for (i = 0; i < sizeof(ccb)-10; i++)
                    329:       printk("%02x ", ((unchar *)&ccb)[i]);
                    330: #endif
                    331:     
                    332:     if (done) {
                    333:        DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
                    334:        if (do_done)
                    335:          printk("aha1542_queuecommand: Two concurrent queuecommand?\n");
                    336:        else
                    337:          do_done = done;
                    338:        aha1542_out(&ahacmd, 1);                /* start scsi command */
                    339:        DEB(aha1542_stat());
                    340:        aha1542_enable_intr();
                    341:     }
                    342:     else
                    343:       printk("aha1542_queuecommand: done can't be NULL\n");
                    344:     
                    345:     return 0;
                    346: }
                    347: 
                    348: volatile static int internal_done_flag = 0;
                    349: volatile static int internal_done_errcode = 0;
1.1.1.3   root      350: static void internal_done(int host, int errcode)
1.1       root      351: {
                    352:     internal_done_errcode = errcode;
                    353:     ++internal_done_flag;
                    354: }
                    355: 
                    356: int aha1542_command(unchar target, const void *cmnd, void *buff, int bufflen)
                    357: {
                    358:     DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
                    359:     aha1542_queuecommand(target, cmnd, buff, bufflen, internal_done);
                    360: 
                    361:     while (!internal_done_flag);
                    362:     internal_done_flag = 0;
                    363:     return internal_done_errcode;
                    364: }
                    365: 
                    366: /* Initialize mailboxes */
                    367: static void setup_mailboxes()
                    368: {
                    369:     static unchar cmd[5] = {CMD_MBINIT, 1};
                    370:     
                    371:     mb[0].status = mb[1].status = 0;
                    372:     aha1542_intr_reset();              /* reset interrupts, so they don't block */     
                    373:     any2scsi((cmd+2), mb);
                    374:     any2scsi(mb[0].ccbptr, &ccb);
                    375:     aha1542_out(cmd, 5);
                    376:     WAIT(INTRFLAGS, INTRMASK, HACC, 0);
                    377:     while (0) {
                    378:       fail:
                    379:        printk("aha1542_detect: failed setting up mailboxes\n");
                    380:     }
                    381:     aha1542_intr_reset();
                    382: }
                    383: 
                    384: /* a hack to avoid a strange compilation error */
                    385: 
                    386: void call_buh()
                    387: {
                    388:     set_intr_gate(0x2b,&aha1542_interrupt);
                    389: }
                    390: 
1.1.1.4 ! root      391: /* Query the board to find out if it is a 1542 or a 1740, or whatever. */
        !           392: static void aha1542_query()
        !           393: {
        !           394:   static unchar inquiry_cmd[] = {CMD_INQUIRY };
        !           395:   static unchar inquiry_result[4];
        !           396:   int i;
        !           397:   i = inb(STATUS);
        !           398:   if (i & DF) {
        !           399:     i = inb(DATA);
        !           400:     printk("Stale data:%x ");
        !           401:   };
        !           402:   aha1542_out(inquiry_cmd, 1);
        !           403:   aha1542_in(inquiry_result, 4);
        !           404:   WAIT(INTRFLAGS, INTRMASK, HACC, 0);
        !           405:   while (0) {
        !           406:   fail:
        !           407:     printk("aha1542_detect: query card type\n");
        !           408:   }
        !           409:       aha1542_intr_reset();
        !           410:   printk("Inquiry:");
        !           411:   for(i=0;i<4;i++) printk("%x ",inquiry_result[i]);
        !           412: }
1.1       root      413: /* return non-zero on detection */
1.1.1.3   root      414: int aha1542_detect(int hostnum)
1.1       root      415: {
                    416:     int i;
                    417: 
                    418:     DEB(printk("aha1542_detect: \n"));
                    419:     
                    420:     if (!(i = aha1542_test_port())) {
                    421:        return 0;
                    422:     }
                    423:  
                    424:     /* Set the Bus on/off-times as not to ruin floppy performens */
                    425:     {
                    426:        static unchar oncmd[] = {CMD_BUSON_TIME, 5};
                    427:        static unchar offcmd[] = {CMD_BUSOFF_TIME, 9};
                    428:        
                    429:        aha1542_intr_reset();
                    430:        aha1542_out(oncmd, 2);
                    431:        WAIT(INTRFLAGS, INTRMASK, HACC, 0);
                    432:        aha1542_intr_reset();
                    433:        aha1542_out(offcmd, 2);
                    434:        WAIT(INTRFLAGS, INTRMASK, HACC, 0);
                    435:        while (0) {
                    436:          fail:
                    437:            printk("aha1542_detect: setting bus on/off-time failed\n");
                    438:        }
                    439:        aha1542_intr_reset();
                    440:     }
1.1.1.4 ! root      441:     aha1542_query();
1.1       root      442: 
1.1.1.4 ! root      443:     DEB(aha1542_stat());
1.1       root      444:     setup_mailboxes();
                    445: 
1.1.1.4 ! root      446:     DEB(aha1542_stat());
1.1       root      447: 
                    448:     DEB(printk("aha1542_detect: enable interrupt channel %d\n", intr_chan));
                    449:     call_buh();
                    450: 
                    451:     if (intr_chan >= 8)
                    452:       outb(inb_p(0x21)&0xfb,0x21);             /* open for slave ?? */
                    453: 
                    454:     DEB(printk("aha1542_detect: enabling interrupts\n"));
                    455:     aha1542_enable_intr();
                    456: 
                    457: #ifdef DEBUG
                    458:     DEB(printk(" *** READ CAPACITY ***\n"));
                    459: 
                    460:     {
                    461:        unchar buf[8];
                    462:        static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
                    463:        int i;
                    464:        
                    465:        for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
                    466:        for (i = 0; i < 2; ++i)
                    467:          if (!aha1542_command(i, cmd, buf, sizeof(buf))) {
                    468:              printk("aha_detect: LU %d sector_size %d device_size %d\n",
                    469:                     i, xscsi2int(buf+4), xscsi2int(buf));
                    470:          }
                    471:     }
                    472: 
                    473:     DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n"));
                    474: 
                    475:     for (i = 0; i < 4; ++i)
                    476:       {
                    477:          unsigned char cmd[10];
                    478:          static buffer[512];
                    479:          
                    480:          cmd[0] = READ_10;
                    481:          cmd[1] = 0;
                    482:          xany2scsi(cmd+2, i);
                    483:          cmd[6] = 0;
                    484:          cmd[7] = 0;
                    485:          cmd[8] = 1;
                    486:          cmd[9] = 0;
                    487:          aha1542_command(0, cmd, buffer, 512);
                    488:       }
                    489: #endif
1.1.1.3   root      490:     aha1542_host = hostnum;
1.1       root      491:     return 1;
                    492: }
                    493: 
                    494: int aha1542_abort(int i)
                    495: {
                    496:     DEB(printk("aha1542_abort\n"));
                    497:     return 0;
                    498: }
                    499: 
                    500: int aha1542_reset(void)
                    501: {
                    502:     DEB(printk("aha1542_reset called\n"));
                    503:     return 0;
                    504: }
                    505: 
                    506: __asm__("
                    507: _aha1542_interrupt:
                    508:        cld
                    509:        pushl %eax
                    510:        pushl %ecx
                    511:        pushl %edx
                    512:        push %ds
                    513:        push %es
                    514:        push %fs
                    515:        movl $0x10,%eax
                    516:        mov %ax,%ds
                    517:        mov %ax,%es
                    518:        movl $0x17,%eax
                    519:        mov %ax,%fs
                    520:        movb $0x20,%al
                    521:        outb %al,$0xA0          # EOI to interrupt controller #1
                    522:        jmp 1f                  # give port chance to breathe
                    523: 1:     jmp 1f
                    524: 1:     outb %al,$0x20
                    525: # Please, someone, change this to use the timer
                    526: #      andl $0xfffeffff,_timer_active
                    527:        movl $_aha1542_intr_handle,%edx
                    528:        call *%edx              # ``interesting'' way of handling intr.
                    529:        pop %fs
                    530:        pop %es
                    531:        pop %ds
                    532:        popl %edx
                    533:        popl %ecx
                    534:        popl %eax
                    535:        iret
                    536: ");

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.