Annotation of lucent/sys/src/boot/pc/scsi.c, revision 1.1.1.1

1.1       root        1: #include "u.h"
                      2: #include "lib.h"
                      3: #include "mem.h"
                      4: #include "dat.h"
                      5: #include "fns.h"
                      6: #include "io.h"
                      7: 
                      8: /*
                      9:  * BUG: only LUN 0
                     10:  */
                     11: 
                     12: static Scsi staticcmd;
                     13: 
                     14: static Disc *sdrive;
                     15: static bufbusy;
                     16: 
                     17: Scsibuf *
                     18: scsibuf(void)
                     19: {
                     20:        static Scsibuf b;
                     21: 
                     22:        if(bufbusy)
                     23:                panic("bufbusy\n");
                     24:        bufbusy++;
                     25:        if(b.virt == 0){
                     26:                b.virt = ialloc(Maxxfer, 0);
                     27:                b.phys = (void *)(PADDR(b.virt));
                     28:        }
                     29:        return &b;
                     30: }
                     31: 
                     32: void
                     33: scsifree(Scsibuf*)
                     34: {
                     35:        if(bufbusy == 0)
                     36:                panic("buf not busy\n");
                     37:        bufbusy = 0;
                     38: }
                     39: 
                     40: Scsi *
                     41: scsicmd(int dev, int cmdbyte, Scsibuf *b, long size)
                     42: {
                     43:        Scsi *cmd = &staticcmd;
                     44: 
                     45:        cmd->target = dev /*>> 3*/;                             /* BUG */
                     46:        cmd->lun = 0/*dev & 7*/;                                /* BUG */
                     47:        cmd->cmd.base = cmd->cmdblk;
                     48:        cmd->cmd.ptr = cmd->cmd.base;
                     49:        memset(cmd->cmdblk, 0, sizeof cmd->cmdblk);
                     50:        cmd->cmdblk[0] = cmdbyte;
                     51:        cmd->cmdblk[1] = cmd->lun << 5;
                     52:        switch(cmdbyte >> 5){
                     53:        case 0:
                     54:                cmd->cmd.lim = &cmd->cmdblk[6];
                     55:                break;
                     56:        case 1:
                     57:                cmd->cmd.lim = &cmd->cmdblk[10];
                     58:                break;
                     59:        default:
                     60:                cmd->cmd.lim = &cmd->cmdblk[12];
                     61:                break;
                     62:        }
                     63:        switch(cmdbyte){
                     64:        case ScsiTestunit:
                     65:                break;
                     66:        case ScsiStartunit:
                     67:                cmd->cmdblk[4] = 1;
                     68:                break;
                     69:        case ScsiModesense:
                     70:                cmd->cmdblk[2] = 1;
                     71:                /* fall through */
                     72:        case ScsiExtsens:
                     73:        case ScsiInquiry:
                     74:                cmd->cmdblk[4] = size;
                     75:                break;
                     76:        case ScsiGetcap:
                     77:                break;
                     78:        }
                     79:        cmd->b = b;
                     80:        cmd->data.base = b->virt;
                     81:        cmd->data.lim = cmd->data.base + size;
                     82:        cmd->data.ptr = cmd->data.base;
                     83:        cmd->save = cmd->data.base;
                     84:        return cmd;
                     85: }
                     86: 
                     87: int
                     88: scsiready(int dev)
                     89: {
                     90:        Scsi *cmd;
                     91:        int status;
                     92: 
                     93:        cmd = scsicmd(dev, ScsiTestunit, scsibuf(), 0);
                     94:        status = scsiexec(cmd, ScsiOut);
                     95:        scsifree(cmd->b);
                     96:        return status&0xff;
                     97: }
                     98: 
                     99: int
                    100: scsisense(int dev, void *p)
                    101: {
                    102:        Scsi *cmd;
                    103:        int status;
                    104: 
                    105:        cmd = scsicmd(dev, ScsiExtsens, scsibuf(), 18);
                    106:        status = scsiexec(cmd, ScsiIn);
                    107:        memmove(p, cmd->data.base, 18);
                    108:        scsifree(cmd->b);
                    109:        return status&0xff;
                    110: }
                    111: 
                    112: int
                    113: scsistartstop(int dev, int cmdbyte)
                    114: {
                    115:        Scsi *cmd;
                    116:        int status;
                    117: 
                    118:        cmd = scsicmd(dev, cmdbyte, scsibuf(), 0);
                    119:        status = scsiexec(cmd, ScsiOut);
                    120:        scsifree(cmd->b);
                    121:        return status&0xff;
                    122: }
                    123: 
                    124: int
                    125: scsicap(int dev, void *p)
                    126: {
                    127:        Scsi *cmd;
                    128:        int status;
                    129: 
                    130:        cmd = scsicmd(dev, ScsiGetcap, scsibuf(), 8);
                    131:        status = scsiexec(cmd, ScsiIn);
                    132:        memmove(p, cmd->data.base, 8);
                    133:        scsifree(cmd->b);
                    134:        return status&0xFF;
                    135: }
                    136: 
                    137: int
                    138: scsibread(int dev, Scsibuf *b, long n, long blocksize, long blockno)
                    139: {
                    140:        Scsi *cmd;
                    141:        int cmdbyte;
                    142: 
                    143:        if(blockno <= 0x1fffff && n <= 256)
                    144:                cmdbyte = ScsiRead;
                    145:        else
                    146:                cmdbyte = ScsiExtread;
                    147: 
                    148:        cmd = scsicmd(dev, cmdbyte, b, n*blocksize);
                    149:        switch(cmdbyte){
                    150:        case ScsiRead:
                    151:                cmd->cmdblk[1] |= blockno >> 16;
                    152:                cmd->cmdblk[2] = blockno >> 8;
                    153:                cmd->cmdblk[3] = blockno;
                    154:                cmd->cmdblk[4] = n;
                    155:                break;
                    156:        default:
                    157:                cmd->cmdblk[2] = blockno >> 24;
                    158:                cmd->cmdblk[3] = blockno >> 16;
                    159:                cmd->cmdblk[4] = blockno >> 8;
                    160:                cmd->cmdblk[5] = blockno;
                    161:                cmd->cmdblk[7] = n>>8;
                    162:                cmd->cmdblk[8] = n;
                    163:                break;
                    164:        }
                    165:        scsiexec(cmd, ScsiIn);
                    166:        n = cmd->data.ptr - cmd->data.base;
                    167:        return n;
                    168: }
                    169: 
                    170: int
                    171: scsibwrite(int dev, Scsibuf *b, long n, long blocksize, long blockno)
                    172: {
                    173:        Scsi *cmd;
                    174: 
                    175:        int cmdbyte;
                    176: 
                    177:        if(blockno <= 0x1fffff && n <= 256)
                    178:                cmdbyte = ScsiWrite;
                    179:        else
                    180:                cmdbyte = ScsiExtwrite;
                    181: 
                    182:        cmd = scsicmd(dev, cmdbyte, b, n*blocksize);
                    183:        switch(cmdbyte){
                    184:        case ScsiWrite:
                    185:                cmd->cmdblk[1] |= blockno >> 16;
                    186:                cmd->cmdblk[2] = blockno >> 8;
                    187:                cmd->cmdblk[3] = blockno;
                    188:                cmd->cmdblk[4] = n;
                    189:                break;
                    190:        default:
                    191:                cmd->cmdblk[2] = blockno >> 24;
                    192:                cmd->cmdblk[3] = blockno >> 16;
                    193:                cmd->cmdblk[4] = blockno >> 8;
                    194:                cmd->cmdblk[5] = blockno;
                    195:                cmd->cmdblk[7] = n>>8;
                    196:                cmd->cmdblk[8] = n;
                    197:                break;
                    198:        }
                    199:        scsiexec(cmd, ScsiOut);
                    200:        n = cmd->data.ptr - cmd->data.base;
                    201:        return n;
                    202: }
                    203: 
                    204: long
                    205: scsiseek(int dev, long off)
                    206: {
                    207:        sdrive[dev].offset = off;
                    208:        return off;
                    209: }
                    210: 
                    211: /*
                    212:  *  read partition table.  The partition table is just ascii strings.
                    213:  */
                    214: #define MAGIC "plan9 partitions"
                    215: static void
                    216: scsipart(int dev)
                    217: {
                    218:        Disc *dp;
                    219:        Partition *pp;
                    220:        char *line[Npart+1], *cp;
                    221:        char *field[3];
                    222:        ulong n;
                    223:        int i;
                    224:        Scsibuf *b;
                    225: 
                    226:        dp = &sdrive[dev];
                    227: 
                    228:        /*
                    229:         *  we always have a partition for the whole disk
                    230:         *  and one for the partition table
                    231:         */
                    232:        pp = &dp->p[0];
                    233:        strcpy(pp->name, "disk");
                    234:        pp->start = 0;
                    235:        pp->end = dp->cap;
                    236:        pp++;
                    237:        strcpy(pp->name, "partition");
                    238:        pp->start = dp->p[0].end - 1;
                    239:        pp->end = dp->p[0].end;
                    240:        dp->npart = 2;
                    241: 
                    242:        /*
                    243:         *  read partition table from disk, null terminate
                    244:         */
                    245:        b = scsibuf();
                    246:        if(scsibread(dev, b, 1, dp->bytes, dp->cap-1) <= 0){
                    247:                scsifree(b);
                    248:                print("can't read partition block\n");
                    249:                return;
                    250:        }
                    251:        cp = b->virt;
                    252:        cp[dp->bytes-1] = 0;
                    253: 
                    254:        /*
                    255:         *  parse partition table.
                    256:         */
                    257:        n = getfields(cp, line, Npart+1, '\n');
                    258:        if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
                    259:                for(i = 1; i < n; i++){
                    260:                        pp++;
                    261:                        if(getfields(line[i], field, 3, ' ') != 3)
                    262:                                break;
                    263:                        strncpy(pp->name, field[0], NAMELEN);
                    264:                        pp->start = strtoul(field[1], 0, 0);
                    265:                        pp->end = strtoul(field[2], 0, 0);
                    266:                        if(pp->start > pp->end || pp->start >= dp->p[0].end)
                    267:                                break;
                    268:                        dp->npart++;
                    269:                }
                    270:        }
                    271:        scsifree(b);
                    272:        return;
                    273: }
                    274: 
                    275: Partition*
                    276: setscsipart(int dev, char *p)
                    277: {
                    278:        Partition *pp;
                    279:        Disc *dp;
                    280: 
                    281:        dp = &sdrive[dev];
                    282:        for(pp = dp->p; pp < &dp->p[dp->npart]; pp++)
                    283:                if(strcmp(pp->name, p) == 0){
                    284:                        dp->current = pp;
                    285:                        return pp;
                    286:                }
                    287:        return 0;
                    288: }
                    289: 
                    290: static long
                    291: scsirw(int dev, int write, char *a, ulong len, ulong offset)
                    292: {
                    293:        Disc *d;
                    294:        Partition *p;
                    295:        Scsibuf *b;
                    296:        ulong block, n, max, x;
                    297: 
                    298:        d = &sdrive[dev];
                    299:        p = d->current;
                    300:        if(p == 0)
                    301:                return -1;
                    302: 
                    303:        block = offset / d->bytes + p->start;
                    304:        n = (offset + len + d->bytes - 1) / d->bytes + p->start - block;
                    305:        max = Maxxfer / d->bytes;
                    306:        if(n > max)
                    307:                n = max;
                    308:        if(block + n > p->end)
                    309:                n = p->end - block;
                    310:        if(block >= p->end || n == 0)
                    311:                return 0;
                    312:        b = scsibuf();
                    313: 
                    314:        offset %= d->bytes;
                    315:        if(write){
                    316:                if(offset || len % d->bytes){
                    317:                        x = scsibread(dev, b, n, d->bytes, block);
                    318:                        if(x < n * d->bytes){
                    319:                                n = x / d->bytes;
                    320:                                x = n * d->bytes - offset;
                    321:                                if(len > x)
                    322:                                        len = x;
                    323:                        }
                    324:                }
                    325:                memmove((char*)b->virt + offset, a, len);
                    326:                x = scsibwrite(dev, b, n, d->bytes, block);
                    327:                if(x < offset)
                    328:                        len = 0;
                    329:                else if(len > x - offset)
                    330:                        len = x - offset;
                    331:        }else{
                    332:                x = scsibread(dev, b, n, d->bytes, block);
                    333:                if(x < offset)
                    334:                        len = 0;
                    335:                else if(len > x - offset)
                    336:                        len = x - offset;
                    337:                memmove(a, (char*)b->virt + offset, len);
                    338:        }
                    339: 
                    340:        scsifree(b);
                    341:        return len;
                    342: }
                    343: 
                    344: long
                    345: scsiread(int dev, void *a, long n)
                    346: {
                    347:        long len;
                    348: 
                    349:        len = scsirw(dev, 0, a, n, sdrive[dev].offset);
                    350:        if(len > 0)
                    351:                sdrive[dev].offset += len;
                    352:        return len;
                    353: }
                    354: 
                    355: extern int (*aha1542reset(void))(Scsi*, int);
                    356: extern int (*ultra14freset(void))(Scsi*, int);
                    357: 
                    358: static int (*exec)(Scsi*, int);
                    359: 
                    360: int
                    361: scsiexec(Scsi *p, int rflag)
                    362: {
                    363:        if(exec == 0)
                    364:                return 0;
                    365:        return (*exec)(p, rflag);
                    366: }
                    367: 
                    368: int
                    369: scsiinit(void)
                    370: {
                    371:        int i, online;
                    372:        uchar buf[32];
                    373: 
                    374:        if((exec = ultra14freset()) == 0 && (exec = aha1542reset()) == 0)
                    375:                return 0;
                    376:        sdrive = ialloc(8 * sizeof(Disc), 0);
                    377:        online = 0;
                    378:        for(i = 0; i < 7; i++){
                    379:                if(scsiready(i) == 0x20)                /* timeout */
                    380:                        continue;
                    381:                scsisense(i, buf);
                    382:                scsistartstop(i, ScsiStartunit);
                    383:                scsisense(i, buf);
                    384:                if(scsicap(i, buf))
                    385:                        continue;
                    386:                online |= (1<<i);
                    387:                sdrive[i].online = 1;
                    388:                sdrive[i].cap = ((buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3])+1;
                    389:                sdrive[i].bytes = (buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7];
                    390:                print("scsi%d: cap %lud, sec %d\n", i, sdrive[i].cap, sdrive[i].bytes);
                    391:                scsipart(i);
                    392:        }
                    393:        return online;
                    394: }

unix.superglobalmegacorp.com

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