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

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

unix.superglobalmegacorp.com

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