Annotation of researchv10no/sys/io/nscsi.c, revision 1.1.1.1

1.1       root        1: /*
                      2:        SCSI Pass-Thru driver for the TD Systems UD? -- Andrew Hume
                      3:        Ninth Edition Unix
                      4: */
                      5: 
                      6: #include "sys/param.h"
                      7: #include "sys/user.h"
                      8: #include "sys/buf.h"
                      9: #include "sys/systm.h"
                     10: #include "sys/pte.h"
                     11: #include "sys/map.h"
                     12: #include "sys/ubaddr.h"
                     13: #include "sys/conf.h"
                     14: 
                     15: #include       "sys/uda.h"
                     16: #include       "sys/mscp.h"
                     17: 
                     18: #include "sys/scsi.h"
                     19: #include       <scsi.h>
                     20: 
                     21: #define        mscp_scsi       m_fmt
                     22: 
                     23: struct udadevice {
                     24:        short   udaip;          /* initialization and polling */
                     25:        short   udasa;          /* status and address */
                     26: };
                     27: #define        UDA_ERR         0100000 /* error bit */
                     28: #define        UDA_STEP4       0040000 /* step 4 has started */
                     29: #define        UDA_STEP3       0020000 /* step 3 has started */
                     30: #define        UDA_STEP2       0010000 /* step 2 has started */
                     31: #define        UDA_STEP1       0004000 /* step 1 has started */
                     32: #define        UDA_GO          0000001 /* start operation, after init */
                     33: 
                     34: #define        UDA_OWN         0x80000000      /* UDA owns this descriptor */
                     35: #define        UDA_INT         0x40000000      /* allow interrupt on ring transition */
                     36: 
                     37: #define WAITPRI        (PZERO+1)
                     38: #define        SCSILTMT        300             /* long timeout in seconds */
                     39: #define        SCSISTMT        10              /* short timeout in seconds */
                     40: #define        ERROR           0x8000          /* in csr */
                     41: #define        SCSIINTR        0700
                     42: #define        SETDSC(dsc, fl) dsc = (dsc&~(UDA_OWN|UDA_INT))|fl
                     43: 
                     44: static memset(p, c, n)
                     45:        register char *p, c;
                     46:        register n;
                     47: {
                     48:        while(n-- > 0)
                     49:                *p++ = c;
                     50: }
                     51: 
                     52: int scsiopen(), scsiclose(), scsiread(), scsiwrite();
                     53: 
                     54: extern struct scsi scsi[];
                     55: extern struct ubaddr scsiaddr[];
                     56: extern int scsicnt;
                     57: struct cdevsw scsicdev =
                     58:        cdinit(scsiopen, scsiclose, scsiread, scsiwrite, nodev);
                     59: int scsi_dbg = 0;
                     60: 
                     61: scsiopen(dev)
                     62:        dev_t dev;
                     63: {
                     64:        register struct scsi *p;
                     65: 
                     66:        if((dev = minor(dev)) >= scsicnt) {
                     67:                u.u_error = ENODEV;
                     68:                return;
                     69:        }
                     70:        if((p = &scsi[dev])->flag&OPEN) {
                     71:                u.u_error = EBUSY;
                     72:                return;
                     73:        }
                     74:        if(((p->addr = (struct udadevice *)ubaddr(&scsiaddr[dev])) == 0)
                     75:          || ubbadaddr(scsiaddr[dev].ubno, (caddr_t)p->addr, sizeof(u_short))) {
                     76:                printf("scsi%d absent\n", dev);
                     77:                u.u_error = ENODEV;
                     78:                return;
                     79:        }
                     80:        if((p->flag&USED) == 0)
                     81:                if(scsistart(dev))
                     82:                        return;
                     83:        p->flag = USED|OPEN|NEXTWR|DONE;
                     84: }
                     85: 
                     86: scsistart(dev)
                     87:        dev_t dev;
                     88: {
                     89:        register struct scsi *p = &scsi[minor(dev)];
                     90: 
                     91:        p->flag |= DONE;
                     92:        p->b1 = geteblk();
                     93:        p->b1->b_bcount = BUFSIZE;
                     94:        p->b1->b_flags = B_BUSY;
                     95:        clrbuf(p->b1);
                     96:        p->ub1 = ubmbuf(scsiaddr[minor(dev)].ubno, p->b1, USLP);
                     97:        p->u1 = ubadbuf(scsiaddr[minor(dev)].ubno, p->b1, p->ub1);
                     98:        p->data = (unsigned char *)p->b1->b_un.b_addr;
                     99:        p->b2 = geteblk();
                    100:        p->b2->b_bcount = BUFSIZE;
                    101:        p->b2->b_flags = B_BUSY;
                    102:        clrbuf(p->b2);
                    103:        p->ub2 = ubmbuf(scsiaddr[minor(dev)].ubno, p->b2, USLP);
                    104:        p->u2 = ubadbuf(scsiaddr[minor(dev)].ubno, p->b2, p->ub2);
                    105:        p->junk = (struct bag *)p->b2->b_un.b_addr;
                    106:        p->timeout = SCSISTMT;
                    107:        if(scsiinit(dev) == 0){
                    108:                scsiclose(dev);
                    109:                p->flag = 0;
                    110:                u.u_error = ENXIO;
                    111:                return(1);
                    112:        }
                    113:        printf("scsi%d run\n", minor(dev));
                    114:        return(0);
                    115: }
                    116: 
                    117: scsiclose(dev)
                    118:        dev_t dev;
                    119: {
                    120:        register struct scsi *p = &scsi[minor(dev)];
                    121: 
                    122:        if((p->flag&DONE) == 0){        /* wait for I/O to complete */
                    123:                (void)tsleep((caddr_t)p, PZERO+1, p->timeout);
                    124:        }
                    125:        p->flag = USED;
                    126: }
                    127: 
                    128: scsiwrite(dev)
                    129:        dev_t dev;
                    130: {
                    131:        register count;
                    132:        register struct scsi *p = &scsi[minor(dev)];
                    133:        register struct mscmd *cmd = &p->junk->cmd.msg;
                    134:        unsigned char flag, bus_id;
                    135:        long readback;
                    136: 
                    137:        if(p->flag&NEXTWR)
                    138:                p->flag &= ~NEXTWR;
                    139:        else {
                    140:                u.u_error = EGREG;
                    141:                return;
                    142:        }
                    143:        if(copyin(u.u_base, &p->tran_id, 4) || copyin(u.u_base+4, &bus_id, 1)
                    144:                        || copyin(u.u_base+5, &flag, 1)
                    145:                        || copyin(u.u_base+6, &readback, 4)
                    146:                        || copyin(u.u_base+10, &cmd->mscp_scsi, SCSICMD)){
                    147:                u.u_error = EFAULT;
                    148:                return;
                    149:        }
                    150:        if(flag & SCSI_RESET){
                    151:                if(scsiinit(dev) == 0){
                    152:                        printf("scsi%d: reset failed\n", minor(dev));
                    153:                        p->flag = 0;
                    154:                        u.u_error = ENXIO;
                    155:                        return;
                    156:                }
                    157:                printf("scsi%d: reset\n", minor(dev));
                    158:                p->flag = USED|OPEN|NEXTWR|DONE;
                    159:                u.u_count = 0;
                    160:                return;
                    161:        }
                    162:        p->timeout = (flag&SCSI_LTMOUT)? SCSILTMT:SCSISTMT;
                    163:        count = u.u_count - (10+SCSICMD);
                    164:        u.u_base += 10+SCSICMD;
                    165:        if((count < 0) || (count > SCSIDATA)){
                    166:                u.u_error = EINVAL;
                    167:                return;
                    168:        }
                    169:        memset(p->data, 0xEE, BUFSIZE);
                    170:        if(flag&SCSI_RD){
                    171:                cmd->m__r1 = 0106;
                    172:                count = readback;
                    173:        } else if(flag&SCSI_WR){
                    174:                if(copyin(u.u_base, p->data, count)){
                    175:                        u.u_error = EFAULT;
                    176:                        return;
                    177:                }
                    178:                cmd->m__r1 = 0107;      
                    179:        } else {
                    180:                u.u_error = EINVAL;
                    181:                return;
                    182:        }
                    183:        cmd->m_opcd = (flag & SCSI_BRESET)? 0160 : 0130;
                    184:        if(scsi_dbg)
                    185:                printf("c=%d uc=%d, dir=0%o, bus_id=%d, new count=%d timeout=%d\n",
                    186:                        count, u.u_count, cmd->m__r1, bus_id, count, p->timeout);
                    187:        cmd->m_unit = bus_id;
                    188:        cmd->m_bcnt = count;
                    189:        cmd->m_fcnt = p->u1;
                    190:        p->flag = (p->flag&~DONE)|PEND;
                    191:        if(flag&SCSI_SENSE)
                    192:                p->flag |= ERRSNSE;
                    193:        p->junk->ca.ca_cmdint = 0;
                    194:        p->junk->ca.ca_rspint = 0;
                    195:        SETDSC(p->junk->ca.ca_cmddsc[0], UDA_OWN);
                    196:        bus_id = p->addr->udaip;        /* start controller */
                    197:        u.u_count = 0;
                    198: }
                    199: 
                    200: scsiread(dev)
                    201:        dev_t dev;
                    202: {
                    203:        register struct scsi *p = &scsi[minor(dev)];
                    204:        register count;
                    205: 
                    206:        if(p->flag&NEXTWR){
                    207:                u.u_error = EGREG;
                    208:                return;
                    209:        } else
                    210:                p->flag |= NEXTWR;
                    211:        if((p->flag&DONE) == 0){
                    212:                if(tsleep((caddr_t)p, PZERO+1, p->timeout) != TS_OK){
                    213:                        u.u_error = ENXIO;
                    214:                        return;
                    215:                }
                    216:        }
                    217:        if(p->sa&0x8000){
                    218:                printf("scsi%d: error sa=#%x\n", minor(dev), p->sa&0xFFFF);
                    219:                u.u_error = EIO;
                    220:                scsiinit(dev);
                    221:                return;
                    222:        }
                    223:        count = u.u_count - SCSIRET;
                    224:        if(count > p->junk->rsp.msg.m_bcnt)
                    225:                count = p->junk->rsp.msg.m_bcnt;
                    226:        if((count < 0) || (count > SCSIDATA)){
                    227:                u.u_error = EINVAL;
                    228:                return;
                    229:        }
                    230:        ((unsigned long *)p->status)[0] = p->tran_id;
                    231:        p->status[4] = p->junk->rsp.msg.m_fbbk;
                    232:        p->status[5] = p->junk->rsp.msg.m_fbbk>>8;
                    233:        p->status[6] = 0;       /* flags */
                    234:        p->status[7] = 1;       /* viking */
                    235:        ((short *)p->status)[4] = p->sa;
                    236:        ((short *)p->status)[5] = p->junk->rsp.msg.m_sts;
                    237:        if(copyout(p->status, u.u_base, SCSIRET)){
                    238:                u.u_error = EFAULT;
                    239:                return;
                    240:        }
                    241:        if(count)
                    242:                if(copyout(p->data, u.u_base+SCSIRET, count)){
                    243:                        u.u_error = EFAULT;
                    244:                        return;
                    245:                }
                    246:        if(p->junk->rsp.msg.m_sts){
                    247:                printf("scsi%d: stat=#%x\n", minor(dev), p->junk->rsp.msg.m_sts);
                    248:                u.u_error = (p->junk->rsp.msg.m_sts == 0x80a)? ESRCH : EIO;
                    249:                return;
                    250:        }
                    251:        u.u_count -= SCSIRET+count;
                    252:        SETDSC(p->junk->ca.ca_rspdsc[0], UDA_OWN|UDA_INT);
                    253: }
                    254: 
                    255: scsi0int(dev)
                    256:        dev_t dev;
                    257: {
                    258:        register struct scsi *p = &scsi[minor(dev)];
                    259:        register s;
                    260: 
                    261:        if((p->flag&PEND) == 0){
                    262:                printf("scsi%d: unexpected interrupt\n", minor(dev));
                    263:                return;
                    264:        }
                    265:        if(p->junk->ca.ca_rspint == 0){
                    266:                printf("scsi%d: rspint=0 cmdint=%d rsp=#%x cmd=#%x\n", minor(dev), p->junk->ca.ca_cmdint, p->junk->ca.ca_rspdsc[0], p->junk->ca.ca_cmddsc[0]);
                    267:                return;
                    268:        }
                    269:        p->sa = p->addr->udasa;
                    270:        s = spl6();
                    271:        p->flag = (p->flag&~PEND)|DONE;
                    272:        splx(s);
                    273:        wakeup((caddr_t)p);
                    274: }
                    275: 
                    276: /*
                    277:  * hardware initialization handshake
                    278:  * for simplicity, don't bother with init interrupts
                    279:  * returns nonzero if ok
                    280:  */
                    281: 
                    282: #define        UDA_STEPS       (UDA_ERR|UDA_STEP4|UDA_STEP3|UDA_STEP2|UDA_STEP1)
                    283: 
                    284: scsiinit(d)
                    285: int d;
                    286: {
                    287:        register struct scsi *p = &scsi[minor(d)];
                    288:        register struct udadevice *udaddr;
                    289:        register int i;
                    290:        time_t out;
                    291:        int s;
                    292: 
                    293:        udaddr = p->addr;
                    294:        out = time + 11;
                    295:        s = spl0();
                    296: printf("scsi1");
                    297:        udaddr->udaip = 0;
                    298:        while((udaddr->udasa & (UDA_ERR|UDA_STEP1)) == 0 && time <= out)
                    299:                ;
                    300:        if((udaddr->udasa & UDA_STEPS) != UDA_STEP1) {
                    301:                steperr("1", udaddr->udasa, d);
                    302:                splx(s);
                    303:                return (0);
                    304:        }
                    305:        udaddr->udasa = UDA_ERR|(SCSIINTR/4);
                    306:        /* no diagnostic wrap, no interrupts during initialization */
                    307: printf("2");
                    308:        out = time + 21;
                    309:        while((udaddr->udasa & (UDA_ERR|UDA_STEP2)) == 0 && time <= out)
                    310:                ;
                    311:        if((udaddr->udasa & UDA_STEPS) != UDA_STEP2) {
                    312:                steperr("2", udaddr->udasa, d);
                    313:                splx(s);
                    314:                return (0);
                    315:        }
                    316:        i = p->u2;      /* unibus address of bag */
                    317:        i += (long)&p->junk->ca.ca_rspdsc[0] - (long)p->junk;
                    318:        udaddr->udasa = (short)i;
                    319:        out = time + 11;
                    320: printf("3");
                    321:        while((udaddr->udasa & (UDA_ERR|UDA_STEP3)) == 0 && time <= out)
                    322:                ;
                    323:        if((udaddr->udasa & UDA_STEPS) != UDA_STEP3) {
                    324:                steperr("3", udaddr->udasa, d);
                    325:                splx(s);
                    326:                return (0);
                    327:        }
                    328:        udaddr->udasa = (i >> 16)&0x3F;
                    329:        out = time + 11;
                    330: printf("4");
                    331:        while((udaddr->udasa & (UDA_ERR|UDA_STEP4)) == 0 && time <= out)
                    332:                ;
                    333:        if((udaddr->udasa & UDA_STEPS) != UDA_STEP4) {
                    334:                steperr("4", udaddr->udasa, d);
                    335:                splx(s);
                    336:                return (0);
                    337:        }
                    338:        i = p->u2 + (long)&p->junk->rsp.msg.m_crf - (long)p->junk;
                    339:        p->junk->ca.ca_rspdsc[0] = UDA_OWN|UDA_INT|i;
                    340:        i = p->u2 + (long)&p->junk->cmd.msg.m_crf - (long)p->junk;
                    341:        p->junk->ca.ca_cmddsc[0] = i;
                    342:        if (udaddr->udasa & UDA_ERR) {
                    343:                steperr("5", udaddr->udasa, d);
                    344:                splx(s);
                    345:                return (0);
                    346:        }
                    347:        udaddr->udasa = UDA_GO;         /* finish init */
                    348:        /* finish cmd packet init */
                    349:        p->junk->cmd.msg_len = 44;
                    350:        p->junk->cmd.msg.m_crf = (long)p->junk;
                    351:        p->junk->cmd.msg.m_opcd = 0130;
                    352:        splx(s);
                    353: printf(" done\n");
                    354:        return (1);
                    355: }
                    356: 
                    357: steperr(str, sa, dev)
                    358:        char *str;
                    359: {
                    360:        printf("scsi%d: step%s error, sa=#%x\n", minor(dev), str, sa&0xFFFF);
                    361: }
                    362: 
                    363: /*
                    364:        dreck to figure out how much we should read back
                    365: */
                    366: 
                    367: scsilen(cmd)
                    368:        unsigned char *cmd;
                    369: {
                    370:        switch(cmd[0])
                    371:        {
                    372:        case 0x03:      return(cmd[4]);
                    373:        case 0x08:      return(cmd[4]*1024);
                    374:        case 0x12:      return(cmd[4]);
                    375:        case 0x1A:      return(cmd[4]);
                    376:        case 0x1C:      return(cmd[3]*256 + cmd[4]);
                    377:        case 0x25:      return(8);
                    378:        case 0x28:      return(1024*(256*cmd[7] + cmd[8]));
                    379:        case 0x2C:      return(6);
                    380:        case 0x2D:      return(6);
                    381:        case 0x4D:      return(1*(256*cmd[7] + cmd[8]));
                    382:        case 0xC2:      return(1024);
                    383:        case 0xC3:      return(4096);
                    384:        case 0xD3:      return(20);
                    385:        }
                    386:        return(0);
                    387: }

unix.superglobalmegacorp.com

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