| plan 9 kernel history: overview | file list | diff list |
1991/0115/port/devwren.c (diff list | history)
| port/devwren.c on 1991/0110 | ||
| 1991/0110 | #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" #include "devtab.h" #include "io.h" | |
| 1991/0112 | typedef struct Part Part; typedef struct Disk Disk; | |
| 1991/0110 | enum { | |
| 1991/0112 | Npart= 2, /* maximum partitions per disk */ Ndisk= 64, /* maximum disks */ | |
| 1991/0110 | ||
| 1991/0112 | Qdir= 0, Qdata= 16, Qstruct= 32, Mask= 0x7, | |
| 1991/0110 | }; | |
| 1991/0112 | static Dirtab *wrendir; #define NWREN (2*(Npart+1)) | |
| 1991/0110 | ||
| 1991/0112 | struct Part { ulong firstblock; ulong maxblock; }; struct Disk { ulong blocksize; Part p[Npart]; }; | |
| 1991/0110 | ||
| 1991/0112 | static Disk wren[Ndisk]; | |
| 1991/0110 | ||
| 1991/0115 | static Scsi staticcmd; /* BUG */ static uchar datablk[BY2PG]; /* BUG */ | |
| 1991/0112 | ||
| 1991/0115 | #define BGLONG(p) (((((((p)[0]<<8)|(p)[1])<<8)|(p)[2])<<8)|(p)[3]) | |
| 1991/0110 | /* * accepts [0-7].[0-7], or abbreviation */ static int wrendev(char *p) { int dev = 0; if (p==0 || p[0]==0) goto out; if (p[0]<'0' || p[0]>'7') goto cant; dev = (p[0]-'0')<<3; if (p[1]==0) goto out; if (p[1]!='.') goto cant; if (p[2]==0) goto out; if (p[2]<'0' || p[2]>'7') goto cant; dev |= p[2]-'0'; if (p[3]!=0) goto cant; out: | |
| 1991/0112 | if(dev >= Ndisk) error(Ebadarg); | |
| 1991/0110 | return dev; cant: error(Ebadarg); } static int wrengen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp) { long l; | |
| 1991/0112 | Part *p; Disk *d; if(s >= ntab) | |
| 1991/0110 | return -1; | |
| 1991/0112 | if(c->dev >= Ndisk) return -1; tab += s; d = &wren[c->dev]; p = &d->p[tab->qid.path&Mask]; if((tab->qid.path&~Mask) == Qdata) l = d->blocksize * (p->maxblock - p->firstblock); | |
| 1991/0110 | else | |
| 1991/0112 | l = 8; | |
| 1991/0110 | devdir(c, tab->qid, tab->name, l, tab->perm, dp); return 1; } void wrenreset(void) | |
| 1991/0112 | { Dirtab *p; int i; | |
| 1991/0110 | ||
| 1991/0112 | p = wrendir = ialloc((Npart+1) * 2 * sizeof(Dirtab), 0); for(i = 0; i < Npart; i++){ sprint(p->name, "data%d", i); p->qid.path = Qdata + i; p->perm = 0600; p++->length = 0; | |
| 1991/0115 | sprint(p->name, "struct%d", i); | |
| 1991/0112 | p->qid.path = Qstruct + i; p->perm = 0600; p++->length = 0; } strcpy(p->name, "data"); p->qid.path = Qdata + Npart; p->perm = 0600; p++->length = 0; strcpy(p->name, "struct"); p->qid.path = Qstruct + Npart; p->perm = 0600; p->length = 0; } | |
| 1991/0110 | void wreninit(void) { Scsi *cmd = &staticcmd; cmd->cmd.base = cmd->cmdblk; cmd->data.base = datablk; } /* * param is #r<target>.<lun> */ Chan * wrenattach(char *param) { uchar buf[32]; int dev; Chan *c; | |
| 1991/0112 | Disk *d; ulong plen; int i; | |
| 1991/0110 | dev = wrendev(param); scsiready(dev); scsisense(dev, buf); scsicap(dev, buf); c = devattach('r', param); c->dev = dev; | |
| 1991/0112 | d = &wren[dev]; d->blocksize = BGLONG(&buf[4]); plen = BGLONG(&buf[0]); d->p[Npart].firstblock = 0; d->p[Npart].maxblock = plen; plen = plen/Npart; for(i = 0; i < Npart; i++){ d->p[i].firstblock = i*plen; d->p[i].maxblock = (i+1)*plen; } | |
| 1991/0110 | return c; } Chan * wrenclone(Chan *c, Chan *nc) { return devclone(c, nc); } int wrenwalk(Chan *c, char *name) { return devwalk(c, name, wrendir, NWREN, wrengen); } void wrenstat(Chan *c, char *db) { devstat(c, db, wrendir, NWREN, wrengen); } Chan * wrenopen(Chan *c, int omode) { if (c->qid.path == Qdata && scsiready(c->dev) != 0) error(Eio); return devopen(c, omode, wrendir, NWREN, wrengen); } void wrencreate(Chan *c, char *name, int omode, ulong perm) { error(Eperm); } void wrenclose(Chan *c) {} #define PSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8)) #define PLONG(p, v) (PSHORT(p, (v)), PSHORT(p+2, (v)>>16)) long wrenread(Chan *c, char *a, long n) { Scsi *cmd = &staticcmd; unsigned long lbn; | |
| 1991/0112 | Part *p; Disk *d; | |
| 1991/0110 | if (n == 0) return 0; | |
| 1991/0112 | if(c->qid.path == CHDIR) | |
| 1991/0110 | return devdirread(c, a, n, wrendir, NWREN, wrengen); | |
| 1991/0112 | d = &wren[c->dev]; p = &(d->p[Mask&c->qid.path]); switch ((int)(c->qid.path & ~Mask)) { | |
| 1991/0110 | case Qdata: | |
| 1991/0112 | if (n % d->blocksize || c->offset % d->blocksize) | |
| 1991/0110 | error(Ebadarg); | |
| 1991/0112 | lbn = (c->offset/d->blocksize) + p->firstblock; if (lbn >= p->maxblock) | |
| 1991/0110 | error(Ebadarg); if (n > sizeof datablk) n = sizeof datablk; qlock(cmd); if (waserror()) { qunlock(cmd); nexterror(); } cmd->target = c->dev>>3; cmd->lun = c->dev&7; cmd->cmd.ptr = cmd->cmd.base; cmd->cmdblk[0] = 0x08; cmd->cmdblk[1] = lbn>>16; cmd->cmdblk[2] = lbn>>8; cmd->cmdblk[3] = lbn; | |
| 1991/0112 | cmd->cmdblk[4] = n/d->blocksize; | |
| 1991/0110 | cmd->cmdblk[5] = 0x00; cmd->cmd.lim = &cmd->cmdblk[6]; cmd->data.lim = cmd->data.base + n; cmd->data.ptr = cmd->data.base; cmd->save = cmd->data.base; scsiexec(cmd, 1); n = cmd->data.ptr - cmd->data.base; memcpy(a, cmd->data.base, n); qunlock(cmd); break; case Qstruct: if (n < 8) error(Ebadarg); if (c->offset >= 8) return 0; n = 8; | |
| 1991/0112 | PLONG((uchar *)&a[0], p->maxblock - p->firstblock); PLONG((uchar *)&a[4], d->blocksize); | |
| 1991/0110 | break; default: panic("wrenread"); } return n; } long wrenwrite(Chan *c, char *a, long n) { Scsi *cmd = &staticcmd; unsigned long lbn; | |
| 1991/0112 | Part *p; Disk *d; | |
| 1991/0110 | if (n == 0) return 0; | |
| 1991/0112 | d = &wren[c->dev]; p = &(d->p[Mask&c->qid.path]); switch ((int)(c->qid.path & ~Mask)) { | |
| 1991/0110 | case Qdata: | |
| 1991/0112 | if (n % d->blocksize || c->offset % d->blocksize) | |
| 1991/0110 | error(Ebadarg); | |
| 1991/0112 | lbn = c->offset/d->blocksize + p->firstblock; if (lbn >= p->maxblock) | |
| 1991/0110 | error(Ebadarg); if (n > sizeof datablk) n = sizeof datablk; qlock(cmd); if (waserror()) { qunlock(cmd); nexterror(); } cmd->target = c->dev>>3; cmd->lun = c->dev&7; cmd->cmd.ptr = cmd->cmd.base; cmd->cmdblk[0] = 0x0a; cmd->cmdblk[1] = lbn>>16; cmd->cmdblk[2] = lbn>>8; cmd->cmdblk[3] = lbn; | |
| 1991/0112 | cmd->cmdblk[4] = n/d->blocksize; | |
| 1991/0110 | cmd->cmdblk[5] = 0x00; cmd->cmd.lim = &cmd->cmdblk[6]; cmd->data.lim = cmd->data.base + n; cmd->data.ptr = cmd->data.base; cmd->save = cmd->data.base; memcpy(cmd->data.base, a, n); scsiexec(cmd, 0); n = cmd->data.ptr - cmd->data.base; qunlock(cmd); break; default: panic("wrenwrite"); } return n; } void wrenremove(Chan *c) { error(Eperm); } void wrenwstat(Chan *c, char *dp) { error(Eperm); } | |