Annotation of lucent/sys/src/9/pc/adaptec.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Adaptec AHA-154[02][BC] Intelligent Host Adapter.
                      3:  * Also works for
                      4:  *     Buslogic BT-545C ISA adapter;
                      5:  *     Buslogic BT-747 EISA adapter.
                      6:  * Needs work:
                      7:  *     handle multiple controllers;
                      8:  *     set options from user-level;
                      9:  *     split out to handle ultrastor too;
                     10:  */
                     11: #include "u.h"
                     12: #include "../port/lib.h"
                     13: #include "mem.h"
                     14: #include "dat.h"
                     15: #include "fns.h"
                     16: #include "io.h"
                     17: #include "../port/error.h"
                     18: 
                     19: #include "ureg.h"
                     20: 
                     21: enum {
                     22:        NCtlr           = 1,
                     23:        NTarget         = 8,            /* targets per controller */
                     24: 
                     25:        Port            = 0x330,        /* factory defaults: I/O port */
                     26:        CtlrID          = 7,            /*      adapter SCSI id */
                     27:        Irq             = 11,           /*      interrupt request level */
                     28: };
                     29: 
                     30: enum {                                 /* registers */
                     31:        Rc              = 0,            /* WO: control */
                     32:        Rs              = 0,            /* RO: status */
                     33:        Rcdo            = 1,            /* WO: command/data out */
                     34:        Rdi             = 1,            /* RO: data in */
                     35:        Rif             = 2,            /* RO: interrupt flags */
                     36: };
                     37: 
                     38: enum {                                 /* Rc */
                     39:        Scrst           = 0x10,         /* SCSI bus reset */
                     40:        Irst            = 0x20,         /* interrupt reset */
                     41:        Srst            = 0x40,         /* soft reset */
                     42:        Hrst            = 0x80,         /* hard reset */
                     43: };
                     44: 
                     45: enum {                                 /* Rs */
                     46:        Invdcmd         = 0x01,         /* invalid host adapter command */
                     47:        Df              = 0x04,         /* data in port full */
                     48:        Cdf             = 0x08,         /* command/data port full */
                     49:        Idle            = 0x10,         /* SCSI host adapter idle */
                     50:        Init            = 0x20,         /* mailbox initialisation required */
                     51:        Diagf           = 0x40,         /* internal diagnostic failure */
                     52:        Stst            = 0x80,         /* self testing in progress */
                     53: };
                     54: 
                     55: enum {                                 /* Rcdo */
                     56:        Cnop            = 0x00,         /* no operation */
                     57:        Cmbinit         = 0x01,         /* mailbox initialisation */
                     58:        Cstart          = 0x02,         /* start SCSI command */
                     59:        Cbios           = 0x03,         /* start PC/AT BIOS command */
                     60:        Cinquiry        = 0x04,         /* adapter inquiry */
                     61:        Cmboie          = 0x05,         /* enable mailbox out available interrupt */
                     62:        Cselection      = 0x06,         /* set selection timeout */
                     63:        Cbuson          = 0x07,         /* set bus-on time */
                     64:        Cbusoff         = 0x08,         /* set bus-off time */
                     65:        Ctransfer       = 0x09,         /* set transfer speed */
                     66:        Cdevices        = 0x0A,         /* return installed devices */
                     67:        Cconfiguration  = 0x0B,         /* return configuration data */
                     68:        Ctenable        = 0x0C,         /* enable target mode */
                     69:        Csetup          = 0x0D,         /* return setup data */
                     70:        Cwbuff          = 0x1A,         /* write adapter channel 2 buffer */
                     71:        Crbuff          = 0x1B,         /* read adapter channel 2 buffer */
                     72:        Cwfifo          = 0x1C,         /* write adapter FIFO buffer */
                     73:        Crfifo          = 0x1D,         /* read adapter FIFO buffer */
                     74:        Cecho           = 0x1F,         /* ECHO command data */
                     75:        Cdiag           = 0x20,         /* adapter diagnostic */
                     76:        Coptions        = 0x21,         /* set host adapter options */
                     77: };
                     78: 
                     79: enum {                                 /* Rif */
                     80:        Mbif            = 0x01,         /* mailbox in full */
                     81:        Mboa            = 0x02,         /* mailbox out available */
                     82:        Hacc            = 0x04,         /* host adapter command complete */
                     83:        Scrd            = 0x08,         /* SCSI reset detected */
                     84:        Ai              = 0x80,         /* any interrupt */
                     85: };
                     86: 
                     87: typedef struct {
                     88:        uchar   cmd;                    /* command */
                     89:        uchar   msb;                    /* CCB pointer MSB */
                     90:        uchar   mid;                    /* CCB pointer MID */
                     91:        uchar   lsb;                    /* CCB pointer LSB */
                     92: } Mbox;
                     93: 
                     94: enum {                                 /* mailbox commands */
                     95:        Mbfree          = 0x00,         /* mailbox is free */
                     96: 
                     97:        Mbostart        = 0x01,         /* start SCSI or adapter command */
                     98:        Mboabort        = 0x02,         /* abort SCSI or adapter command */
                     99: 
                    100:        Mbiok           = 0x01,         /* CCB completed without error */
                    101:        Mbiabort        = 0x02,         /* CCB aborted by host */
                    102:        Mbinx           = 0x03,         /* aborted CCB not found */
                    103:        Mbierror        = 0x04,         /* CCB completed with error */
                    104: };
                    105: 
                    106: typedef struct {
                    107:        uchar   op;                     /* command control block operation code */
                    108:        uchar   ctl;                    /* address and direction control */
                    109:        uchar   cmdlen;                 /* SCSI command length */
                    110:        uchar   reqlen;                 /* request sense allocation length */
                    111:        uchar   datalen[3];             /* data length (MSB, MID, LSB) */
                    112:        uchar   dataptr[3];             /* data pointer (MSB, MID, LSB) */
                    113:        uchar   linkptr[3];             /* link pointer (MSB, MID, LSB) */
                    114:        uchar   linkid;                 /* command linking identifier */
                    115:        uchar   hastat;                 /* host adapter status */
                    116:        uchar   tarstat;                /* target device status */
                    117:        uchar   reserved[2];
                    118:        uchar   cs[12+0xFF];            /* SCSI command and sense bytes */
                    119: } Ccb;
                    120: 
                    121: enum {                                 /* op */
                    122:        OInitiator      = 0x00,         /* initiator CCB */
                    123:        OTarget         = 0x01,         /* target CCB */
                    124:        Osg             = 0x02,         /* initiator CCB with scatter/gather */
                    125:        Ordl            = 0x03,         /* initiator CCB, residual data length returned */
                    126:        Osgrdl          = 0x04,         /* initiator CCB, both of the above */
                    127:        Obdr            = 0x81,         /* bus device reset */
                    128: };
                    129: 
                    130: enum {                                 /* ctl */
                    131:        CCBdatain       = 0x08,         /* inbound data transfer, length is checked */
                    132:        CCBdataout      = 0x10,         /* outbound data transfer, length is checked */
                    133: };
                    134: 
                    135: enum {                                 /* hastat */
                    136:        Eok             = 0x00,         /* no host adapter detected error */
                    137:        Etimeout        = 0x11,         /* selection timeout */
                    138:        Elength         = 0x12,         /* data over/under run */
                    139:        Ebusfree        = 0x13,         /* unexpected bus free */
                    140:        Ephase          = 0x14,         /* target bus phase sequence error */
                    141:        Eopcode         = 0x16,         /* invalid CCB opcode */
                    142:        Elink           = 0x17,         /* linked CCB does not have same LUN */
                    143:        Edirection      = 0x18,         /* invalid target direction received from host */
                    144:        Eduplicate      = 0x19,         /* duplicate CCB received in target mode */
                    145:        Esegment        = 0x1A,         /* invalid CCB or segment list parameter */
                    146: };
                    147: 
                    148: enum {                                 /* tarstat */
                    149:        Sgood           = 0x00,         /* good status */
                    150:        Scheck          = 0x02,         /* check status */
                    151:        Sbusy           = 0x08,         /* LUN busy */
                    152: };
                    153: 
                    154: typedef struct Target Target;
                    155: typedef struct Ctlr Ctlr;
                    156: 
                    157: struct Target {
                    158:        QLock;
                    159:        Rendez;
                    160: 
                    161:        Ccb     ccb;
                    162:        ulong   paddr;                  /* physical address of ccb */
                    163:        uchar   *sense;                 /* address of returned sense data */
                    164: 
                    165:        int     done;
                    166:        Target  *active;                /* link on active list */
                    167: };
                    168: 
                    169: struct Ctlr {
                    170:        Lock;
                    171: 
                    172:        ulong   port;                   /* I/O port */
                    173:        ulong   id;                     /* adapter SCSI id */
                    174: 
                    175:        uchar   cmd[5];                 /* adapter command out */
                    176:        uchar   cmdlen;                 /* adapter command out length */
                    177:        uchar   data[256];              /* adapter command data in */
                    178:        uchar   datalen;                /* adapter command data in length */
                    179: 
                    180:        Mbox    mb[NTarget+NTarget];    /* mailbox out + mailbox in */
                    181: 
                    182:        Mbox    *mbox;                  /* current mailbox out index into mb */
                    183:        Mbox    *mbix;                  /* current mailbox in index into mb */
                    184: 
                    185:        Target  target[NTarget];
                    186:        Target  *active;                /* link on active list */
                    187: };
                    188: 
                    189: static Ctlr softctlr[NCtlr];
                    190: 
                    191: /*
                    192:  * Issue a command to the controller. The command and its length is
                    193:  * contained in ctlr->cmd and ctlr->cmdlen. If any data is to be
                    194:  * returned, ctlr->datalen should be non-0, and the returned data will
                    195:  * be placed in ctlr->data.
                    196:  * If we see Hacc set, bail out, we'll process
                    197:  * the invalid command at interrupt time.
                    198:  */
                    199: static void
                    200: issue(Ctlr *ctlr)
                    201: {
                    202:        int len;
                    203: 
                    204:        len = 0;
                    205:        while(len < ctlr->cmdlen){
                    206:                if((inb(ctlr->port+Rs) & Cdf) == 0){
                    207:                        outb(ctlr->port+Rcdo, ctlr->cmd[len]);
                    208:                        len++;
                    209:                }
                    210: 
                    211:                if(inb(ctlr->port+Rif) & Hacc)
                    212:                        return;
                    213:        }
                    214: 
                    215:        if(ctlr->datalen){
                    216:                len = 0;
                    217:                while(len < ctlr->datalen){
                    218:                        if(inb(ctlr->port+Rs) & Df){
                    219:                                ctlr->data[len] = inb(ctlr->port+Rdi);
                    220:                                len++;
                    221:                        }
                    222: 
                    223:                        if(inb(ctlr->port+Rif) & Hacc)
                    224:                                return;
                    225:                }
                    226:        }
                    227: }
                    228: 
                    229: static int
                    230: done(void *arg)
                    231: {
                    232:        return ((Target*)arg)->done;
                    233: }
                    234: 
                    235: static int
                    236: scsiio(int bus, Scsi *p, int rw)
                    237: {
                    238:        Ctlr *ctlr;
                    239:        Target *tp;
                    240:        ushort status;
                    241:        ulong len, s;
                    242: 
                    243:        /*
                    244:         * Wait for the target to become free,
                    245:         * then set it up. The Adaptec will allow us to
                    246:         * queue multiple transactions per target, but
                    247:         * gives no guarantee about ordering, so we just
                    248:         * allow one per target.
                    249:         */
                    250:        ctlr = &softctlr[bus];
                    251:        tp = &ctlr->target[p->target];
                    252: 
                    253:        qlock(tp);
                    254:        if(waserror()){
                    255:                qunlock(tp);
                    256:                nexterror();
                    257:        }
                    258: 
                    259:        /*
                    260:         * If this is a request-sense and we have valid sense data
                    261:         * from the last command, return it immediately.
                    262:         * A pox on these weird enum names and the WD33C93A status
                    263:         * codes.
                    264:         */
                    265:        if(p->cmd.base[0] == ScsiExtsens && tp->sense){
                    266:                len = 8+tp->sense[7];
                    267:                memmove(p->data.ptr, tp->sense, len);
                    268:                p->data.ptr += len;
                    269:                tp->sense = 0;
                    270: 
                    271:                qunlock(tp);
                    272:                poperror();
                    273:                return 0x6000;
                    274:        }
                    275:        tp->sense = 0;
                    276: 
                    277:        /*
                    278:         * Fill in the ccb. 
                    279:         */
                    280:        tp->ccb.op = Ordl;
                    281:        tp->ccb.ctl = (p->target<<5)|p->lun;
                    282: 
                    283:        len = p->cmd.lim - p->cmd.base;
                    284:        tp->ccb.cmdlen = len;
                    285:        memmove(tp->ccb.cs, p->cmd.base, len);
                    286: 
                    287:        tp->ccb.reqlen = 0xFF;
                    288: 
                    289:        len = p->data.lim - p->data.base;
                    290:        tp->ccb.datalen[0] = (len>>16) & 0xFF;
                    291:        tp->ccb.datalen[1] = (len>>8) & 0xFF;
                    292:        tp->ccb.datalen[2] = len;
                    293:        if(len == 0)
                    294:                tp->ccb.ctl |= CCBdataout|CCBdatain;
                    295:        else if(rw == ScsiIn)
                    296:                tp->ccb.ctl |= CCBdatain;
                    297:        else
                    298:                tp->ccb.ctl |= CCBdataout;
                    299: 
                    300:        len = PADDR(p->data.base);
                    301:        tp->ccb.dataptr[0] = (len>>16) & 0xFF;
                    302:        tp->ccb.dataptr[1] = (len>>8) & 0xFF;
                    303:        tp->ccb.dataptr[2] = len;
                    304: 
                    305:        tp->ccb.linkptr[0] = tp->ccb.linkptr[1] = tp->ccb.linkptr[2] = 0;
                    306:        tp->ccb.linkid = 0;
                    307: 
                    308:        tp->ccb.hastat = tp->ccb.tarstat = 0;
                    309:        tp->ccb.reserved[0] = tp->ccb.reserved[1] = 0;
                    310: 
                    311:        /*
                    312:         * Link the target onto the beginning of the
                    313:         * ctlr active list and start the request.
                    314:         * The interrupt routine has to be able to take
                    315:         * requests off the queue in any order.
                    316:         */
                    317:        s = splhi();
                    318:        if(active.machs > 1)
                    319:                lock(ctlr);
                    320: 
                    321:        tp->done = 0;
                    322:        tp->active = ctlr->active;
                    323:        ctlr->active = tp;
                    324: 
                    325:        ctlr->mbox->msb = (tp->paddr>>16) & 0xFF;
                    326:        ctlr->mbox->mid = (tp->paddr>>8) & 0xFF;
                    327:        ctlr->mbox->lsb = tp->paddr & 0xFF;
                    328:        ctlr->mbox->cmd = Mbostart;
                    329: 
                    330:        ctlr->cmd[0] = Cstart;
                    331:        ctlr->cmdlen = 1;
                    332:        ctlr->datalen = 0;
                    333:        issue(ctlr);
                    334: 
                    335:        ctlr->mbox++;
                    336:        if(ctlr->mbox >= &ctlr->mb[NTarget])
                    337:                ctlr->mbox = ctlr->mb;
                    338: 
                    339:        if(active.machs > 1)
                    340:                unlock(ctlr);
                    341:        splx(s);
                    342: 
                    343:        /*
                    344:         * Wait for the request to complete
                    345:         * and return the status.
                    346:         */
                    347:        tsleep(tp, done, tp, 60*5*1000);
                    348:        if(done(tp) == 0)
                    349:                print("adaptec%d: timeout cmd=#%2.2ux\n", p->target, tp->ccb.cs[0]);
                    350: 
                    351:        if((status = (tp->ccb.hastat<<8)) == 0)
                    352:                status = 0x6000;
                    353:        status |= tp->ccb.tarstat;
                    354:        len = (tp->ccb.datalen[0]<<16)|(tp->ccb.datalen[1]<<8)|tp->ccb.datalen[2];
                    355:        p->data.ptr = p->data.lim - len;
                    356: 
                    357:        /*
                    358:         * If the command returned sense data, keep a note
                    359:         * of where it is for a subsequent request-sense command.
                    360:         */
                    361:        if(tp->ccb.tarstat == Scheck && tp->ccb.hastat == Eok)
                    362:                tp->sense = &tp->ccb.cs[tp->ccb.cmdlen];
                    363: 
                    364:        qunlock(tp);
                    365:        poperror();
                    366: 
                    367:        return status;
                    368: }
                    369: 
                    370: static int
                    371: aha1542exec(Scsi *p, int rw)
                    372: {
                    373:        Ctlr *ctlr = &softctlr[0];
                    374: 
                    375:        if(ctlr->port == 0)
                    376:                error(Enodev);
                    377:        if(p->target == CtlrID)
                    378:                return 0x6002;
                    379: 
                    380:        return p->status = scsiio(0, p, rw);
                    381: }
                    382: 
                    383: static void
                    384: interrupt(Ureg *ur, void *a)
                    385: {
                    386:        Ctlr *ctlr = &softctlr[0];
                    387:        uchar rif, rs;
                    388:        Target *tp, **l;
                    389:        ulong paddr;
                    390: 
                    391:        USED(ur, a);
                    392: 
                    393:        if(active.machs > 1)
                    394:                lock(ctlr);
                    395: 
                    396:        /*
                    397:         * Save and clear the interrupt(s). The only
                    398:         * interrupts expected are Hacc, which we ignore,
                    399:         * and Mbif which means something completed.
                    400:         */
                    401:        rif = inb(ctlr->port+Rif);
                    402:        rs = inb(ctlr->port+Rs);
                    403:        outb(ctlr->port+Rc, Irst);
                    404:        if(rif & ~(Ai|Hacc|Mbif))
                    405:                print("adaptec%d: interrupt #%2.2ux\n", 0, rif);
                    406:        if((rif & Hacc) && (rs & Invdcmd))
                    407:                print("adaptec%d: invdcmd #%2.2ux, len %d\n", 0, ctlr->cmd[0], ctlr->cmdlen);
                    408: 
                    409:        /*
                    410:         * Look for something in the mail.
                    411:         * If there is, try to find the recipient from the
                    412:         * ccb address, take it off the active list and
                    413:         * wakeup whoever.
                    414:         */
                    415:        while(ctlr->mbix->cmd){
                    416:                paddr = (ctlr->mbix->msb<<16)|(ctlr->mbix->mid<<8)|ctlr->mbix->lsb;
                    417:                l = &ctlr->active;
                    418:                for(tp = *l; tp; tp = tp->active){
                    419:                        if(tp->paddr == paddr)
                    420:                                break;
                    421:                        l = &tp->active;
                    422:                }
                    423:                if(tp == 0)
                    424:                        panic("adaptec%d: no target for ccb #%lux\n", 0, paddr);
                    425:                *l = tp->active;
                    426: 
                    427:                ctlr->mbix->cmd = 0;
                    428: 
                    429:                tp->done = 1;
                    430:                wakeup(tp);
                    431: 
                    432:                ctlr->mbix++;
                    433:                if(ctlr->mbix >= &ctlr->mb[NTarget+NTarget])
                    434:                        ctlr->mbix = &ctlr->mb[NTarget];
                    435:        }
                    436: 
                    437:        if(active.machs > 1)
                    438:                unlock(ctlr);
                    439: }
                    440: 
                    441: static void
                    442: reset(Ctlr *ctlr)
                    443: {
                    444:        ulong paddr;
                    445:        int i;
                    446: 
                    447:        /*
                    448:         * Initialise the software controller and set the board
                    449:         * scanning the mailboxes.
                    450:         * Need code here to tidy things up if we're
                    451:         * resetting after being active.
                    452:         */
                    453:        for(i = 0; i < NTarget; i++){
                    454:                ctlr->target[i].paddr = PADDR(&ctlr->target[i].ccb);
                    455:                ctlr->mbox = ctlr->mb;
                    456:                ctlr->mbix = &ctlr->mb[NTarget];
                    457:        }
                    458: 
                    459:        ctlr->cmd[0] = Cmbinit;
                    460:        paddr = PADDR(ctlr->mb);
                    461:        ctlr->cmd[1] = NTarget;
                    462:        ctlr->cmd[2] = (paddr>>16) & 0xFF;
                    463:        ctlr->cmd[3] = (paddr>>8) & 0xFF;
                    464:        ctlr->cmd[4] = paddr & 0xFF;
                    465:        ctlr->cmdlen = 5;
                    466:        ctlr->datalen = 0;
                    467:        issue(ctlr);
                    468: }
                    469: 
                    470: static ISAConf aha1542 = {
                    471:        "aha1542",
                    472:        Port,
                    473:        Irq,
                    474:        0,
                    475:        0,
                    476: };
                    477: 
                    478: int (*
                    479: aha1542reset(void))(Scsi*, int)
                    480: {
                    481:        ISAConf *isa = &aha1542;
                    482:        Ctlr *ctlr;
                    483:        ulong s;
                    484:        uchar rif, rs;
                    485:        int dma, irq;
                    486: 
                    487:        /*
                    488:         * See if we have any configuration info.
                    489:         * Only one controller for now.
                    490:         */
                    491:        if(isaconfig("scsi", 0, &aha1542) == 0)
                    492:                return 0;
                    493:        ctlr = &softctlr[0];
                    494:        memset(ctlr, 0, sizeof(Ctlr));
                    495:        ctlr->port = isa->port;
                    496: 
                    497:        /*
                    498:         * Attempt to hard-reset the board and reset
                    499:         * the SCSI bus. If the board state doesn't settle to
                    500:         * idle with mailbox initialisation required, either
                    501:         * it isn't an Adaptec or it's broken.
                    502:         * The 154[02]C has an extra I/O port we could use for
                    503:         * identification, but that wouldn't work on the B.
                    504:         */
                    505:        outb(ctlr->port+Rc, Hrst|Scrst);
                    506:        delay(500);
                    507:        if(inb(ctlr->port+Rs) != (Init|Idle))
                    508:                return 0;
                    509: 
                    510:        /*
                    511:         * Get the DMA and IRQ info from the board. This will
                    512:         * cause an interrupt which we hope doesn't cause any
                    513:         * trouble because we don't know which one it is yet.
                    514:         * We have to do this to get the DMA info as it won't
                    515:         * be set up if the board has the BIOS disabled.
                    516:         */
                    517:        s = splhi();
                    518:        ctlr->cmd[0] = Cconfiguration;
                    519:        ctlr->cmdlen = 1;
                    520:        ctlr->datalen = 3;
                    521:        issue(ctlr);
                    522:        while(((rif = inb(ctlr->port+Rif)) & Hacc) == 0)
                    523:                ;
                    524:        
                    525:        rs = inb(ctlr->port+Rs);
                    526:        outb(ctlr->port+Rc, Irst);
                    527:        if((rif & Hacc) && (rs & Invdcmd)){
                    528:                splx(s);
                    529:                return 0;
                    530:        }
                    531:        splx(s);
                    532: 
                    533:        dma = -1;
                    534:        switch(ctlr->data[0]){                  /* DMA Arbitration Priority */
                    535: 
                    536:        case 0x80:                              /* Channel 7 */
                    537:                outb(0xD6, 0xC3);
                    538:                outb(0xD4, 0x03);
                    539:                dma = 7;
                    540:                break;
                    541: 
                    542:        case 0x40:                              /* Channel 6 */
                    543:                outb(0xD6, 0xC2);
                    544:                outb(0xD4, 0x02);
                    545:                dma = 6;
                    546:                break;
                    547: 
                    548:        case 0x20:                              /* Channel 5 */
                    549:                outb(0xD6, 0xC1);
                    550:                outb(0xD4, 0x01);
                    551:                dma = 5;
                    552:                break;
                    553: 
                    554:        case 0x01:                              /* Channel 0 */
                    555:                outb(0x0B, 0xC0);
                    556:                outb(0x0A, 0x00);
                    557:                dma = 0;
                    558:                break;
                    559: 
                    560:        default:
                    561:                /*
                    562:                 * This might be an EISA card (e.g. Buslogic 747)
                    563:                 * which doesn't have ISA DMA compatibility set
                    564:                 * so no DMA channel will show.
                    565:                 * Carry on regardless.
                    566:                print("adaptec%d: invalid DMA priority #%2.2ux\n", 0, ctlr->data[0]);
                    567:                return 0;
                    568:                 */
                    569:                break;
                    570:        }
                    571: 
                    572:        switch(ctlr->data[1]){                  /* Interrupt Channel */
                    573: 
                    574:        case 0x40:
                    575:                irq = 15;
                    576:                break;
                    577: 
                    578:        case 0x20:
                    579:                irq = 14;
                    580:                break;
                    581: 
                    582:        case 0x08:
                    583:                irq = 12;
                    584:                break;
                    585: 
                    586:        case 0x04:
                    587:                irq = 11;
                    588:                break;
                    589: 
                    590:        case 0x02:
                    591:                irq = 10;
                    592:                break;
                    593: 
                    594:        case 0x01:
                    595:                irq = 9;
                    596:                break;
                    597: 
                    598:        default:
                    599:                print("scsi%d: %s: invalid irq #%2.2ux\n",
                    600:                        0, isa->type, ctlr->data[1]);
                    601:                return 0;
                    602:        }
                    603: 
                    604:        setvec(Int0vec+irq, interrupt, 0);
                    605:        ctlr->id = ctlr->data[2] & 0x07;
                    606:        reset(ctlr);
                    607: 
                    608:        print("scsi%d: %s: port %lux irq %d, dma %d\n",
                    609:                0, isa->type, ctlr->port, irq, dma);
                    610: 
                    611:        return aha1542exec;
                    612: }

unix.superglobalmegacorp.com

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