Annotation of lucent/sys/src/9/gnot/scsi.c, revision 1.1.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.