Annotation of lucent/sys/src/9/gnot/scsi.c, revision 1.1

1.1     ! root        1: #include       "u.h"
        !             2: #include       "../port/lib.h"
        !             3: #include       "mem.h"
        !             4: #include       "dat.h"
        !             5: #include       "fns.h"
        !             6: #include       "../port/error.h"
        !             7: #include       "devtab.h"
        !             8: #include       "io.h"
        !             9: 
        !            10: int    scsiintr(void);
        !            11: 
        !            12: #define        DPRINT  if(debug)kprint
        !            13: 
        !            14: int    scsidebugs[8];
        !            15: int    scsiownid = 0x08|7; /* enable advanced features */
        !            16: 
        !            17: Scsibuf *
        !            18: scsialloc(ulong n)
        !            19: {
        !            20:        Scsibuf *b;
        !            21: 
        !            22:        b = xalloc(sizeof(Scsibuf));
        !            23:        b->virt = b->phys = xalloc(n);
        !            24:        return b;
        !            25: }
        !            26: 
        !            27: typedef struct Scsictl {
        !            28:        uchar   asr;
        !            29:        uchar   data;
        !            30:        uchar   stat;
        !            31:        uchar   dma;
        !            32: } Scsictl;
        !            33: 
        !            34: #define        Scsiaddr        48
        !            35: #define        DEV     ((Scsictl *)&PORT[Scsiaddr])
        !            36: 
        !            37: static long    poot;
        !            38: #define        WAIT    (poot=0, poot==0?0:poot)
        !            39: 
        !            40: #define        PUT(a,d)        (DEV->asr=(a), WAIT, DEV->data=(d))
        !            41: #define        GET(a)          (DEV->asr=(a), WAIT, DEV->data)
        !            42: 
        !            43: enum Int_status {
        !            44:        Inten = 0x01, Scsirst = 0x02,
        !            45:        INTRQ = 0x01, DMA = 0x02,
        !            46: };
        !            47: 
        !            48: enum SBIC_regs {
        !            49:        Own_id=0x00, Control=0x01, CDB=0x03, Target_LUN=0x0f,
        !            50:        Cmd_phase=0x10, Tc_hi=0x12,
        !            51:        Dest_id=0x15, Src_id=0x16, SCSI_Status=0x17,
        !            52:        Cmd=0x18, Data=0x19,
        !            53: };
        !            54: 
        !            55: enum Commands {
        !            56:        Reset = 0x00,
        !            57:        Assert_ATN = 0x02,
        !            58:        Negate_ACK = 0x03,
        !            59:        Select_with_ATN = 0x06,
        !            60:        Select_with_ATN_and_Xfr = 0x08,
        !            61:        Select_and_Xfr = 0x09,
        !            62:        Transfer_Info = 0x20,
        !            63:        SBT = 0x80,             /* modifier for single-byte transfer */
        !            64: };
        !            65: 
        !            66: enum Aux_status {
        !            67:        INT=0x80, LCI=0x40, BSY=0x20, CIP=0x10,
        !            68:        PE=0x02, DBR=0x01,
        !            69: };
        !            70: 
        !            71: static int     isscsi;
        !            72: static QLock   scsilock;
        !            73: static Rendez  scsirendez;
        !            74: static uchar * datap;
        !            75: static uchar * datalim;
        !            76: static long    debug, scsirflag, scsibusy, scsiinservice;
        !            77: 
        !            78: static void
        !            79: nop(void)
        !            80: {}
        !            81: 
        !            82: void
        !            83: resetscsi(void)
        !            84: {
        !            85:        static int inited;
        !            86: 
        !            87:        if(!inited)
        !            88:                addportintr(scsiintr);
        !            89:        inited = 1;
        !            90: }
        !            91: 
        !            92: void
        !            93: initscsi(void)
        !            94: {
        !            95:        isscsi = portprobe("scsi", -1, Scsiaddr, -1, 0L);
        !            96:        if (isscsi >= 0) {
        !            97:                DEV->stat = Scsirst;
        !            98:                delay(100);
        !            99:                DEV->stat = Inten;
        !           100:                while (DEV->stat & (INTRQ|DMA))
        !           101:                        nop();
        !           102:                scsiownid &= 0x0f; /* possibly advanced features */
        !           103:                scsiownid |= 0x80; /* 16MHz */
        !           104:                PUT(Own_id, scsiownid);
        !           105:                PUT(Cmd, Reset);
        !           106:        }
        !           107: }
        !           108: 
        !           109: static int
        !           110: scsidone(void *arg)
        !           111: {
        !           112:        USED(arg);
        !           113:        return (scsibusy == 0);
        !           114: }
        !           115: 
        !           116: int
        !           117: scsiexec(Scsi *p, int rflag)
        !           118: {
        !           119:        long n;
        !           120: 
        !           121:        debug = scsidebugs[p->target&7];
        !           122:        DPRINT("scsi %d.%d %2.2ux ", p->target, p->lun, *(p->cmd.ptr));
        !           123:        qlock(&scsilock);
        !           124:        scsirflag = rflag;
        !           125:        p->rflag = rflag;
        !           126:        datap = p->data.base;
        !           127:        datalim = p->data.lim;
        !           128:        if ((scsiownid & 0x08) && rflag)
        !           129:                PUT(Dest_id, 0x40|p->target);
        !           130:        else
        !           131:                PUT(Dest_id, p->target);
        !           132:        PUT(Target_LUN, p->lun);
        !           133:        n = p->data.lim - p->data.base;
        !           134:        PUT(Tc_hi, n>>16);
        !           135:        DEV->data = n>>8;
        !           136:        DEV->data = n;
        !           137:        if (scsiownid & 0x08) {
        !           138:                n = p->cmd.lim - p->cmd.ptr;
        !           139:                DPRINT("len=%d ", n);
        !           140:                PUT(Own_id, n);
        !           141:        }
        !           142:        PUT(CDB, *(p->cmd.ptr)++);
        !           143:        while (p->cmd.ptr < p->cmd.lim)
        !           144:                DEV->data = *(p->cmd.ptr)++;
        !           145:        scsibusy = 1;
        !           146:        PUT(Cmd, Select_and_Xfr);
        !           147:        /*PUT(Cmd, Select_with_ATN_and_Xfr);*/
        !           148:        while(waserror())
        !           149:                ;
        !           150:        DPRINT("S<");
        !           151:        sleep(&scsirendez, scsidone, 0);
        !           152:        DPRINT(">\n");
        !           153:        p->data.ptr = datap;
        !           154:        p->status = GET(Target_LUN);
        !           155:        p->status |= DEV->data<<8;
        !           156:        poperror();
        !           157:        qunlock(&scsilock);
        !           158:        debug = 0;
        !           159:        return p->status;
        !           160: }
        !           161: 
        !           162: void
        !           163: scsirun(void)
        !           164: {
        !           165:        wakeup(&scsirendez);
        !           166:        scsibusy = 0;
        !           167: }
        !           168: 
        !           169: void
        !           170: scsireset0(void)
        !           171: {
        !           172: /*     PUT(Control, 0x29);     /* burst DMA, halt on parity error */
        !           173:        PUT(Control, 0x28);     /* burst DMA, allow parity errors */
        !           174:        PUT(Control+1, 0xff);   /* timeout */
        !           175:        PUT(Src_id, 0x80);      /* enable reselection */
        !           176:        scsirun();
        !           177:        /*qunlock(&scsilock);*/
        !           178: }
        !           179: 
        !           180: int
        !           181: scsiintr(void)
        !           182: {
        !           183:        int status, s;
        !           184: 
        !           185:        if(isscsi < 0 || scsiinservice
        !           186:                || !((status = DEV->stat) & (DMA|INTRQ)))
        !           187:                        return 0;
        !           188:        DEV->stat = 0;
        !           189:        scsiinservice = 1;
        !           190:        s = spl1();
        !           191:        DPRINT("i%x ", status);
        !           192:        do{
        !           193:                if (status & DMA)
        !           194:                        scsidmaintr();
        !           195:                if (status & INTRQ)
        !           196:                        scsictrlintr();
        !           197:        }while ((status = DEV->stat) & (DMA|INTRQ));
        !           198:        splx(s);
        !           199:        scsiinservice = 0;
        !           200:        DEV->stat = Inten;
        !           201:        return 1;
        !           202: }
        !           203: 
        !           204: void
        !           205: scsidmaintr(void)
        !           206: {
        !           207:        uchar *p = 0;
        !           208: /*
        !           209:  *     if (scsirflag) {
        !           210:  *             unsigned char *p;
        !           211:  *             DPRINT("R", p=datap);
        !           212:  *             do
        !           213:  *                     *datap++ = DEV->dma;
        !           214:  *             while (DEV->stat & DMA);
        !           215:  *             DPRINT("%d ", datap-p);
        !           216:  *     } else {
        !           217:  *             unsigned char *p;
        !           218:  *             DPRINT("W", p=datap);
        !           219:  *             do
        !           220:  *                     DEV->dma = *datap++;
        !           221:  *             while (DEV->stat & DMA);
        !           222:  *             DPRINT("%d ", datap-p);
        !           223:  *     }
        !           224:  */
        !           225:        if(scsirflag){
        !           226:                DPRINT("R", p=datap);
        !           227:                datap = scsirecv(datap);
        !           228:                DPRINT("%d ", datap-p);
        !           229:        }else{
        !           230:                DPRINT("X", p=datap);
        !           231:                datap = scsixmit(datap);
        !           232:                DPRINT("%d ", datap-p);
        !           233:        }
        !           234: }
        !           235: 
        !           236: void
        !           237: scsictrlintr(void)
        !           238: {
        !           239:        int status, phase;
        !           240:        long n;
        !           241: 
        !           242:        status = GET(SCSI_Status);
        !           243:        DPRINT("I%2.2x ", status);
        !           244:        switch(status){
        !           245:        case 0x00:                      /* reset by command or power-up */
        !           246:        case 0x01:                      /* reset by command or power-up */
        !           247:                scsireset0();
        !           248:                break;
        !           249:        case 0x21:                      /* Save Data Pointers message received */
        !           250:                n = GET(Tc_hi);
        !           251:                n = (n<<8)|DEV->data;
        !           252:                n = (n<<8)|DEV->data;
        !           253:                datap = datalim - n;
        !           254:                PUT(Cmd_phase, 0x41);
        !           255:                PUT(Cmd, Select_and_Xfr);
        !           256:                break;
        !           257:        case 0x16:                      /* select-and-transfer completed */
        !           258:        case 0x42:                      /* timeout during select */
        !           259:                scsirun();
        !           260:                break;
        !           261:        case 0x4b:                      /* unexpected status phase */
        !           262:                DEV->asr = Target_LUN;
        !           263:                kprint("lun/status 0x%ux\n", DEV->data);
        !           264:                phase = DEV->data;
        !           265:                kprint("phase 0x%ux\n", phase);
        !           266:                PUT(Tc_hi, 0);
        !           267:                DEV->data = 0;
        !           268:                DEV->data = 0;
        !           269:                switch(phase){
        !           270:                case 0x50:
        !           271:                case 0x60:
        !           272:                        break;
        !           273:                default:
        !           274:                        phase = 0x46;
        !           275:                        break;
        !           276:                }
        !           277:                PUT(Cmd_phase, phase);
        !           278:                PUT(Cmd, Select_and_Xfr);
        !           279:                break;
        !           280:        default:
        !           281:                kprint("scsintr 0x%ux\n", status);
        !           282:                DEV->asr = Target_LUN;
        !           283:                kprint("lun/status 0x%ux\n", DEV->data);
        !           284:                kprint("phase 0x%ux\n", DEV->data);
        !           285:                switch (status&0xf0) {
        !           286:                case 0x00:
        !           287:                case 0x10:
        !           288:                case 0x20:
        !           289:                case 0x40:
        !           290:                case 0x80:
        !           291:                        if(status & 0x08){
        !           292:                                kprint("count 0x%ux", GET(Tc_hi));
        !           293:                                kprint(" 0x%ux", DEV->data);
        !           294:                                kprint(" 0x%ux\n", DEV->data);
        !           295:                        }
        !           296:                        scsirun();
        !           297:                        break;
        !           298:                default:
        !           299:                        panic("scsi status 0x%2.2ux", status);
        !           300:                }
        !           301:                kprint("resetting...");
        !           302:                PUT(Own_id, scsiownid);
        !           303:                PUT(Cmd, Reset);
        !           304:                break;
        !           305:        }
        !           306: }

unix.superglobalmegacorp.com

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