Annotation of lucent/sys/src/9/port/devscsi.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: 
                      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.