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

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: 
                     75: int makecode(unsigned hosterr, unsigned scsierr)
                     76: {
                     77:     switch (hosterr) {
                     78:       case 0x0:
                     79:       case 0xa: /* Linked command complete without error and linked normally */
                     80:       case 0xb: /* Linked command complete without error, interrupt generated */
                     81:        hosterr = 0;
                     82:        break;
                     83: 
                     84:       case 0x11: /* Selection time out-The initiator selection or target
                     85:                    reselection was not complete within the SCSI Time out period */
                     86:        hosterr = DID_TIME_OUT;
                     87:        break;
                     88: 
                     89:       case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
                     90:                    thean was allocated by the Data Length field or the sum of the
                     91:                    Scatter / Gather Data Length fields. */
                     92: 
                     93:       case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
                     94: 
                     95:       case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
                     96:                    invalid. This usually indicates a software failure. */
                     97: 
                     98:       case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
                     99:                    This usually indicates a software failure. */
                    100: 
                    101:       case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
                    102:                    of linked CCB's does not specify the same logical unit number as
                    103:                    the first. */
                    104:       case 0x18: /* Invalid Target Direction received from Host-The direction of a
                    105:                    Target Mode CCB was invalid. */
                    106: 
                    107:       case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
                    108:                    received to service data transfer between the same target LUN
                    109:                    and initiator SCSI ID in the same direction. */
                    110: 
                    111:       case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
                    112:                    length segment or invalid segment list boundaries was received.
                    113:                    A CCB parameter was invalid. */
                    114:        hosterr = DID_ERROR; /* Couldn't find any better */
                    115:        break;
                    116: 
                    117:       case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
                    118:                    phase sequence was requested by the target. The host adapter
                    119:                    will generate a SCSI Reset Condition, notifying the host with
                    120:                    a SCRD interrupt */
                    121:        hosterr = DID_RESET;
                    122:        break;
                    123:       default:
                    124:        printk("makecode: unknown hoststatus %x\n", hosterr);
                    125:        break;
                    126:     }
                    127:     return scsierr|(hosterr << 16);
                    128: }
                    129: 
                    130: int aha1542_test_port(void)
                    131: {
                    132:     volatile int debug = 0;
                    133:     
                    134:     /* Reset the adapter. I ought to make a hard reset, but it's not really nessesary */
                    135:     
                    136:     /*  DEB(printk("aha1542_test_port called \n")); */
                    137:     
                    138:     outb(SRST|IRST/*|SCRST*/, CONTROL);
                    139:     
                    140:     debug = 1;
                    141:     /* Expect INIT and IDLE, any of the others are bad */
                    142:     WAIT(STATUS, STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF);
                    143:     
                    144:     debug = 2;
                    145:     /* Shouldn't have generated any interrupts during reset */
                    146:     if (inb(INTRFLAGS)&INTRMASK) goto fail;
                    147:     
                    148:     debug = 3;
                    149:     /* Test the basic ECHO command */
                    150:     outb(CMD_ECHO, DATA);
                    151:     
                    152:     debug = 4;
                    153:     /* Wait for CDF=0. If any of the others are set, it's bad */
                    154:     WAIT(STATUS, STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF);
                    155:     
                    156:     debug = 5;
                    157:     /* The meaning of life */
                    158:     outb(42, DATA);
                    159:     
                    160:     debug = 6;
                    161:     /* Expect only DF, that is, data ready */
                    162:     WAIT(STATUS, STATMASK, DF, STST|DIAGF|CDF|INVDCMD);
                    163:     
                    164:     debug = 7;
                    165:     /* Is the answer correct? */
                    166:     if (inb(DATA) != 42) goto fail;
                    167:     
                    168:     debug = 8;
                    169:     /* Reading port should reset DF */
                    170:     if (inb(STATUS) & DF) goto fail;
                    171:     
                    172:     debug = 9;
                    173:     /* When HACC, command is completed, and we're though testing */
                    174:     WAIT(INTRFLAGS, HACC, HACC, 0);
                    175:     /* now initialize adapter */
                    176:     
                    177:     debug = 10;
                    178:     /* Clear interrupts */
                    179:     outb(IRST, CONTROL);
                    180:     
                    181:     debug = 11;
                    182:     
                    183:     return debug;                              /* 1 = ok */
                    184:   fail:
                    185:     return 0;                                  /* 0 = not ok */
                    186: }
                    187: 
                    188: /* What's this little function for? */
                    189: char *aha1542_info(void)
                    190: {
                    191:     static char buffer[] = "Adaptec 1542";
                    192:     return buffer;
                    193: }
                    194: 
                    195: /* A "high" level interrupt handler */
                    196: void aha1542_intr_handle(void)
                    197: {
1.1.1.3 ! root      198:     void (*my_done)(int, int) = do_done;
1.1       root      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"));
1.1.1.3 ! root      223:        my_done(aha1542_host, DID_TIME_OUT << 16);
1.1       root      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));
1.1.1.3 ! root      250:     my_done(aha1542_host, errstatus);
1.1       root      251:     return;
                    252: }
                    253: 
1.1.1.3 ! root      254: int aha1542_queuecommand(unchar target, const void *cmnd, void *buff, int bufflen, void (*done)(int, int))
1.1       root      255: {
                    256:     unchar ahacmd = CMD_START_SCSI;
                    257:     unchar *cmd = (unchar *) cmnd;
1.1.1.3 ! root      258:     DEB(int i);
1.1       root      259: 
1.1.1.3 ! root      260:     DEB(if (target > 1) {done(aha1542_host, DID_TIME_OUT << 16); return 0;});
1.1       root      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;
1.1.1.3 ! root      320: static void internal_done(int host, int errcode)
1.1       root      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 */
1.1.1.3 ! root      362: int aha1542_detect(int hostnum)
1.1       root      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
1.1.1.3 ! root      437:     aha1542_host = hostnum;
1.1       root      438:     return 1;
                    439: }
                    440: 
                    441: int aha1542_abort(int i)
                    442: {
                    443:     DEB(printk("aha1542_abort\n"));
                    444:     return 0;
                    445: }
                    446: 
                    447: int aha1542_reset(void)
                    448: {
                    449:     DEB(printk("aha1542_reset called\n"));
                    450:     return 0;
                    451: }
                    452: 
                    453: __asm__("
                    454: _aha1542_interrupt:
                    455:        cld
                    456:        pushl %eax
                    457:        pushl %ecx
                    458:        pushl %edx
                    459:        push %ds
                    460:        push %es
                    461:        push %fs
                    462:        movl $0x10,%eax
                    463:        mov %ax,%ds
                    464:        mov %ax,%es
                    465:        movl $0x17,%eax
                    466:        mov %ax,%fs
                    467:        movb $0x20,%al
                    468:        outb %al,$0xA0          # EOI to interrupt controller #1
                    469:        jmp 1f                  # give port chance to breathe
                    470: 1:     jmp 1f
                    471: 1:     outb %al,$0x20
                    472: # Please, someone, change this to use the timer
                    473: #      andl $0xfffeffff,_timer_active
                    474:        movl $_aha1542_intr_handle,%edx
                    475:        call *%edx              # ``interesting'' way of handling intr.
                    476:        pop %fs
                    477:        pop %es
                    478:        pop %ds
                    479:        popl %edx
                    480:        popl %ecx
                    481:        popl %eax
                    482:        iret
                    483: ");

unix.superglobalmegacorp.com

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