Annotation of researchv10dc/sys/io/nscsi.c, revision 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.