Annotation of lucent/sys/src/9/pc/adaptec.c, revision 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.