| plan 9 kernel history: overview | file list | diff list |
1995/0404/port/devsd.c (diff list | history)
| port/devsd.c on 1994/0913 | ||
| 1994/0913 | /* * SCSI disc driver */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "devtab.h" | |
| 1995/0403 | enum { TypeDA = 0x00, /* Direct Access */ | |
| 1995/0404 | TypeSA = 0x01, /* Sequential Access */ | |
| 1995/0403 | TypeWO = 0x04, /* Worm */ TypeCD = 0x05, /* CD-ROM */ TypeMO = 0x07, /* rewriteable Magneto-Optical */ | |
| 1995/0404 | TYpeMC = 0x08, /* Medium Changer */ | |
| 1995/0403 | }; | |
| 1994/0913 | enum { | |
| 1994/1228 | LogNpart = 4, | |
| 1994/0913 | Npart = 1<<LogNpart, Ndisk = 32, Nlun = 8, }; #define DRIVE(qid) ((qid).path>>LogNpart) #define PART(qid) ((qid).path&(Npart-1)) typedef struct Part Part; typedef struct Disk Disk; struct Part { ulong beg; ulong end; char name[NAMELEN]; }; struct Disk { QLock; Target* t; uchar lun; char id[NAMELEN]; char vol[NAMELEN]; uchar* inquire; ulong size; ulong bsize; int npart; Part table[Npart]; }; int ndisk; Disk disk[Ndisk]; static void sdrdpart(Disk*); static long sdio(Chan*, int, char*, ulong, ulong); | |
| 1995/0403 | static int types[] = { | |
| 1995/0404 | TypeDA, TypeCD, TypeMO, | |
| 1995/0403 | -1, }; | |
| 1994/0913 | static int | |
| 1995/0325 | sdgen(Chan *c, Dirtab*, long, long s, Dir *dirp) | |
| 1994/0913 | { Qid qid; Disk *d; Part *p; int unit; char name[2*NAMELEN]; d = disk; while(s >= d->npart) { s -= d->npart; d++; } unit = d - disk; if(unit > ndisk) return -1; p = d->table+s; sprint(name, "%s%s", d->vol, p->name); name[NAMELEN-1] = '\0'; qid = (Qid){(unit<<LogNpart)+s, 0}; devdir(c, qid, name, (p->end - p->beg) * d->bsize, eve, 0666, dirp); return 1; } void sdreset(void) { } void sdinit(void) { Disk *d; ulong s, b; | |
| 1995/0329 | uchar inq[255]; int dev, i, nbytes; | |
| 1994/0913 | dev = 0; for(;;) { d = &disk[ndisk]; | |
| 1995/0403 | dev = scsiinv(dev, types, &d->t, &d->inquire, d->id); | |
| 1994/0913 | if(dev < 0) break; | |
| 1995/0404 | if(scsitest(d->t, 0) < 0) scsireqsense(d->t, 0, 0); if(scsistart(d->t, 0, 1) < 0) scsireqsense(d->t, 0, 0); print("sd1|"); | |
| 1994/0913 | /* Search for other lun's */ for(i = 0; i < Nlun; i++) { d->lun = i; | |
| 1995/0404 | print("sd2|"); | |
| 1995/0329 | /* * A SCSI target does not support a lun if the * the peripheral device type and qualifier fields * in the response to an inquiry command are 0x7F. */ memset(inq, 0, sizeof(inq)); nbytes = sizeof(inq); if(scsiinquiry(d->t, d->lun, inq, &nbytes) != STok || inq[0] == 0x7F) continue; | |
| 1995/0404 | print("sd3|"); | |
| 1994/0913 | s = 0; b = 0; if(scsicap(d->t, d->lun, &s, &b) != STok) { | |
| 1995/0404 | scsireqsense(d->t, 0, 0); | |
| 1994/0913 | continue; } | |
| 1995/0404 | print("sd4/%d/%d|", s, b); | |
| 1994/0913 | if(s == 0 || b == 0) continue; | |
| 1995/0404 | print("sd5/0x%2.2ux|", d->inquire[0]); | |
| 1994/0913 | d->size = s; d->bsize = b; | |
| 1995/0403 | switch(d->inquire[0] & 0x1F){ | |
| 1994/0913 | ||
| 1995/0403 | case TypeDA: case TypeMO: sprint(d->vol, "sd%d", ndisk); break; case TypeCD: sprint(d->vol, "cd%d", ndisk); break; default: continue; } | |
| 1995/0404 | print("sd6|"); | |
| 1995/0403 | ||
| 1994/0913 | if(++ndisk >= Ndisk) break; d++; d->t = d[-1].t; d->inquire = d[-1].inquire; strcpy(d->id, d[-1].id); } if(ndisk >= Ndisk) { print("devsd: configure more disks\n"); break; } } } Chan* sdattach(char *spec) { int i; for(i = 0; i < ndisk; i++) sdrdpart(&disk[i]); return devattach('w', spec); } Chan * sdclone(Chan *c, Chan *nc) { return devclone(c, nc); } int sdwalk(Chan *c, char *name) { return devwalk(c, name, 0, 0, sdgen); } void sdstat(Chan *c, char *db) { devstat(c, db, 0, 0, sdgen); } Chan * sdopen(Chan *c, int omode) { return devopen(c, omode, 0, 0, sdgen); } void | |
| 1995/0325 | sdcreate(Chan*, char*, int, ulong) | |
| 1994/0913 | { error(Eperm); } void | |
| 1995/0325 | sdremove(Chan*) | |
| 1994/0913 | { error(Eperm); } void | |
| 1995/0325 | sdwstat(Chan*, char*) | |
| 1994/0913 | { error(Eperm); } void sdclose(Chan *c) { Disk *d; Part *p; | |
| 1995/0325 | if(c->qid.path & CHDIR) | |
| 1994/0913 | return; d = &disk[DRIVE(c->qid)]; p = &d->table[PART(c->qid)]; | |
| 1995/0325 | if((c->mode&3) != OREAD && strcmp(p->name, "partition") == 0) sdrdpart(d); | |
| 1994/0913 | } long sdread(Chan *c, void *a, long n, ulong offset) { | |
| 1995/0325 | if(c->qid.path & CHDIR) | |
| 1994/0913 | return devdirread(c, a, n, 0, 0, sdgen); return sdio(c, 0, a, n, offset); } | |
| 1995/0108 | Block* sdbread(Chan *c, long n, ulong offset) { return devbread(c, n, offset); } | |
| 1994/0913 | long sdwrite(Chan *c, char *a, long n, ulong offset) { return sdio(c, 1, a, n, offset); | |
| 1995/0108 | } long sdbwrite(Chan *c, Block *bp, ulong offset) { return devbwrite(c, bp, offset); | |
| 1994/0913 | } static void sdrdpart(Disk *d) { Part *p; int n, i; char *b, *line[Npart+2], *field[3]; static char MAGIC[] = "plan9 partitions"; b = scsialloc(d->bsize); if(b == 0) error(Enomem); qlock(d); p = d->table; strcpy(p->name, "disk"); p->beg = 0; p->end = d->size + 1; p++; strcpy(p->name, "partition"); p->beg = d->table[0].end - 1; p->end = d->table[0].end; p++; d->npart = 2; | |
| 1995/0403 | if((d->inquire[0] & 0x1F) == TypeCD){ scsifree(b); qunlock(d); return; } | |
| 1994/0913 | scsibio(d->t, d->lun, SCSIread, b, 1, d->bsize, d->table[0].end-1); b[d->bsize-1] = '\0'; /* * parse partition table. */ | |
| 1995/0117 | n = getfields(b, line, Npart+2, "\n"); | |
| 1994/0913 | if(n > 0 && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0) { for(i = 1; i < n; i++) { | |
| 1995/0117 | switch(getfields(line[i], field, 3, " ")) { | |
| 1994/0913 | case 2: if(strcmp(field[0], "unit") == 0) strncpy(d->vol, field[1], NAMELEN); break; case 3: | |
| 1994/1228 | if(p >= &d->table[Npart]) break; | |
| 1994/0913 | strncpy(p->name, field[0], NAMELEN); p->beg = strtoul(field[1], 0, 0); p->end = strtoul(field[2], 0, 0); if(p->beg > p->end || p->beg >= d->table[0].end) break; p++; } } } d->npart = p - d->table; scsifree(b); qunlock(d); } static long sdio(Chan *c, int write, char *a, ulong len, ulong offset) { Disk *d; Part *p; uchar *b; ulong block, n, max, x; d = &disk[DRIVE(c->qid)]; p = &d->table[PART(c->qid)]; | |
| 1995/0403 | if(write && (d->inquire[0] & 0x1F) == TypeCD) error(Eperm); | |
| 1994/0913 | block = (offset / d->bsize) + p->beg; n = (offset + len + d->bsize - 1) / d->bsize + p->beg - block; max = SCSImaxxfer / d->bsize; if(n > max) n = max; if(block + n > p->end) n = p->end - block; if(block >= p->end || n == 0) return 0; b = scsialloc(n*d->bsize); if(b == 0) error(Enomem); if(waserror()) { scsifree(b); nexterror(); } offset %= d->bsize; if(write) { if(offset || len % d->bsize) { x = scsibio(d->t, d->lun, SCSIread, b, n, d->bsize, block); if(x < n * d->bsize) { n = x / d->bsize; x = n * d->bsize - offset; if(len > x) len = x; } } memmove(b + offset, a, len); x = scsibio(d->t, d->lun, SCSIwrite, b, n, d->bsize, block); if(x < offset) len = 0; else if(len > x - offset) len = x - offset; } else { x = scsibio(d->t, d->lun, SCSIread, b, n, d->bsize, block); if(x < offset) len = 0; else if(len > x - offset) len = x - offset; memmove(a, b+offset, len); } poperror(); scsifree(b); return len; } | |