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

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

unix.superglobalmegacorp.com

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