Annotation of lucent/sys/src/boot/pc/scsi1542.c, revision 1.1

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

unix.superglobalmegacorp.com

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