Annotation of lucent/sys/src/9/port/devwren.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: #include       "io.h"
                      9: 
                     10: #define DATASIZE       (8*1024)
                     11: 
                     12: typedef struct Partition       Partition;
                     13: typedef struct Drive           Drive;
                     14: 
                     15: enum {
                     16:        Npart=          8+2,    /* 8 sub partitions, disk, and partition */
                     17:        Ndisk=          64,     /* maximum disks; if you change it, you must
                     18:                                   map from dev to disk */
                     19: 
                     20:        /* file types */
                     21:        Qdir=           0,
                     22: };
                     23: #define PART(x)                ((x)&0xF)
                     24: #define DRIVE(x)       (((x)>>4)&(Ndisk-1))
                     25: #define MKQID(d,p)     (((d)<<4) | (p))
                     26: 
                     27: struct Partition
                     28: {
                     29:        ulong   start;
                     30:        ulong   end;
                     31:        char    name[NAMELEN+1];
                     32: };
                     33: 
                     34: struct Drive
                     35: {
                     36:        QLock;
                     37:        ulong           bytes;                  /* bytes per block */
                     38:        int             npart;                  /* actual number of partitions */
                     39:        int             drive;
                     40:        int             readonly;
                     41:        Partition       p[Npart];
                     42: };
                     43: 
                     44: static Drive   wren[Ndisk];
                     45: 
                     46: static void    wrenpart(int);
                     47: static long    wrenio(Chan*, int, char*, ulong, ulong);
                     48: 
                     49: /*
                     50:  *  accepts [0-7].[0-7], or abbreviation
                     51:  */
                     52: static int
                     53: wrendev(char *p)
                     54: {
                     55:        int drive, unit;
                     56: 
                     57:        if(p == 0 || p[0] == '\0')
                     58:                return 0;
                     59:        if(p[0] < '0' || p[0] > '7')
                     60:                error(Ebadarg);
                     61:        drive = p[0] - '0';
                     62:        unit = 0;
                     63:        if(p[1]){
                     64:                if(p[1] != '.' || p[2] < '0' || p[2] > '7' || p[3] != '\0')
                     65:                        error(Ebadarg);
                     66:                unit = p[2] - '0';
                     67:        }
                     68:        return (drive << 3) | unit;
                     69: }
                     70: 
                     71: static int
                     72: wrengen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp)
                     73: {
                     74:        Qid qid;
                     75:        int drive;
                     76:        char name[NAMELEN+4];
                     77:        Drive *dp;
                     78:        Partition *pp;
                     79:        ulong l;
                     80: 
                     81:        USED(tab, ntab);
                     82:        qid.vers = 0;
                     83:        drive = c->dev;
                     84:        if(drive >= Ndisk)
                     85:                return -1;
                     86:        dp = &wren[drive];
                     87: 
                     88:        if(s >= dp->npart)
                     89:                return -1;
                     90: 
                     91:        pp = &dp->p[s];
                     92:        if(drive & 7)
                     93:                sprint(name, "sd%d.%d%s", drive>>3, drive&7, pp->name);
                     94:        else
                     95:                sprint(name, "sd%d%s", drive>>3, pp->name);
                     96:        name[NAMELEN] = 0;
                     97:        qid.path = MKQID(drive, s);
                     98:        l = (pp->end - pp->start) * dp->bytes;
                     99:        devdir(c, qid, name, l, eve, dp->readonly ? 0444 : 0666, dirp);
                    100:        return 1;
                    101: }
                    102: 
                    103: void
                    104: wrenreset(void)
                    105: {
                    106: }
                    107: 
                    108: void
                    109: wreninit(void)
                    110: {
                    111: }
                    112: 
                    113: /*
                    114:  *  param is #w<target>.<lun>
                    115:  */
                    116: Chan *
                    117: wrenattach(char *param)
                    118: {
                    119:        Chan *c;
                    120:        int drive;
                    121: 
                    122:        drive = wrendev(param);
                    123:        wrenpart(drive);
                    124:        c = devattach('w', param);
                    125:        c->dev = drive;
                    126:        return c;
                    127: }
                    128: 
                    129: Chan*
                    130: wrenclone(Chan *c, Chan *nc)
                    131: {
                    132:        return devclone(c, nc);
                    133: }
                    134: 
                    135: int
                    136: wrenwalk(Chan *c, char *name)
                    137: {
                    138:        return devwalk(c, name, 0, 0, wrengen);
                    139: }
                    140: 
                    141: void
                    142: wrenstat(Chan *c, char *dp)
                    143: {
                    144:        devstat(c, dp, 0, 0, wrengen);
                    145: }
                    146: 
                    147: Chan*
                    148: wrenopen(Chan *c, int omode)
                    149: {
                    150:        return devopen(c, omode, 0, 0, wrengen);
                    151: }
                    152: 
                    153: void
                    154: wrencreate(Chan *c, char *name, int omode, ulong perm)
                    155: {
                    156:        USED(c, name, omode, perm);
                    157:        error(Eperm);
                    158: }
                    159: 
                    160: void
                    161: wrenclose(Chan *c)
                    162: {
                    163:        Drive *d;
                    164:        Partition *p;
                    165: 
                    166:        if(c->mode != OWRITE && c->mode != ORDWR)
                    167:                return;
                    168: 
                    169:        d = &wren[DRIVE(c->qid.path)];
                    170:        p = &d->p[PART(c->qid.path)];
                    171:        if(strcmp(p->name, "partition"))
                    172:                return;
                    173: 
                    174:        wrenpart(DRIVE(c->qid.path));
                    175: }
                    176: 
                    177: void
                    178: wrenremove(Chan *c)
                    179: {
                    180:        USED(c);
                    181:        error(Eperm);
                    182: }
                    183: 
                    184: void
                    185: wrenwstat(Chan *c, char *dp)
                    186: {
                    187:        USED(c, dp);
                    188:        error(Eperm);
                    189: }
                    190: 
                    191: long
                    192: wrenread(Chan *c, char *a, long n, ulong offset)
                    193: {
                    194:        if(c->qid.path == CHDIR)
                    195:                return devdirread(c, a, n, 0, 0, wrengen);
                    196:        return wrenio(c, 0, a, n, offset);
                    197: }
                    198: 
                    199: long
                    200: wrenwrite(Chan *c, char *a, long n, ulong offset)
                    201: {
                    202:        n = wrenio(c, 1, a, n, offset);
                    203:        if(n)
                    204:                return n;
                    205:        error("end of device");
                    206:        return 0;               /* not reached */
                    207: }
                    208: 
                    209: static long
                    210: wrenio(Chan *c, int write, char *a, ulong len, ulong offset)
                    211: {
                    212:        Drive *d;
                    213:        Partition *p;
                    214:        Scsibuf *b;
                    215:        ulong block, n, max, x;
                    216:        d = &wren[DRIVE(c->qid.path)];
                    217:        if(d->npart == 0)                       /* drive repartitioned */
                    218:                error(Eio);
                    219:        p = &d->p[PART(c->qid.path)];
                    220: 
                    221:        block = offset / d->bytes + p->start;
                    222:        n = (offset + len + d->bytes - 1) / d->bytes + p->start - block;
                    223:        max = DATASIZE / d->bytes;
                    224:        if(n > max)
                    225:                n = max;
                    226:        if(block + n > p->end)
                    227:                n = p->end - block;
                    228:        if(block >= p->end || n == 0)
                    229:                return 0;
                    230:        b = scsibuf();
                    231:        if(waserror()){
                    232:                scsifree(b);
                    233:                nexterror();
                    234:        }
                    235:        offset %= d->bytes;
                    236:        if(write){
                    237:                if(offset || len % d->bytes){
                    238:                        x = scsibread(d->drive, b, n, d->bytes, block);
                    239:                        if(x < n * d->bytes){
                    240:                                n = x / d->bytes;
                    241:                                x = n * d->bytes - offset;
                    242:                                if(len > x)
                    243:                                        len = x;
                    244:                        }
                    245:                }
                    246:                memmove((char*)b->virt + offset, a, len);
                    247:                x = scsibwrite(d->drive, b, n, d->bytes, block);
                    248:                if(x < offset)
                    249:                        len = 0;
                    250:                else if(len > x - offset)
                    251:                        len = x - offset;
                    252:        }else{
                    253:                x = scsibread(d->drive, b, n, d->bytes, block);
                    254:                if(x < offset)
                    255:                        len = 0;
                    256:                else if(len > x - offset)
                    257:                        len = x - offset;
                    258:                if(len)
                    259:                        memmove(a, (char*)b->virt + offset, len);
                    260:        }
                    261:        poperror();
                    262:        scsifree(b);
                    263:        return len;
                    264: }
                    265: 
                    266: /*
                    267:  *  read partition table.  The partition table is just ascii strings.
                    268:  */
                    269: #define MAGIC "plan9 partitions"
                    270: static void
                    271: wrenpart(int dev)
                    272: {
                    273:        Drive *dp;
                    274:        Partition *pp;
                    275:        uchar buf[128];
                    276:        Scsibuf *b;
                    277:        char *rawpart, *line[Npart+1], *field[3];
                    278:        ulong n;
                    279:        int i;
                    280: 
                    281:        dp = &wren[dev];
                    282:        if(waserror()){
                    283:                qunlock(dp);
                    284:                nexterror();
                    285:        }
                    286:        qlock(dp);
                    287:        scsiready(dev);
                    288:        scsisense(dev, buf);
                    289:        scsistartstop(dev, ScsiStartunit);
                    290:        scsisense(dev, buf);
                    291:        if(scsicap(dev, buf))
                    292:                error(Eio);
                    293:        dp->drive = dev;
                    294:        dp->readonly = scsiwp(dev);
                    295: 
                    296:        /*
                    297:         *  we always have a partition for the whole disk
                    298:         *  and one for the partition table
                    299:         */
                    300:        dp->bytes = (buf[4]<<24)+(buf[5]<<16)+(buf[6]<<8)+(buf[7]);
                    301:        pp = &dp->p[0];
                    302:        strcpy(pp->name, "disk");
                    303:        pp->start = 0;
                    304:        pp->end = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]) + 1;
                    305:        pp++;
                    306:        strcpy(pp->name, "partition");
                    307:        pp->start = dp->p[0].end - 1;
                    308:        pp->end = dp->p[0].end;
                    309: 
                    310:        scsiinquiry(dev, buf, sizeof buf);
                    311:        switch(buf[0]) {
                    312:        default:
                    313:                error("not a SCSI disk");
                    314:        case 0x00:                      /* Direct access (disk) */
                    315:        case 0x05:                      /* CD-rom */
                    316:        case 0x07:                      /* rewriteable MO */
                    317:                break;
                    318:        }
                    319: 
                    320:        if(memcmp(&buf[8], "INSITE  I325VM        *F", 24) == 0)
                    321:                scsimodesense(dev, 0x2e, buf, 0x2a);
                    322:        /*
                    323:         *  read partition table from disk, null terminate
                    324:         */
                    325:        b = scsibuf();
                    326:        if(waserror()){
                    327:                scsifree(b);
                    328:                nexterror();
                    329:        }
                    330:        scsibread(dev, b, 1, dp->bytes, dp->p[0].end-1);
                    331:        rawpart = b->virt;
                    332:        rawpart[dp->bytes-1] = 0;
                    333: 
                    334:        /*
                    335:         *  parse partition table.
                    336:         */
                    337:        pp = &dp->p[2];
                    338:        n = getfields(rawpart, line, Npart+1, "\n");
                    339:        if(n > 0 && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
                    340:                for(i = 1; i < n; i++){
                    341:                        if(getfields(line[i], field, 3, " ") != 3)
                    342:                                break;
                    343:                        strncpy(pp->name, field[0], NAMELEN);
                    344:                        pp->start = strtoul(field[1], 0, 0);
                    345:                        pp->end = strtoul(field[2], 0, 0);
                    346:                        if(pp->start > pp->end || pp->start >= dp->p[0].end)
                    347:                                break;
                    348:                        pp++;
                    349:                }
                    350:        }
                    351:        dp->npart = pp - dp->p;
                    352:        poperror();
                    353:        scsifree(b);
                    354:        poperror();
                    355:        qunlock(dp);
                    356: }

unix.superglobalmegacorp.com

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