Annotation of lucent/sys/src/9/port/devscsi.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: 
        !             9: #define        DPRINT  if(debug)kprint
        !            10: 
        !            11: #define DATASIZE       (256*512)
        !            12: #define NBUS           2
        !            13: 
        !            14: static Scsi staticcmd[NBUS];   /* BUG: should be one per scsi device */
        !            15: 
        !            16: enum
        !            17: {
        !            18:        Qscsiid = 1,            /* Top level */
        !            19: 
        !            20:        Qdir    = 0,            /* Sub-directory */
        !            21:        Qcmd,
        !            22:        Qdata,
        !            23:        Qdebug,
        !            24: };
        !            25: 
        !            26: static Dirtab scsidir[]={
        !            27:        "cmd",          {Qcmd},         0,      0666,
        !            28:        "data",         {Qdata},        0,      0666,
        !            29:        "debug",        {Qdebug},       1,      0666,
        !            30: };
        !            31: #define        NSCSI   (sizeof scsidir/sizeof(Dirtab))
        !            32: 
        !            33: extern int     scsidebugs[];
        !            34: extern int     scsiownid;
        !            35: 
        !            36: static int
        !            37: scsigen1(Chan *c, long qid, Dir *dp)
        !            38: {
        !            39:        if (qid == CHDIR)
        !            40:                devdir(c, (Qid){qid,0}, ".", 0, eve, 0555, dp);
        !            41:        else if (qid == Qscsiid)
        !            42:                devdir(c, (Qid){Qscsiid,0}, "scsiid", NUMSIZE, eve, 0666, dp);
        !            43:        else if (qid&CHDIR) {
        !            44:                char name[2];
        !            45:                name[0] = '0'+((qid>>4)&7), name[1] = 0;
        !            46:                devdir(c, (Qid){qid,0}, name, 0, eve, 0555, dp);
        !            47:        } else {
        !            48:                Dirtab *tab = &scsidir[(qid&7)-1];
        !            49:                devdir(c, (Qid){qid,0}, tab->name, tab->length, eve, tab->perm, dp);
        !            50:        }
        !            51:        return 1;
        !            52: }
        !            53: 
        !            54: static int
        !            55: scsigeno(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp)
        !            56: {
        !            57:        USED(tab, ntab, s);
        !            58:        return scsigen1(c, c->qid.path, dp);
        !            59: }
        !            60: 
        !            61: static int
        !            62: scsigen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp)
        !            63: {
        !            64:        USED(tab, ntab);
        !            65:        if (c->qid.path == CHDIR) {
        !            66:                if (0<=s && s<=7)
        !            67:                        return scsigen1(c, CHDIR|0x100|(s<<4), dp);
        !            68:                else if (s == 8)
        !            69:                        return scsigen1(c, 1, dp);
        !            70:                else
        !            71:                        return -1;
        !            72:        }
        !            73:        if (s >= NSCSI)
        !            74:                return -1;
        !            75:        return scsigen1(c, (c->qid.path&~CHDIR)+s+1, dp);
        !            76: }
        !            77: 
        !            78: void
        !            79: scsireset(void)
        !            80: {
        !            81:        scsibufreset(DATASIZE);
        !            82:        resetscsi();
        !            83: }
        !            84: 
        !            85: void
        !            86: scsiinit(void)
        !            87: {
        !            88:        int i;
        !            89: 
        !            90:        for(i = 0; i < NBUS; i++)
        !            91:                staticcmd[i].bus = i;
        !            92: 
        !            93:        initscsi();
        !            94: }
        !            95: 
        !            96: Chan *
        !            97: scsiattach(char *param)
        !            98: {
        !            99:        Chan *c;
        !           100: 
        !           101:        c = devattach('S', param);
        !           102:        c->dev = 0;
        !           103:        if(param[0] == '1')
        !           104:                c->dev = 1;
        !           105:        return c;
        !           106: }
        !           107: 
        !           108: Chan *
        !           109: scsiclone(Chan *c, Chan *nc)
        !           110: {
        !           111:        return devclone(c, nc);
        !           112: }
        !           113: 
        !           114: int
        !           115: scsiwalk(Chan *c, char *name)
        !           116: {
        !           117:        return devwalk(c, name, 0, 0, scsigen);
        !           118: }
        !           119: 
        !           120: void
        !           121: scsistat(Chan *c, char *db)
        !           122: {
        !           123:        devstat(c, db, 0, 0, scsigeno);
        !           124: }
        !           125: 
        !           126: Chan *
        !           127: scsiopen(Chan *c, int omode)
        !           128: {
        !           129:        return devopen(c, omode, 0, 0, scsigeno);
        !           130: }
        !           131: 
        !           132: void
        !           133: scsicreate(Chan *c, char *name, int omode, ulong perm)
        !           134: {
        !           135:        USED(c, name, omode, perm);
        !           136:        error(Eperm);
        !           137: }
        !           138: 
        !           139: void
        !           140: scsiclose(Chan *c)
        !           141: {
        !           142:        Scsi *cmd = &staticcmd[c->dev];
        !           143:        
        !           144:        if((c->qid.path & CHDIR) || c->qid.path==1)
        !           145:                return;
        !           146:        if((c->qid.path & 0xf) == Qcmd){
        !           147:                if(canqlock(cmd) || cmd->pid == u->p->pid){
        !           148:                        cmd->pid = 0;
        !           149:                        qunlock(cmd);
        !           150:                }
        !           151:        }
        !           152: }
        !           153: 
        !           154: long
        !           155: scsiread(Chan *c, char *a, long n, ulong offset)
        !           156: {
        !           157:        Scsi *cmd = &staticcmd[c->dev];
        !           158: 
        !           159:        if(n == 0)
        !           160:                return 0;
        !           161:        if(c->qid.path & CHDIR)
        !           162:                return devdirread(c, a, n, 0, 0, scsigen);
        !           163:        if(c->qid.path==Qscsiid){
        !           164:                n = readnum(offset, a, n, scsiownid, NUMSIZE);
        !           165:        }else switch(c->qid.path & 0xf){
        !           166:        case Qcmd:
        !           167:                if(n < 4)
        !           168:                        error(Ebadarg);
        !           169:                if(canqlock(cmd)){
        !           170:                        qunlock(cmd);
        !           171:                        error(Egreg);
        !           172:                }
        !           173:                if(cmd->pid != u->p->pid)
        !           174:                        error(Egreg);
        !           175:                n = 4;
        !           176:                *a++ = 0;
        !           177:                *a++ = 0;
        !           178:                *a++ = cmd->status >> 8;
        !           179:                *a = cmd->status;
        !           180:                cmd->pid = 0;
        !           181:                qunlock(cmd);
        !           182:                break;
        !           183:        case Qdata:
        !           184:                if(canqlock(cmd)){
        !           185:                        qunlock(cmd);
        !           186:                        error(Egreg);
        !           187:                }
        !           188:                if(cmd->pid != u->p->pid)
        !           189:                        error(Egreg);
        !           190:                if (n > DATASIZE)
        !           191:                        error(Ebadarg);
        !           192:                cmd->b = scsibuf();
        !           193:                cmd->data.base = cmd->b->virt;
        !           194:                if(waserror()){
        !           195:                        scsifree(cmd->b);
        !           196:                        nexterror();
        !           197:                }
        !           198:                cmd->data.lim = cmd->data.base + n;
        !           199:                cmd->data.ptr = cmd->data.base;
        !           200:                cmd->save = cmd->data.base;
        !           201:                scsiexec(cmd, ScsiIn);
        !           202:                n = cmd->data.ptr - cmd->data.base;
        !           203:                memmove(a, cmd->data.base, n);
        !           204:                poperror();
        !           205:                scsifree(cmd->b);
        !           206:                break;
        !           207:        case Qdebug:
        !           208:                if(offset == 0){
        !           209:                        n=1;
        !           210:                        *a="01"[scsidebugs[(c->qid.path>>4)&7]!=0];
        !           211:                }else
        !           212:                        n = 0;
        !           213:                break;
        !           214:        default:
        !           215:                panic("scsiread");
        !           216:        }
        !           217:        return n;
        !           218: }
        !           219: 
        !           220: long
        !           221: scsiwrite(Chan *c, char *a, long n, ulong offset)
        !           222: {
        !           223:        Scsi *cmd;
        !           224:        int id, m; 
        !           225:        char buf[NUMSIZE+1];
        !           226: 
        !           227:        cmd = &staticcmd[c->dev];
        !           228:        if(c->qid.path==Qscsiid && n>0) {
        !           229:                m = n;
        !           230:                if(m > NUMSIZE)
        !           231:                        m = NUMSIZE;
        !           232:                memmove(buf, a, m);
        !           233:                buf[m] = '\0';
        !           234:                id = strtoul(buf, 0, 0);
        !           235:                if(id < 0 || id > 15)
        !           236:                        error(Ebadarg);
        !           237:                scsiownid=id;
        !           238:                scsireset();
        !           239:        }else switch(c->qid.path & 0xf){
        !           240:        case Qcmd:
        !           241:                if(n < 6 || n > sizeof cmd->cmdblk)
        !           242:                        error(Ebadarg);
        !           243:                qlock(cmd);
        !           244:                cmd->pid = u->p->pid;
        !           245:                cmd->cmd.base = cmd->cmdblk;
        !           246:                memmove(cmd->cmd.base, a, n);
        !           247:                cmd->cmd.lim = cmd->cmd.base + n;
        !           248:                cmd->cmd.ptr = cmd->cmd.base;
        !           249:                cmd->target = (c->qid.path>>4)&7;
        !           250:                cmd->lun = (a[1]>>5)&7;
        !           251:                cmd->status = 0xFFFF;
        !           252:                break;
        !           253:        case Qdata:
        !           254:                if(canqlock(cmd)){
        !           255:                        qunlock(cmd);
        !           256:                        error(Egreg);
        !           257:                }
        !           258:                if(cmd->pid != u->p->pid)
        !           259:                        error(Egreg);
        !           260:                if (n > DATASIZE)
        !           261:                        error(Ebadarg);
        !           262:                cmd->b = scsibuf();
        !           263:                cmd->data.base = cmd->b->virt;
        !           264:                if(waserror()){
        !           265:                        scsifree(cmd->b);
        !           266:                        nexterror();
        !           267:                }
        !           268:                cmd->data.lim = cmd->data.base + n;
        !           269:                cmd->data.ptr = cmd->data.base;
        !           270:                cmd->save = cmd->data.base;
        !           271:                memmove(cmd->data.base, a, n);
        !           272:                scsiexec(cmd, ScsiOut);
        !           273:                n = cmd->data.ptr - cmd->data.base;
        !           274:                poperror();
        !           275:                scsifree(cmd->b);
        !           276:                break;
        !           277:        case Qdebug:
        !           278:                if(offset == 0){
        !           279:                        scsidebugs[(c->qid.path>>4)&7] = (*a=='1');
        !           280:                        n = 1;
        !           281:                }else
        !           282:                        n = 0;
        !           283:                break;
        !           284:        default:
        !           285:                panic("scsiwrite");
        !           286:        }
        !           287:        return n;
        !           288: }
        !           289: 
        !           290: void
        !           291: scsiremove(Chan *c)
        !           292: {
        !           293:        USED(c);
        !           294:        error(Eperm);
        !           295: }
        !           296: 
        !           297: void
        !           298: scsiwstat(Chan *c, char *dp)
        !           299: {
        !           300:        USED(c, dp);
        !           301:        error(Eperm);
        !           302: }
        !           303: 
        !           304: Scsi *
        !           305: scsicmd(int dev, int cmdbyte, Scsibuf *b, long size)
        !           306: {
        !           307:        Scsi *cmd = &staticcmd[0];
        !           308: 
        !           309:        qlock(cmd);
        !           310:        cmd->target = dev >> 3;
        !           311:        cmd->lun = dev & 7;
        !           312:        cmd->cmd.base = cmd->cmdblk;
        !           313:        cmd->cmd.ptr = cmd->cmd.base;
        !           314:        memset(cmd->cmdblk, 0, sizeof cmd->cmdblk);
        !           315:        cmd->cmdblk[0] = cmdbyte;
        !           316:        cmd->cmdblk[1] = cmd->lun << 5;
        !           317:        switch(cmdbyte >> 5){
        !           318:        case 0:
        !           319:                cmd->cmd.lim = &cmd->cmdblk[6];
        !           320:                break;
        !           321:        case 1:
        !           322:                cmd->cmd.lim = &cmd->cmdblk[10];
        !           323:                break;
        !           324:        default:
        !           325:                cmd->cmd.lim = &cmd->cmdblk[12];
        !           326:                break;
        !           327:        }
        !           328:        switch(cmdbyte){
        !           329:        case ScsiTestunit:
        !           330:                break;
        !           331:        case ScsiStartunit:
        !           332:                cmd->cmdblk[4] = 1;
        !           333:                break;
        !           334:        case ScsiModesense:
        !           335:                cmd->cmdblk[2] = 1;
        !           336:                /* fall through */
        !           337:        case ScsiExtsens:
        !           338:        case ScsiInquiry:
        !           339:                cmd->cmdblk[4] = size;
        !           340:                break;
        !           341:        case ScsiGetcap:
        !           342:                break;
        !           343:        }
        !           344:        cmd->b = b;
        !           345:        cmd->data.base = b->virt; 
        !           346:        cmd->data.lim = cmd->data.base + size;
        !           347:        cmd->data.ptr = cmd->data.base;
        !           348:        cmd->save = cmd->data.base;
        !           349:        return cmd;
        !           350: }
        !           351: 
        !           352: int
        !           353: scsiready(int dev)
        !           354: {
        !           355:        Scsi *cmd;
        !           356:        int status;
        !           357: 
        !           358:        cmd = scsicmd(dev, ScsiTestunit, scsibuf(), 0);
        !           359:        if(waserror()){
        !           360:                scsifree(cmd->b);
        !           361:                qunlock(cmd);
        !           362:                nexterror();
        !           363:        }
        !           364:        status = scsiexec(cmd, ScsiOut);
        !           365:        poperror();
        !           366:        scsifree(cmd->b);
        !           367:        qunlock(cmd);
        !           368:        if((status&0xff00) != 0x6000)
        !           369:                error(Eio);
        !           370:        return status&0xff;
        !           371: }
        !           372: 
        !           373: int
        !           374: scsistartstop(int dev, int cmdbyte)
        !           375: {
        !           376:        Scsi *cmd;
        !           377:        int status;
        !           378: 
        !           379:        cmd = scsicmd(dev, cmdbyte, scsibuf(), 0);
        !           380:        if(waserror()){
        !           381:                scsifree(cmd->b);
        !           382:                qunlock(cmd);
        !           383:                nexterror();
        !           384:        }
        !           385:        status = scsiexec(cmd, ScsiOut);
        !           386:        poperror();
        !           387:        scsifree(cmd->b);
        !           388:        qunlock(cmd);
        !           389:        if((status&0xff00) != 0x6000)
        !           390:                error(Eio);
        !           391:        return status&0xff;
        !           392: }
        !           393: 
        !           394: int
        !           395: scsisense(int dev, void *p)
        !           396: {
        !           397:        Scsi *cmd;
        !           398:        int status;
        !           399: 
        !           400:        cmd = scsicmd(dev, ScsiExtsens, scsibuf(), 18);
        !           401:        if(waserror()){
        !           402:                scsifree(cmd->b);
        !           403:                qunlock(cmd);
        !           404:                nexterror();
        !           405:        }
        !           406:        status = scsiexec(cmd, ScsiIn);
        !           407:        memmove(p, cmd->data.base, 18);
        !           408:        poperror();
        !           409:        scsifree(cmd->b);
        !           410:        qunlock(cmd);
        !           411:        if((status&0xff00) != 0x6000)
        !           412:                error(Eio);
        !           413:        return status&0xff;
        !           414: }
        !           415: 
        !           416: int
        !           417: scsicap(int dev, void *p)
        !           418: {
        !           419:        Scsi *cmd;
        !           420:        int status;
        !           421: 
        !           422:        cmd = scsicmd(dev, ScsiGetcap, scsibuf(), 8);
        !           423:        if(waserror()){
        !           424:                scsifree(cmd->b);
        !           425:                qunlock(cmd);
        !           426:                nexterror();
        !           427:        }
        !           428:        status = scsiexec(cmd, ScsiIn);
        !           429:        memmove(p, cmd->data.base, 8);
        !           430:        poperror();
        !           431:        scsifree(cmd->b);
        !           432:        qunlock(cmd);
        !           433:        if((status&0xff00) != 0x6000)
        !           434:                error(Eio);
        !           435:        if(status & 0xFF)
        !           436:                scsisense(dev, p);
        !           437:        return status&0xff;
        !           438: }
        !           439: 
        !           440: int
        !           441: scsiinquiry(int dev, void *p, int size)
        !           442: {
        !           443:        Scsi *cmd;
        !           444:        int status;
        !           445: 
        !           446:        cmd = scsicmd(dev, ScsiInquiry, scsibuf(), size);
        !           447:        if(waserror()){
        !           448:                scsifree(cmd->b);
        !           449:                qunlock(cmd);
        !           450:                nexterror();
        !           451:        }
        !           452:        status = scsiexec(cmd, ScsiIn);
        !           453:        memmove(p, cmd->data.base, size);
        !           454:        poperror();
        !           455:        scsifree(cmd->b);
        !           456:        qunlock(cmd);
        !           457:        if((status&0xff00) != 0x6000)
        !           458:                error(Eio);
        !           459:        if(status & 0xFF)
        !           460:                scsisense(dev, p);
        !           461:        return status&0xff;
        !           462: }
        !           463: 
        !           464: int
        !           465: scsiwp(int dev)
        !           466: {
        !           467: /* Device specific
        !           468:        Scsi *cmd;
        !           469:        int r, status;
        !           470: 
        !           471:        cmd = scsicmd(dev, ScsiModesense, scsibuf(), 12);
        !           472:        if(waserror()){
        !           473:                scsifree(cmd->b);
        !           474:                qunlock(cmd);
        !           475:                nexterror();
        !           476:        }
        !           477:        status = scsiexec(cmd, ScsiIn);
        !           478:        r = cmd->data.base[2] & 0x80;
        !           479:        poperror();
        !           480:        scsifree(cmd->b);
        !           481:        qunlock(cmd);
        !           482:        if ((status&0xffff) != 0x6000)
        !           483:                error(Eio);
        !           484:        return r;
        !           485: */
        !           486:        USED(dev);
        !           487:        return 0;
        !           488: }
        !           489: 
        !           490: int
        !           491: scsimodesense(int dev, int page, void *p, int size)
        !           492: {
        !           493:        Scsi *cmd;
        !           494:        int status;
        !           495: 
        !           496:        cmd = scsicmd(dev, ScsiModesense, scsibuf(), size);
        !           497:        cmd->cmdblk[2] = page;
        !           498:        if(waserror()){
        !           499:                scsifree(cmd->b);
        !           500:                qunlock(cmd);
        !           501:                nexterror();
        !           502:        }
        !           503:        status = scsiexec(cmd, ScsiIn);
        !           504:        memmove(p, cmd->data.base, size);
        !           505:        poperror();
        !           506:        scsifree(cmd->b);
        !           507:        qunlock(cmd);
        !           508:        if ((status&0xffff) != 0x6000)
        !           509:                error(Eio);
        !           510:        return status&0xff;
        !           511: }
        !           512: 
        !           513: int
        !           514: scsibread(int dev, Scsibuf *b, long n, long blocksize, long blockno)
        !           515: {
        !           516:        Scsi *cmd;
        !           517:        int cmdbyte, status;
        !           518: 
        !           519:        if(blockno <= 0x1fffff && n <= 256)
        !           520:                cmdbyte = ScsiRead;
        !           521:        else
        !           522:                cmdbyte = ScsiExtread;
        !           523: 
        !           524:        cmd = scsicmd(dev, cmdbyte, b, n*blocksize);
        !           525:        if(waserror()){
        !           526:                qunlock(cmd);
        !           527:                nexterror();
        !           528:        }
        !           529:        switch(cmdbyte){
        !           530:        case ScsiRead:
        !           531:                cmd->cmdblk[1] |= blockno >> 16;
        !           532:                cmd->cmdblk[2] = blockno >> 8;
        !           533:                cmd->cmdblk[3] = blockno;
        !           534:                cmd->cmdblk[4] = n;
        !           535:                break;
        !           536:        default:
        !           537:                cmd->cmdblk[2] = blockno >> 24;
        !           538:                cmd->cmdblk[3] = blockno >> 16;
        !           539:                cmd->cmdblk[4] = blockno >> 8;
        !           540:                cmd->cmdblk[5] = blockno;
        !           541:                cmd->cmdblk[7] = n>>8;
        !           542:                cmd->cmdblk[8] = n;
        !           543:                break;
        !           544:        }
        !           545:        status = scsiexec(cmd, ScsiIn);
        !           546:        n = cmd->data.ptr - cmd->data.base;
        !           547:        poperror();
        !           548:        qunlock(cmd);
        !           549:        if(n <= 0 && status == 0x6002)
        !           550:                error(Eio);
        !           551: 
        !           552:        return n;
        !           553: }
        !           554: 
        !           555: int
        !           556: scsibwrite(int dev, Scsibuf *b, long n, long blocksize, long blockno)
        !           557: {
        !           558:        Scsi *cmd;
        !           559:        int cmdbyte, status;
        !           560: 
        !           561:        if(blockno <= 0x1fffff && n <= 256)
        !           562:                cmdbyte = ScsiWrite;
        !           563:        else
        !           564:                cmdbyte = ScsiExtwrite;
        !           565: 
        !           566:        cmd = scsicmd(dev, cmdbyte, b, n*blocksize);
        !           567:        if(waserror()){
        !           568:                qunlock(cmd);
        !           569:                nexterror();
        !           570:        }
        !           571:        switch(cmdbyte){
        !           572:        case ScsiWrite:
        !           573:                cmd->cmdblk[1] |= blockno >> 16;
        !           574:                cmd->cmdblk[2] = blockno >> 8;
        !           575:                cmd->cmdblk[3] = blockno;
        !           576:                cmd->cmdblk[4] = n;
        !           577:                break;
        !           578:        default:
        !           579:                cmd->cmdblk[2] = blockno >> 24;
        !           580:                cmd->cmdblk[3] = blockno >> 16;
        !           581:                cmd->cmdblk[4] = blockno >> 8;
        !           582:                cmd->cmdblk[5] = blockno;
        !           583:                cmd->cmdblk[7] = n>>8;
        !           584:                cmd->cmdblk[8] = n;
        !           585:                break;
        !           586:        }
        !           587:        status = scsiexec(cmd, ScsiOut);
        !           588:        n = cmd->data.ptr - cmd->data.base;
        !           589:        poperror();
        !           590:        qunlock(cmd);
        !           591:        if(n <= 0 && status == 0x6002)
        !           592:                error(Eio);
        !           593:        return n;
        !           594: }

unix.superglobalmegacorp.com

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