|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.