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

1.1     ! root        1: /*
        !             2:  * Ultrastor [13]4f SCSI Host Adapter.
        !             3:  * Originally written by Charles Forsyth, [email protected].
        !             4:  * Needs work:
        !             5:  *     handle multiple controllers;
        !             6:  *     set options from user-level;
        !             7:  *     split out to handle adaptec too;
        !             8:  */
        !             9: #include "u.h"
        !            10: #include "lib.h"
        !            11: #include "mem.h"
        !            12: #include "dat.h"
        !            13: #include "fns.h"
        !            14: #include "io.h"
        !            15: 
        !            16: typedef struct Ctlr Ctlr;
        !            17: typedef struct Mailbox Mailbox;
        !            18: typedef struct Scatter Scatter;
        !            19: 
        !            20: enum {
        !            21:        Nctl            = 1,            /* only support one */
        !            22:        Nmbox           = 8,            /* number of Mailboxes; up to 16? */
        !            23:        Nscatter        = 33,           /* s/g list limit fixed by Ultrastor controller */
        !            24:        Timeout         = 10,           /* seconds to wait for things to complete */
        !            25: 
        !            26:        Port            = 0x330,        /* factory defaults: I/O port */
        !            27:        CtlrID          = 7,            /*      adapter SCSI id */
        !            28:        Irq             = 14,           /*      interrupt request level */
        !            29: };
        !            30: 
        !            31: struct Scatter {
        !            32:        ulong   start;  /* physical address; Intel byte order */
        !            33:        ulong   len;    /* length in bytes; Intel byte order */
        !            34: };
        !            35: 
        !            36: /*
        !            37:  * Ultrastor mailbox pointers point to one of these structures
        !            38:  */
        !            39: struct Mailbox {
        !            40:        uchar   op;             /* Adapter operation */
        !            41:        uchar   addr;           /* lun, chan, scsi ID */
        !            42:        uchar   datap[4];       /* transfer data phys. pointer */
        !            43:        uchar   datalen[4];     /* transfer data length */
        !            44:        uchar   cmdlink[4];     /* command link phys. pointer */
        !            45:        uchar   linkid;         /* SCSI command link ID */
        !            46:        uchar   nscatter;       /* scatter/gather length (8 bytes per entry) */
        !            47:        uchar   senselen;       /* length of sense data */
        !            48:        uchar   cmdlen;         /* length of CDB */
        !            49:        uchar   cmd[12];        /* SCSI command */
        !            50:        uchar   adapterstatus;
        !            51:        uchar   targetstatus;
        !            52:        uchar   sensep[4];      /* sense data phys. pointer */
        !            53: 
        !            54:        /* the remainder is used by software, not the device */
        !            55:        uchar   sensedata[64];  /* enough for AdapterInquiry data too */
        !            56:        int     busy;           /* interrupt pending */
        !            57:        ulong   physaddr;       /* physical address of this Mailbox */
        !            58:        int     p9status;       /* p9 status value */
        !            59:        Mailbox *next;          /* next Mailbox in free list */
        !            60: };
        !            61: 
        !            62: /* pack pointer as Intel order bytes (can simply assign) */
        !            63: #define        PL(buf,p)       (*(ulong*)(buf)=(ulong)(p))
        !            64: 
        !            65: enum {
        !            66:                                        /* bits in Mailbox.op[0] */
        !            67:                                        /* 3 bit opcode */
        !            68:        OpAdapter       = 0x01,         /* adapter command, not SCSI command */
        !            69:        OpTarget        = 0x02,         /* SCSI command for device */
        !            70:        OpReset         = 0x04,         /* device reset */
        !            71:                                        /* 2 bit transfer direction */
        !            72:        CmdDirection    = 0<<3,         /* transfer direction determined by SCSI command */
        !            73:        DataIn          = 1<<3,         /* SCSI Data In */
        !            74:        DataOut         = 2<<3,         /* SCSI Data Out */
        !            75:        NoTransfer      = 3<<3,
        !            76:        Nodiscon=       1<<5,           /* disable disconnect */
        !            77:        Usecache=       1<<6,           /* use adapter cache (if available) */
        !            78:        Scattered=      1<<7,           /* transfer pointer refers to S/G list */
        !            79: 
        !            80:                                        /* OpAdapter commands in Mailbox.cmd[0] */
        !            81:        AdapterInquiry  = 0x01,
        !            82:        AdapterSelftest = 0x02,
        !            83:        AdapterRead     = 0x03,         /* read adapter's buffer */
        !            84:        AdapterWrite    = 0x04,         /* write to adapter's buffer */
        !            85: 
        !            86:                                        /* IO port offsets and bits */
        !            87:        AdapterMask     = 0x00,         /* local doorbell mask register */
        !            88:          OGMIntEnable  = 0x01,
        !            89:          SoftResetEnable = 0x40,
        !            90:          AdapterReady  = 0xe1,         /* adapter ready for work when all these set */
        !            91:        AdapterIntr     = 0x01,         /* adapter interrupt/status; set by host, reset by adapter */
        !            92:          SignalAdapter = 0x01,         /* tell adapter to read OGMpointer */
        !            93:          BusReset      = 0x20,         /* SCSI Bus Reset */
        !            94:          SoftReset     = 0x40,         /* Adapter Soft Reset */
        !            95:        HostMask        = 0x02,         /* host doorbell mask register */
        !            96:          ICMIntEnable  = 0x01,         /* incoming mail enable */
        !            97:          SIntEnable    = 0x80,         /* enable interrupt from HostIntr reg */
        !            98:        HostIntr        = 0x03,         /* host doorbell interrupt/status; set by adapter, reset by host */
        !            99:          IntPending    = 0x80,         /* interrupt pending for host */
        !           100:          SignalHost    = 0x01,         /* Incoming Mail Interrupt */
        !           101:        ProductID       = 0x04,         /* two byte product ID */
        !           102:        Config1         = 0x06,
        !           103:        Config2         = 0x07,
        !           104:        OGMpointer      = 0x08,         /* pointer to Outgoing Mail */
        !           105:        ICMpointer      = 0x0c,         /* pointer to Incoming Mail */
        !           106: };
        !           107: 
        !           108: #define        OUT(c,v) outb(ctlr->io+(c), (v))
        !           109: #define        IN(c)   inb(ctlr->io+(c))
        !           110: 
        !           111: struct Ctlr {
        !           112:        int     io;             /* io port */
        !           113:        int     irq;            /* interrupt vector */
        !           114:        int     dma;            /* DMA channel */
        !           115:        int     ownid;          /* adapter's SCSI ID */
        !           116:        Mailbox mbox[Nmbox];
        !           117:        Mailbox *free;          /* next free Mailbox */
        !           118: };
        !           119: 
        !           120: static Ctlr    ultra[Nctl];
        !           121: 
        !           122: static void
        !           123: resetadapter(int busreset)
        !           124: {
        !           125:        Ctlr *ctlr = &ultra[0];
        !           126:        int i;
        !           127: 
        !           128:        if(IN(AdapterMask) & SoftResetEnable){
        !           129:                OUT(AdapterIntr, SoftReset|busreset);
        !           130:                for(i=50000; IN(AdapterIntr) & (SoftReset|busreset);)
        !           131:                        if(--i<0) {
        !           132:                                print("Ultrastor reset timed out\n");
        !           133:                                break;
        !           134:                        }
        !           135:        }
        !           136: }
        !           137: 
        !           138: static void
        !           139: freebox(Ctlr *ctlr, Mailbox *mbox)
        !           140: {
        !           141:        mbox->next = ctlr->free;
        !           142:        ctlr->free = mbox;
        !           143: }
        !           144: 
        !           145: static void
        !           146: ultra14fwait(Ctlr *ctlr, Mailbox *mbox)
        !           147: {
        !           148:        ulong start;
        !           149:        int x;
        !           150:        static void interrupt(Ureg*, void*);
        !           151: 
        !           152:        x = spllo();
        !           153:        start = m->ticks;
        !           154:        while(TK2SEC(m->ticks - start) < Timeout && mbox->busy)
        !           155:                ;
        !           156:        if(TK2SEC(m->ticks - start) >= Timeout){
        !           157:                print("ultra14fwait timed out\n");
        !           158:                interrupt(0, ctlr);
        !           159:        }
        !           160:        splx(x);
        !           161: }
        !           162: 
        !           163: static int
        !           164: ultra14fexec(Scsi *p, int rflag)
        !           165: {
        !           166:        Ctlr *ctlr = &ultra[0];
        !           167:        Mailbox *mbox;
        !           168:        long n;
        !           169:        uchar *cp;
        !           170:        ulong s;
        !           171: 
        !           172:        if (p == 0 || ctlr->io == 0)
        !           173:                return 0x6001;  /* device not available */
        !           174: 
        !           175:        /*
        !           176:         * get a free Mailbox and build an Ultrastor command
        !           177:         */
        !           178:        if((mbox = ctlr->free) == 0)
        !           179:                return 0x6001;
        !           180:        ctlr->free = mbox->next;
        !           181:        p->rflag = rflag;
        !           182:        mbox->p9status = 0;
        !           183:        mbox->op = OpTarget | CmdDirection | Usecache;  /* BUG? is it safe always to Usecache? */
        !           184:        mbox->addr = p->target | (p->lun<<5);
        !           185:        if(p->cmd.lim - p->cmd.ptr > sizeof(mbox->cmd))
        !           186:                panic("ultra14fexec");
        !           187:        mbox->cmdlen = p->cmd.lim - p->cmd.ptr;
        !           188:        for(cp = mbox->cmd; p->cmd.ptr < p->cmd.lim;)
        !           189:                *cp++ = *p->cmd.ptr++;
        !           190:        n = p->data.lim - p->data.ptr;
        !           191:        mbox->nscatter = 0;
        !           192:        PL(mbox->datap, PADDR(p->data.ptr));
        !           193:        PL(mbox->datalen, n);
        !           194:        mbox->adapterstatus = 0;
        !           195:        mbox->targetstatus = 0;
        !           196: 
        !           197:        /*
        !           198:         * send the command to the host adapter
        !           199:         */
        !           200:        s = splhi();
        !           201:        if(IN(AdapterIntr) & SignalAdapter)
        !           202:                panic("ultrastor busy");
        !           203:        mbox->busy = 1;
        !           204:        outl(ctlr->io+OGMpointer, mbox->physaddr);
        !           205:        OUT(AdapterIntr, SignalAdapter);
        !           206: 
        !           207:        /*
        !           208:         * wait for reply
        !           209:         */
        !           210:        splx(s);
        !           211:        ultra14fwait(ctlr, mbox);
        !           212: 
        !           213:        p->status = mbox->p9status;
        !           214:        if(p->status == 0x6000)
        !           215:                p->data.ptr = p->data.lim;      /* can only assume no residue */
        !           216:        freebox(ctlr, mbox);
        !           217:        return p->status;
        !           218: }
        !           219: 
        !           220: static void
        !           221: scsimoan(char *msg, Mailbox *mbox)
        !           222: {
        !           223:        /*int i;*/
        !           224: 
        !           225:        print("SCSI error: %s:", msg);
        !           226:        print("id=%d cmd=%2.2x status=%2.2x adapter=%2.2x",
        !           227:                mbox->addr&7, mbox->cmd[0], mbox->targetstatus, mbox->adapterstatus);
        !           228:        /*print(" sense:");
        !           229:        for(i=0; i<10; i++)
        !           230:                print(" %2.2x", mbox->sensedata[i]);*/
        !           231:        print("\n");
        !           232: }
        !           233: 
        !           234: static void
        !           235: interrupt(Ureg*, void *arg)
        !           236: {
        !           237:        Ctlr *ctlr;
        !           238:        Mailbox *mbox;
        !           239:        ulong pa;
        !           240: 
        !           241:        ctlr = arg;
        !           242: 
        !           243:        if((IN(HostIntr) & SignalHost) == 0)
        !           244:                return; /* no incoming mail */
        !           245:        pa = inl(ctlr->io+ICMpointer);
        !           246:        OUT(HostIntr, SignalHost);      /* release ICM slot */
        !           247:        for(mbox = &ctlr->mbox[0]; mbox->physaddr != pa;)
        !           248:                if(++mbox >= &ctlr->mbox[Nmbox]) {
        !           249:                        /* these sometimes happen in response to a scsi bus reset; ignore them */
        !           250:                        print("ultrastor: invalid ICM pointer #%lux\n", pa);
        !           251:                        return;
        !           252:                }
        !           253: 
        !           254:        mbox->p9status = 0x1000 | mbox->adapterstatus;
        !           255:        switch(mbox->adapterstatus){
        !           256:        default:
        !           257:                scsimoan("adapter", mbox);
        !           258:                if(mbox->adapterstatus >= 0x92) /* ie, scsi command protocol error */
        !           259:                        resetadapter(BusReset);
        !           260:                /* might adapter reset be required in other cases? */
        !           261:                break;
        !           262: 
        !           263:        case 0x91:      /* selection timed out */
        !           264:                mbox->p9status = 0x20;
        !           265:                break;
        !           266: 
        !           267:        case 0xA3:
        !           268:                scsimoan("SCSI bus reset error", mbox);
        !           269:                break;
        !           270: 
        !           271:        case 0x00:
        !           272:                mbox->p9status = 0x6000 | mbox->targetstatus;
        !           273:                break;
        !           274:        }
        !           275:        mbox->busy = 0;
        !           276: }
        !           277: 
        !           278: static int irq[4] = {
        !           279:        15, 14, 11, 10,
        !           280: };
        !           281: 
        !           282: int (*
        !           283: ultra14freset(void))(Scsi*, int)
        !           284: {
        !           285:        Ctlr *ctlr = &ultra[0];
        !           286:        Mailbox *mbox;
        !           287:        int i, model;
        !           288: 
        !           289:        /*
        !           290:         * Check it is an Ultrastor [13]4f.
        !           291:         * Only one controller for now.
        !           292:         * For the moment assume the factory default settings.
        !           293:         */
        !           294:        memset(ctlr, 0, sizeof(Ctlr));
        !           295:        ctlr->io = Port;
        !           296: 
        !           297:        if(IN(ProductID) != 0x56)
        !           298:                return 0;
        !           299:        model = IN(ProductID+1);
        !           300:        switch(model){
        !           301: 
        !           302:        case 0x40:
        !           303:                model = 14;
        !           304:                break;
        !           305: 
        !           306:        case 0x41:
        !           307:                model = 34;
        !           308:                break;
        !           309: 
        !           310:        default:
        !           311:                return 0;
        !           312:        }
        !           313: 
        !           314:        i = IN(Config1);
        !           315:        ctlr->irq = irq[((i>>4)&03)];
        !           316:        if(model == 14)
        !           317:                ctlr->dma = 5 + ((i>>6)&03);
        !           318:        ctlr->ownid = IN(Config2)&07;
        !           319:        /*print("Ultrastor %dF id %d io 0x%x irq %d dma %d\n",
        !           320:                model, ctlr->ownid, ctlr->io, ctlr->irq, ctlr->dma);*/
        !           321: 
        !           322:        /*
        !           323:         * set the DMA controller to cascade mode for bus master
        !           324:         */
        !           325:        switch(ctlr->dma){
        !           326:        case 5:
        !           327:                outb(0xd6, 0xc1); outb(0xd4, 1); break;
        !           328:        case 6:
        !           329:                outb(0xd6, 0xc2); outb(0xd4, 2); break;
        !           330:        case 7:
        !           331:                outb(0xd6, 0xc3); outb(0xd4, 3); break;
        !           332:        }
        !           333: 
        !           334:        resetadapter(0);
        !           335:        ctlr->free = 0;
        !           336:        for(i=0; i<Nmbox; i++){
        !           337:                mbox = &ctlr->mbox[i];
        !           338:                memset(mbox, 0, sizeof(*mbox));
        !           339:                mbox->physaddr = PADDR(mbox);
        !           340:                PL(mbox->sensep, 0);    /* DON'T collect sense data automatically: messes up scuzz? */
        !           341:                mbox->senselen = 0;
        !           342:                mbox->next = ctlr->free;
        !           343:                ctlr->free = mbox;
        !           344:        }
        !           345: 
        !           346:        setvec(Int0vec+ctlr->irq, interrupt, ctlr);
        !           347: 
        !           348:        /*
        !           349:         * issue AdapterInquiry command to check it's alive
        !           350:         * -- could check enquiry data
        !           351:         */
        !           352:        OUT(HostMask, 0);       /* mask interrupts */
        !           353:        mbox = &ctlr->mbox[0];
        !           354:        mbox->op = OpAdapter | CmdDirection;
        !           355:        mbox->addr = ctlr->ownid;
        !           356:        mbox->cmdlen = 1;
        !           357:        mbox->cmd[0] = AdapterInquiry;
        !           358:        PL(mbox->datap, PADDR(mbox->sensedata));
        !           359:        PL(mbox->datalen, 38);
        !           360:        while(IN(AdapterIntr) & SignalAdapter)
        !           361:                ;
        !           362:        outl(ctlr->io+OGMpointer, mbox->physaddr);
        !           363:        OUT(AdapterIntr, SignalAdapter);
        !           364:        for(i=100000; (IN(HostIntr)&SignalHost)==0;)
        !           365:                if(--i < 0){
        !           366:                        print("No response to UltraStor Inquiry\n");
        !           367:                        ctlr->io = 0;
        !           368:                        return 0;
        !           369:                }
        !           370:        OUT(HostIntr, SignalHost);
        !           371: 
        !           372:        OUT(HostMask, ICMIntEnable|SIntEnable);
        !           373: 
        !           374:        return ultra14fexec;
        !           375: }

unix.superglobalmegacorp.com

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