## diffname port/devsd.c 1994/0913
## diff -e /dev/null /n/fornaxdump/1994/0913/sys/src/brazil/port/devsd.c
0a
/*
* 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"
enum
{
LogNpart = 3,
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);
static int
sdgen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp)
{
Qid qid;
Disk *d;
Part *p;
int unit;
char name[2*NAMELEN];
USED(tab, ntab);
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;
int dev, i;
dev = 0;
for(;;) {
d = &disk[ndisk];
dev = scsiinv(dev, 0, &d->t, &d->inquire, d->id);
if(dev < 0)
break;
if(scsistart(d->t, 0, 1) != STok)
continue;
/* Search for other lun's */
for(i = 0; i < Nlun; i++) {
d->lun = i;
scsireqsense(d->t, d->lun, 1);
/* NCR Raid only seems to answer second capacity
* command if lun != 0
*/
if(scsicap(d->t, d->lun, &s, &b) != STok) {
scsireqsense(d->t, 0, 1);
continue;
}
scsireqsense(d->t, 0, 1);
s = 0;
b = 0;
if(scsicap(d->t, d->lun, &s, &b) != STok) {
scsireqsense(d->t, 0, 1);
continue;
}
if(scsireqsense(d->t, d->lun, 1) != STok)
continue;
if(s == 0 || b == 0)
continue;
d->size = s;
d->bsize = b;
sprint(d->vol, "sd%d", ndisk);
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
sdcreate(Chan *c, char *name, int omode, ulong perm)
{
USED(c, name, omode, perm);
error(Eperm);
}
void
sdremove(Chan *c)
{
USED(c);
error(Eperm);
}
void
sdwstat(Chan *c, char *dp)
{
USED(c, dp);
error(Eperm);
}
void
sdclose(Chan *c)
{
Disk *d;
Part *p;
if(c->mode != OWRITE && c->mode != ORDWR)
return;
d = &disk[DRIVE(c->qid)];
p = &d->table[PART(c->qid)];
if(strcmp(p->name, "partition"))
return;
sdrdpart(d);
}
long
sdread(Chan *c, void *a, long n, ulong offset)
{
if(c->qid.path == CHDIR)
return devdirread(c, a, n, 0, 0, sdgen);
return sdio(c, 0, a, n, offset);
}
long
sdwrite(Chan *c, char *a, long n, ulong offset)
{
return sdio(c, 1, a, n, offset);
}
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;
scsibio(d->t, d->lun, SCSIread, b, 1, d->bsize, d->table[0].end-1);
b[d->bsize-1] = '\0';
/*
* parse partition table.
*/
n = getfields(b, line, Npart+2, '\n');
if(n > 0 && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0) {
for(i = 1; i < n; i++) {
switch(getfields(line[i], field, 3, ' ')) {
case 2:
if(strcmp(field[0], "unit") == 0)
strncpy(d->vol, field[1], NAMELEN);
break;
case 3:
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)];
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;
}
.
## diffname port/devsd.c 1994/1228
## diff -e /n/fornaxdump/1994/0913/sys/src/brazil/port/devsd.c /n/fornaxdump/1994/1228/sys/src/brazil/port/devsd.c
278a
if(p >= &d->table[Npart])
break;
.
147a
print("sd out\n");
.
14c
LogNpart = 4,
.
## diffname port/devsd.c 1994/1230
## diff -e /n/fornaxdump/1994/1228/sys/src/brazil/port/devsd.c /n/fornaxdump/1994/1230/sys/src/brazil/port/devsd.c
148d
## diffname port/devsd.c 1995/0108
## diff -e /n/fornaxdump/1994/1230/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0108/sys/src/brazil/port/devsd.c
235a
}
long
sdbwrite(Chan *c, Block *bp, ulong offset)
{
return devbwrite(c, bp, offset);
.
231a
Block*
sdbread(Chan *c, long n, ulong offset)
{
return devbread(c, n, offset);
}
.
## diffname port/devsd.c 1995/0117
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0117/sys/src/brazil/port/devsd.c
285c
switch(getfields(line[i], field, 3, " ")) {
.
282c
n = getfields(b, line, Npart+2, "\n");
.
## diffname port/devsd.c 1995/0324
## diff -e /n/fornaxdump/1995/0117/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0324/sys/src/brazil/port/devsd.c
214a
print("sdclose: qid 0x%lux drive %d, part %d\n", c->qid, DRIVE(c->qid), PART(c->qid));
.
## diffname port/devsd.c 1995/0325
## diff -e /n/fornaxdump/1995/0324/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0325/sys/src/brazil/port/devsd.c
227c
if(c->qid.path & CHDIR)
.
218,221c
if((c->mode&3) != OREAD && strcmp(p->name, "partition") == 0)
sdrdpart(d);
.
215d
212c
if(c->qid.path & CHDIR)
.
202d
200c
sdwstat(Chan*, char*)
.
195d
193c
sdremove(Chan*)
.
188d
186c
sdcreate(Chan*, char*, int, ulong)
.
63,64d
55c
sdgen(Chan *c, Dirtab*, long, long s, Dir *dirp)
.
## diffname port/devsd.c 1995/0329
## diff -e /n/fornaxdump/1995/0325/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0329/sys/src/brazil/port/devsd.c
105a
/*
* 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;
.
104a
.
90c
uchar inq[255];
int dev, i, nbytes;
.
## diffname port/devsd.c 1995/0403
## diff -e /n/fornaxdump/1995/0329/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0403/sys/src/brazil/port/devsd.c
321a
if(write && (d->inquire[0] & 0x1F) == TypeCD)
error(Eperm);
.
280a
if((d->inquire[0] & 0x1F) == TypeCD){
scsifree(b);
qunlock(d);
return;
}
.
144a
case TypeDA:
case TypeWO:
case TypeMO:
sprint(d->vol, "sd%d", ndisk);
break;
case TypeCD:
sprint(d->vol, "cd%d", ndisk);
break;
default:
continue;
}
.
143c
switch(d->inquire[0] & 0x1F){
.
96c
dev = scsiinv(dev, types, &d->t, &d->inquire, d->id);
.
53a
static int types[] = {
TypeDA, TypeWO, TypeCD, TypeMO,
-1,
};
.
11a
enum {
TypeDA = 0x00, /* Direct Access */
TypeWO = 0x04, /* Worm */
TypeCD = 0x05, /* CD-ROM */
TypeMO = 0x07, /* rewriteable Magneto-Optical */
};
.
## diffname port/devsd.c 1995/0404
## diff -e /n/fornaxdump/1995/0403/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0404/sys/src/brazil/port/devsd.c
169a
print("sd6|");
.
158d
151a
print("sd5/0x%2.2ux|", d->inquire[0]);
.
147,149d
145a
print("sd4/%d/%d|", s, b);
.
143c
scsireqsense(d->t, 0, 0);
.
131,139d
129a
print("sd3|");
.
119,120d
117a
print("sd2|");
.
112,113c
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|");
.
62c
TypeDA, TypeCD, TypeMO,
.
16a
TYpeMC = 0x08, /* Medium Changer */
.
13a
TypeSA = 0x01, /* Sequential Access */
.
## diffname port/devsd.c 1995/0405
## diff -e /n/fornaxdump/1995/0404/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0405/sys/src/brazil/port/devsd.c
287d
283a
/*
* If the drive wasn't ready when we tried to do a
* read-capacity earlier (in sdinit()), try again.
* It might be possible to be smarter here, and look at the
* response from a test-unit-ready which would show if the
* target was in the process of becoming ready.
*/
if(d->size == 0 || d->bsize == 0){
if(scsicap(d->t, d->lun, &d->size, &d->bsize) != STok){
d->size = d->bsize = 0;
error(Eio);
}
}
.
164d
148,151d
144,146c
switch(type){
.
142d
140a
type = scratch[0] & 0x1F;
/*
* Read-capacity is mandatory for TypeDA, TypeMO and TypeCD.
* It may return 'not ready' if TypeDA is not spun up,
* TypeMO or TypeCD are not loaded or just plain slow getting
* their act together after a reset.
* If 'not ready' comes back, try starting a TypeDA and punt
* the get capacity until the drive is attached.
* It might be possible to be smarter here, and look at the
* response from a test-unit-ready which would show if the
* target was in the process of becoming ready.
*/
if(scsicap(d->t, d->lun, &d->size, &d->bsize) != STok) {
nbytes = sizeof(scratch);
memset(scratch, 0, nbytes);
scsireqsense(d->t, 0, scratch, &nbytes, 1);
if((scratch[2] & 0x0F) != 0x02)
continue;
if(type == TypeDA)
scsistart(d->t, d->lun, 0);
d->size = d->bsize = 0;
.
134,139c
if(scratch[0] == 0x7F)
.
130,132c
nbytes = sizeof(scratch);
memset(scratch, 0, nbytes);
if(scsiinquiry(d->t, d->lun, scratch, &nbytes) != STok)
.
123d
114,120c
/*
* Search for all the lun's.
*/
.
103,104c
uchar scratch[0xFF], type;
.
## diffname port/devsd.c 1995/0416
## diff -e /n/fornaxdump/1995/0405/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0416/sys/src/brazil/port/devsd.c
364a
if(d->bsize == 0)
error(Eio);
.
287,300d
189,191c
/*
* If the drive wasn't ready when we tried to do a
* read-capacity earlier (in sdinit()), try again.
* It might be possible to be smarter here, and look at the
* response from a test-unit-ready which would show if the
* target was in the process of becoming ready.
*/
nfound = 0;
for(i = 0; i < ndisk; i++){
d = &disk[i];
if(waserror()){
poperror();
continue;
}
if(d->size == 0 || d->bsize == 0){
if(scsicap(d->t, d->lun, &d->size, &d->bsize) != STok){
d->size = d->bsize = 0;
continue;
}
}
sdrdpart(d);
nfound++;
poperror();
}
if(nfound == 0)
return 0;
.
187c
int i, nfound;
Disk *d;
.
## diffname port/devsd.c 1995/0417
## diff -e /n/fornaxdump/1995/0416/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0417/sys/src/brazil/port/devsd.c
376,378d
311a
/*
* If the drive wasn't ready when we tried to do a
* read-capacity earlier (in sdinit()), try again.
* It might be possible to be smarter here, and look at the
* response from a test-unit-ready which would show if the
* target was in the process of becoming ready.
*/
if(d->size == 0 || d->bsize == 0){
if(scsicap(d->t, d->lun, &d->size, &d->bsize) != STok){
d->size = d->bsize = 0;
error(Eio);
}
}
.
190,216c
for(i = 0; i < ndisk; i++)
sdrdpart(&disk[i]);
.
187,188c
int i;
.
## diffname port/devsd.c 1995/0722
## diff -e /n/fornaxdump/1995/0417/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0722/sys/src/brazil/port/devsd.c
63c
static int types[] =
{
.
12c
enum
{
.
## diffname port/devsd.c 1995/0909
## diff -e /n/fornaxdump/1995/0722/sys/src/brazil/port/devsd.c /n/fornaxdump/1995/0909/sys/src/brazil/port/devsd.c
149c
if((scratch[2] & 0x0F) != 0x02 && (scratch[2] & 0x0F) != 0)
.
## diffname port/devsd.c 1996/0223
## diff -e /n/fornaxdump/1995/0909/sys/src/brazil/port/devsd.c /n/fornaxdump/1996/0223/sys/src/brazil/port/devsd.c
10d
## diffname port/devsd.c 1996/0315
## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/port/devsd.c /n/fornaxdump/1996/0315/sys/src/brazil/port/devsd.c
334c
switch(parsefields(line[i], field, 3, " ")) {
.
331c
n = parsefields(b, line, Npart+2, "\n");
.
## diffname port/devsd.c 1996/0607
## diff -e /n/fornaxdump/1996/0315/sys/src/brazil/port/devsd.c /n/fornaxdump/1996/0607/sys/src/brazil/port/devsd.c
415c
buggery:
.
407a
if(x < 0){
len = -1;
goto buggery;
}
.
399a
if(x < 0){
len = -1;
goto buggery;
}
.
390a
if(x < 0){
len = -1;
goto buggery;
}
.
382,386c
return scsierrstr(STnomem);
.
367,369d
353c
d->partok = 1;
return STok;
.
334,348c
if(parsefields(line[i], field, 3, " ") != 3)
break;
if(p >= &d->table[Npart])
break;
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++;
.
319,324d
309,311d
304,307c
return scsierrstr(STnomem);
.
301a
p->end = d->size + 1;
if((d->inquire[0] & 0x1F) == TypeCD)
return STok;
.
298c
return scsierrstr(n);
.
296c
n = scsicap(d->t, d->lun, &d->size, &d->bsize);
if(n != STok){
.
289,293c
* If the drive wasn't ready when a read-capacity was tried
* earlier (in sdinit()), try again.
.
287a
if(d->partok)
return STok;
p = d->table;
strcpy(p->name, "disk");
p->beg = 0;
p->end = 0;
d->npart = 1;
.
280c
static int
.
270a
Disk *d;
d = &disk[DRIVE(c->qid)];
if((d->inquire[0] & 0x1F) == TypeCD)
error(Eperm);
.
250a
qunlock(d);
}
.
249c
if((c->mode&3) != OREAD && strcmp(p->name, "partition") == 0){
qlock(d);
d->partok = 0;
.
190,191c
for(i = 0; i < ndisk; i++){
qlock(&disk[i]);
if(disk[i].partok == 0)
sdrdpart(&disk[i]);
qunlock(&disk[i]);
}
.
140,142d
60c
static int sdrdpart(Disk*);
.
49a
int partok;
ulong version;
.
## diffname port/devsd.c 1996/0710
## diff -e /n/fornaxdump/1996/0607/sys/src/brazil/port/devsd.c /n/fornaxdump/1996/0710/sys/src/brazil/port/devsd.c
181a
scsifree(scratch);
.
127c
nbytes = 0xFF;
.
109a
scratch = scsialloc(0xFF);
.
106c
uchar *scratch, type;
.
## diffname port/devsd.c 1996/1225
## diff -e /n/fornaxdump/1996/0710/sys/src/brazil/port/devsd.c /n/fornaxdump/1996/1225/sys/src/brazil/port/devsd.c
72c
sdgen(Chan *c, Dirtab*, int, int s, Dir *dirp)
.
## diffname port/devsd.c 1997/0327
## diff -e /n/fornaxdump/1996/1225/sys/src/brazil/port/devsd.c /n/emeliedump/1997/0327/sys/src/brazil/port/devsd.c
349c
if(parsefields(line[i], field, nelem(field), " ") != 3)
.
346c
n = parsefields(b, line, nelem(line), "\n");
.
289,293c
Dev sddevtab = {
devreset,
sdinit,
sdattach,
devclone,
sdwalk,
sdstat,
sdopen,
devcreate,
sdclose,
sdread,
devbread,
sdwrite,
devbwrite,
devremove,
devwstat,
};
.
271,277c
static long
.
262c
static long
.
225,243c
static void
.
219c
static Chan*
.
213c
static void
.
201,207c
static int
.
186c
static Chan*
.
145c
nbytes = 0xFF;
.
97,102c
static void
.
## diffname port/devsd.c 1997/0408
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/devsd.c /n/emeliedump/1997/0408/sys/src/brazil/port/devsd.c
254a
'w',
"sd",
.
## diffname port/devsd.c 1998/0319
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/port/devsd.c /n/emeliedump/1998/0319/sys/src/brazil/port/devsd.c
245a
ulong offset = off;
.
243c
sdwrite(Chan *c, char *a, long n, vlong off)
.
235a
ulong offset = off;
.
234c
sdread(Chan *c, void *a, long n, vlong off)
.
## diffname port/devsd.c 1998/0325
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/port/devsd.c /n/emeliedump/1998/0325/sys/src/brazil/port/devsd.c
358a
ulong offset = off;
.
353c
sdio(Chan *c, int write, char *a, ulong len, vlong off)
.
248d
245c
sdwrite(Chan *c, char *a, long n, vlong offset)
.
236d
234c
sdread(Chan *c, void *a, long n, vlong offset)
.
63c
static long sdio(Chan*, int, char*, ulong, vlong);
.
## diffname port/devsd.c 1998/0327
## diff -e /n/emeliedump/1998/0325/sys/src/brazil/port/devsd.c /n/emeliedump/1998/0327/sys/src/brazil/port/devsd.c
376c
offset = off % d->bsize;
.
362,363c
block = (off / d->bsize) + p->beg;
n = (off + len + d->bsize - 1) / d->bsize + p->beg - block;
.
357c
ulong offset;
.
252c
return sdio(c, 1, a, n, off);
.
244c
sdwrite(Chan *c, char *a, long n, vlong off)
.
240c
return sdio(c, 0, a, n, off);
.
234c
sdread(Chan *c, void *a, long n, vlong off)
.
## diffname port/devsd.c 1998/0512
## diff -e /n/emeliedump/1998/0327/sys/src/brazil/port/devsd.c /n/emeliedump/1998/0512/sys/src/brazil/port/devsd.c
192c
.
## diffname port/devsd.c 1998/0930
## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/devsd.c /n/emeliedump/1998/0930/sys/src/brazil/port/devsd.c
144a
}
.
143c
switch(scratch[2] & 0x0F){
case 0x00:
case 0x01:
case 0x02:
break;
case 0x06:
if(scratch[12] == 0x28 && scratch[13] == 0)
break;
if(scratch[12] == 0x29 && scratch[13] == 0)
break;
/*FALLTHROUGH*/
default:
.
124a
.
## diffname port/devsd.c 1998/1022
## diff -e /n/emeliedump/1998/0930/sys/src/brazil/port/devsd.c /n/emeliedump/1998/1022/sys/src/brazil/port/devsd.c
93c
l = (p->end - p->beg) * (vlong)d->bsize;
devdir(c, qid, name, l, eve, 0666, dirp);
.
78a
vlong l;
.
## diffname port/devsd.c 1999/0228
## diff -e /n/emeliedump/1998/1022/sys/src/brazil/port/devsd.c /n/emeliedump/1999/0228/sys/src/brazil/port/devsd.c
155c
if(scratch[12] == 0x29 && !scratch[13])
.
153c
if(scratch[12] == 0x28 && !scratch[13])
.
135,140c
* Read-capacity is mandatory for TypeDA, TypeMO and
* TypeCD. It may return 'not ready' if TypeDA is not
* spun up, TypeMO or TypeCD are not loaded or just
* plain slow getting their act together after a reset.
* If 'not ready' comes back, try starting a TypeDA and
* punt the get capacity until the drive is attached.
.
## diffname port/devsd.c 1999/0320
## diff -e /n/emeliedump/1999/0228/sys/src/brazil/port/devsd.c /n/emeliedump/1999/0320/sys/src/brazil/port/devsd.c
260c
sdwrite(Chan *c, void *a, long n, vlong off)
.
## diffname port/devsd.c 1999/0507
## diff -e /n/emeliedump/1999/0320/sys/src/brazil/port/devsd.c /n/emeliedump/1999/0507/sys/src/brazil/port/devsd.c
45c
int lun;
.
## diffname port/devsd.c 1999/0728
## diff -e /n/emeliedump/1999/0507/sys/src/brazil/port/devsd.c /n/emeliedump/1999/0728/sys/src/brazil/port/devsd.c
73a
.
## diffname port/devsd.c 1999/1230
## diff -e /n/emeliedump/1999/0728/sys/src/brazil/port/devsd.c /n/emeliedump/1999/1230/sys/src/9/port/devsd.c
81a
if(s == DEVDOTDOT){
devdir(c, qid, "#w", 0, eve, 0555, dirp);
return 1;
}
.
## diffname port/devsd.c 2000/0104
## diff -e /n/emeliedump/1999/1230/sys/src/9/port/devsd.c /n/emeliedump/2000/0104/sys/src/9/port/devsd.c
349d
344a
n = parsefields(b, line, nelem(line), "\n");
if(n <= 0 || strncmp(line[0], MAGIC, sizeof(MAGIC)-1) != 0){
/* try the last */
scsibio(d->t, d->lun, SCSIread, b, 1, d->bsize, d->table[0].end-1);
b[d->bsize-1] = '\0';
n = parsefields(b, line, nelem(line), "\n");
/* only point partition file at last sector if there is one there */
if(n > 0 && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
d->table[1].beg++;
d->table[1].end++;
}
}
.
343c
/*
* Read second last sector from disk, null terminate.
* The last sector used to hold the partition tables.
* However, this sector is special on some PC's so we've
* started to use the second last sector as the partition
* table instead. To avoid reconfiguring all our old systems
* we still check if there is a valid partition table in
* the last sector if none is found in the second last.
*/
scsibio(d->t, d->lun, SCSIread, b, 1, d->bsize, d->table[0].end-2);
.
338,339c
p->beg = d->table[0].end - 2;
p->end = d->table[0].end - 1;
.
74d
## diffname port/devsd.c 2000/0308
## diff -e /n/emeliedump/2000/0104/sys/src/9/port/devsd.c /n/emeliedump/2000/0308/sys/src/9/port/devsd.c
371c
if(getfields(line[i], field, nelem(field), 1, " ") != 3)
.
358c
n = getfields(b, line, nelem(line), 1, "\n");
.
353c
n = getfields(b, line, nelem(line), 1, "\n");
.
## diffname port/devsd.c 2000/0506
## diff -e /n/emeliedump/2000/0308/sys/src/9/port/devsd.c /n/emeliedump/2000/0506/sys/src/9/port/devsd.c
461a
Dev sddevtab = {
'S',
"sd",
sdreset,
devinit,
sdattach,
sdclone,
sdwalk,
sdstat,
sdopen,
devcreate,
sdclose,
sdread,
devbread,
sdwrite,
devbwrite,
devremove,
sdwstat,
};
.
458,460c
if(unit->changed)
error(Enonexist);
pp = &unit->part[PART(c->qid)];
if(!pp->valid)
error(Enonexist);
if(strcmp(up->user, pp->user) && !iseve())
error(Eperm);
convM2D(dp, &d);
strncpy(pp->user, d.uid, NAMELEN);
pp->perm = d.mode&0777;
qunlock(&unit->ctl);
poperror();
.
444,455c
return n;
}
static void
sdwstat(Chan* c, char* dp)
{
Dir d;
SDpart *pp;
SDunit *unit;
if((c->qid.path & CHDIR) || TYPE(c->qid) != Qpart)
error(Eperm);
unit = sdunit[UNIT(c->qid)];
qlock(&unit->ctl);
if(waserror()){
qunlock(&unit->ctl);
nexterror();
.
438,442c
break;
case Qpart:
return sdbio(c, 1, a, n, off);
.
432,436c
else{
if(unit->pid != up->pid)
error(Eperm);
if(unit->state != Rawdata)
error(Ebadusefd);
unit->state = Rawstatus;
unit->req->write = 1;
return sdrio(unit->req, a, n);
.
430a
if((req = malloc(sizeof(SDreq))) == nil){
qunlock(&unit->raw);
error(Enomem);
}
req->unit = unit;
memmove(req->cmd, a, n);
req->clen = n;
req->flags = SDnosense;
req->status = ~0;
unit->req = req;
unit->pid = up->pid;
unit->state = Rawdata;
.
425,429c
if(n < 6 || n > sizeof(req->cmd)){
qunlock(&unit->raw);
error(Ebadarg);
.
413,423c
if(cb->nf < 1)
error(Ebadctl);
if(strcmp(cb->f[0], "part") == 0){
if(cb->nf != 4 || unit->npart >= SDnpart)
error(Ebadctl);
if(unit->sectors == 0 && !sdinitpart(unit))
error(Eio);
start = strtoul(cb->f[2], 0, 0);
end = strtoul(cb->f[3], 0, 0);
sdaddpart(unit, cb->f[1], start, end);
}
else if(strcmp(cb->f[0], "delpart") == 0){
if(cb->nf != 2 || unit->part == nil)
error(Ebadctl);
sddelpart(unit, cb->f[1]);
}
else if(unit->dev->ifc->wctl)
unit->dev->ifc->wctl(unit, cb);
else
error(Ebadctl);
qunlock(&unit->ctl);
poperror();
free(cb);
break;
case Qraw:
unit = sdunit[UNIT(c->qid)];
if(canqlock(&unit->raw)){
if(unit->state != Rawcmd){
qunlock(&unit->raw);
error(Ebadusefd);
.
403,411c
qlock(&unit->ctl);
if(waserror()){
qunlock(&unit->ctl);
free(cb);
nexterror();
}
if(unit->changed)
error(Eio);
.
400,401c
switch(TYPE(c->qid)){
default:
error(Eperm);
case Qctl:
cb = parsecmd(a, n);
unit = sdunit[UNIT(c->qid)];
.
394,398c
Cmdbuf *cb;
SDreq *req;
SDunit *unit;
ulong end, start;
.
392c
sdwrite(Chan *c, void *a, long n, vlong off)
.
386,388c
return 0;
.
383,384d
381a
if(unit->pid != up->pid)
error(Eperm);
if(unit->state == Rawdata){
unit->state = Rawstatus;
return sdrio(unit->req, a, n);
}
else if(unit->state == Rawstatus){
status = unit->req->status;
unit->pid = 0;
unit->state = Rawcmd;
free(unit->req);
unit->req = nil;
qunlock(&unit->raw);
return readnum(0, a, n, status, NUMSIZE);
}
break;
case Qpart:
return sdbio(c, 0, a, n, off);
.
364,380c
qunlock(&unit->ctl);
l = readstr(offset, a, n, p);
free(p);
return l;
case Qraw:
unit = sdunit[UNIT(c->qid)];
if(canqlock(&unit->raw)){
qunlock(&unit->raw);
error(Ebadusefd);
.
342,362c
offset = off;
switch(TYPE(c->qid)){
default:
error(Eperm);
case Qtopdir:
case Qunitdir:
return devdirread(c, a, n, 0, 0, sdgen);
case Qctl:
unit = sdunit[UNIT(c->qid)];
p = malloc(READSTR);
l = snprint(p, READSTR, "inquiry %.48s\n",
(char*)unit->inquiry+8);
qlock(&unit->ctl);
if(!unit->changed && unit->sectors){
/*
* If there's a device specific routine it must
* provide all information pertaining to night geometry
* and the garscadden trains.
*/
if(unit->dev->ifc->rctl)
l += unit->dev->ifc->rctl(unit, p+l, READSTR-l);
else
l += snprint(p+l, READSTR-l,
"geometry %ld %ld\n",
unit->sectors, unit->secsize);
pp = unit->part;
for(i = 0; i < SDnpart; i++){
if(pp->valid)
l += snprint(p+l, READSTR-l,
"part %.*s %lud %lud\n",
NAMELEN, pp->name,
pp->start, pp->end);
pp++;
}
.
335,340c
static long
sdread(Chan *c, void *a, long n, vlong off)
{
char *p;
SDpart *pp;
SDunit *unit;
ulong offset;
int i, l, status;
.
331,333c
return r->rlen;
}
.
328,329c
if(!r->write && r->rlen > 0)
memmove(a, data, r->rlen);
if(data != nil){
sdfree(data);
r->data = nil;
}
poperror();
.
326c
if(r->unit->dev->ifc->rio(r) != SDok)
error(Eio);
.
323a
nexterror();
.
314,322c
if(waserror()){
if(data != nil){
sdfree(data);
r->data = nil;
.
308,312c
data = nil;
if(n){
if((data = sdmalloc(n)) == nil)
error(Enomem);
if(r->write)
memmove(data, a, n);
}
r->data = data;
r->dlen = n;
.
305,306c
if(n >= SDmaxio || n < 0)
error(Etoobig);
.
300,303c
void *data;
.
297,298c
static long
sdrio(SDreq* r, void* a, long n)
.
280,295c
return len;
}
.
276,278c
if(unit->inquiry[1] & 0x80){
qunlock(&unit->ctl);
poperror();
}
.
271,274c
offset = off%unit->secsize;
if(write){
if(offset || (len%unit->secsize)){
if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0)
error(Eio);
if(l < (nb*unit->secsize)){
nb = l/unit->secsize;
l = nb*unit->secsize - offset;
if(len > l)
len = l;
}
}
memmove(b+offset, a, len);
if((l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno)) < 0)
error(Eio);
if(l < offset)
len = 0;
else if(len > l - offset)
len = l - offset;
}
else {
if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0)
error(Eio);
if(l < offset)
len = 0;
else if(len > l - offset)
len = l - offset;
memmove(a, b+offset, len);
}
sdfree(b);
poperror();
.
269c
b = sdmalloc(nb*unit->secsize);
if(b == nil)
error(Enomem);
if(waserror()){
sdfree(b);
nexterror();
}
.
264,267c
/*
* Check the request is within bounds.
* Removeable drives are locked throughout the I/O
* in case the media changes unexpectedly.
* Non-removeable drives are not locked during the I/O
* to allow the hardware to optimise if it can; this is
* a little fast and loose.
* It's assumed that non-removeable media parameters
* (sectors, secsize) can't change once the drive has
* been brought online.
*/
pp = &unit->part[PART(c->qid)];
bno = (off/unit->secsize) + pp->start;
nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
max = SDmaxio/unit->secsize;
if(nb > max)
nb = max;
if(bno+nb > pp->end)
nb = pp->end - bno;
if(bno >= pp->end || nb == 0){
if(write)
error(Eio);
qunlock(&unit->ctl);
poperror();
return 0;
}
if(!(unit->inquiry[1] & 0x80)){
qunlock(&unit->ctl);
poperror();
}
.
261,262c
qlock(&unit->ctl);
if(waserror()){
qunlock(&unit->ctl);
nexterror();
}
if(unit->changed)
error(Eio);
.
258,259c
unit = sdunit[UNIT(c->qid)];
.
256a
long l;
uchar *b;
SDpart *pp;
SDunit *unit;
ulong bno, max, nb, offset;
.
255c
sdbio(Chan* c, int write, char* a, long len, vlong off)
.
244,250c
switch(TYPE(c->qid)){
default:
break;
case Qraw:
unit = sdunit[UNIT(c->qid)];
if(canqlock(&unit->raw) || unit->pid == up->pid){
unit->pid = 0;
unit->state = Rawcmd;
qunlock(&unit->raw);
}
break;
case Qpart:
unit = sdunit[UNIT(c->qid)];
qlock(&unit->ctl);
if(waserror()){
qunlock(&unit->ctl);
c->flag &= ~COPEN;
nexterror();
}
pp = &unit->part[PART(c->qid)];
pp->nopen--;
unit->nopen--;
if(unit->nopen == 0)
unit->changed = 0;
qunlock(&unit->ctl);
poperror();
break;
.
242a
if(!(c->flag & COPEN))
return;
.
238,239c
SDpart *pp;
SDunit *unit;
.
236c
sdclose(Chan* c)
.
232c
SDpart *pp;
SDunit *unit;
c = devopen(c, omode, 0, 0, sdgen);
switch(TYPE(c->qid)){
default:
break;
case Qpart:
unit = sdunit[UNIT(c->qid)];
qlock(&unit->ctl);
if(waserror()){
qunlock(&unit->ctl);
c->flag &= ~COPEN;
nexterror();
}
if(unit->changed)
error(Eio);
pp = &unit->part[PART(c->qid)];
pp->nopen++;
unit->nopen++;
qunlock(&unit->ctl);
poperror();
break;
}
return c;
.
230c
sdopen(Chan* c, int omode)
.
226c
devstat(c, db, nil, 0, sdgen);
.
224c
sdstat(Chan* c, char* db)
.
220c
return devwalk(c, name, nil, 0, sdgen);
.
218c
sdwalk(Chan* c, char* name)
.
216a
static Chan*
sdclone(Chan* c, Chan* nc)
{
return devclone(c, nc);
}
.
214c
if(spec[0] != 's' || spec[1] != 'd')
error(Ebadspec);
idno = spec[2];
subno = strtol(&spec[3], &p, 0);
if(p == &spec[3])
error(Ebadspec);
for(sdev = sdlist; sdev != nil; sdev = sdev->next){
if(sdev->idno == idno && subno < sdev->nunit)
break;
}
if(sdev == nil || sdgetunit(sdev, subno) == nil)
error(Enonexist);
c = devattach(sddevtab.dc, spec);
c->qid = (Qid){QID(sdev->index+subno, 0, Qunitdir)|CHDIR, 0};
c->dev = sdev->index+subno;
return c;
.
207,211c
if(sdnunit == 0 || *spec == '\0'){
c = devattach(sddevtab.dc, spec);
c->qid = (Qid){QID(0, 0, Qtopdir)|CHDIR, 0};
return c;
.
205c
Chan *c;
char *p;
SDev *sdev;
int idno, subno;
.
203c
sdattach(char* spec)
.
199c
return -1;
.
197a
if(s < sdnunit){
if(sdunit[s] == nil && sdindex2unit(s) == nil)
return 0;
q = (Qid){QID(s, 0, Qunitdir)|CHDIR, 0};
devdir(c, q, sdunit[s]->name, 0, eve, 0555, dp);
return 1;
}
s -= sdnunit;
return sd1gen(c, s+Qtopbase, dp);
case Qunitdir:
if(s == DEVDOTDOT){
q = (Qid){QID(0, 0, Qtopdir)|CHDIR, 0};
snprint(name, NAMELEN, "#%C", sddevtab.dc);
devdir(c, q, name, 0, eve, 0555, dp);
return 1;
}
unit = sdunit[UNIT(c->qid)];
qlock(&unit->ctl);
if(!unit->changed && unit->sectors == 0)
sdinitpart(unit);
i = s+Qunitbase;
if(i < Qpart){
r = sd2gen(c, i, dp);
qunlock(&unit->ctl);
return r;
}
i -= Qpart;
if(unit->npart == 0 || i >= SDnpart){
qunlock(&unit->ctl);
break;
}
pp = &unit->part[i];
if(unit->changed || !pp->valid){
qunlock(&unit->ctl);
return 0;
}
l = (pp->end - pp->start) * (vlong)unit->secsize;
q = (Qid){QID(UNIT(c->qid), i, Qpart), c->qid.vers};
devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
qunlock(&unit->ctl);
return 1;
case Qraw:
case Qctl:
case Qpart:
unit = sdunit[UNIT(c->qid)];
qlock(&unit->ctl);
r = sd2gen(c, TYPE(c->qid), dp);
qunlock(&unit->ctl);
return r;
default:
break;
.
196a
pp = &unit->part[PART(c->qid)];
l = (pp->end - pp->start) * (vlong)unit->secsize;
q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qpart), c->qid.vers};
devdir(c, q, pp->name, l, pp->user, pp->perm, dp);
return 1;
}
return -1;
}
static int
sd1gen(Chan*, int i, Dir*)
{
switch(i){
default:
return -1;
}
return -1;
}
static int
sdgen(Chan* c, Dirtab*, int, int s, Dir* dp)
{
Qid q;
vlong l;
int i, r;
SDpart *pp;
SDunit *unit;
char name[NAMELEN];
switch(TYPE(c->qid)){
case Qtopdir:
if(s == DEVDOTDOT){
q = (Qid){QID(0, 0, Qtopdir)|CHDIR, 0};
snprint(name, NAMELEN, "#%C", sddevtab.dc);
devdir(c, q, name, 0, eve, 0555, dp);
return 1;
.
194,195c
/*
* Legacy and option code goes here. This will be hard...
*/
/*
* The maximum number of possible units is known, allocate
* placeholders for their datastructures; the units will be
* probed and structures allocated when attached.
* Allocate controller names for the different types.
*/
if(sdnunit == 0)
return;
if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil)
return;
if((sdunitflg = malloc(sdnunit*sizeof(int))) == nil){
free(sdunit);
sdunit = nil;
return;
}
for(i = 0; sdifc[i] != nil; i++){
if(sdifc[i]->id)
sdifc[i]->id(sdlist);
}
}
static int
sd2gen(Chan* c, int i, Dir* dp)
{
Qid q;
vlong l;
SDpart *pp;
SDunit *unit;
switch(i){
case Qctl:
q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qctl), c->qid.vers};
devdir(c, q, "ctl", 0, eve, 0640, dp);
return 1;
case Qraw:
q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qraw), c->qid.vers};
devdir(c, q, "raw", 0, eve, 0600, dp);
return 1;
case Qpart:
unit = sdunit[UNIT(c->qid)];
if(unit->changed)
.
192a
tail->index = sdnunit;
sdnunit += tail->nunit;
}
.
186,191c
static void
sdreset(void)
{
int i;
SDev *sdev, *tail;
/*
* Probe all configured controllers and make a list
* of devices found, accumulating a possible maximum number
* of units attached and marking each device with an index
* into the linear top-level directory array of units.
*/
tail = nil;
for(i = 0; sdifc[i] != nil; i++){
if(sdifc[i]->pnp == nil || (sdev = sdifc[i]->pnp()) == nil)
continue;
if(sdlist != nil)
tail->next = sdev;
else
sdlist = sdev;
for(tail = sdev; tail->next != nil; tail = tail->next){
sdev->index = sdnunit;
sdnunit += tail->nunit;
.
182,184c
}
.
178,180c
return nil;
.
173,176c
/*
* Associate a unit with a given index into the top-level
* device directory.
* The device will be probed if it has not already been
* successfully accessed.
*/
for(sdev = sdlist; sdev != nil; sdev = sdev->next){
if(index >= sdev->index && index < sdev->index+sdev->nunit)
return sdgetunit(sdev, index-sdev->index);
}
.
171c
static SDunit*
sdindex2unit(int index)
{
SDev *sdev;
.
153,169c
return unit;
}
.
139,151c
/*
* No need to lock anything here as this is only
* called before the unit is made available in the
* sdunit[] array.
*/
if(unit->dev->ifc->verify(unit) == 0){
qunlock(&sdqlock);
free(unit);
return nil;
}
sdunit[index] = unit;
}
qunlock(&sdqlock);
.
133,137c
snprint(unit->name, NAMELEN, "%s%d", sdev->name, subno);
unit->subno = subno;
unit->dev = sdev;
.
125,131c
if(sdev->enabled == 0 && sdev->ifc->enable)
sdev->ifc->enable(sdev);
sdev->enabled = 1;
.
122,123c
if(sdunitflg[index]){
qunlock(&sdqlock);
return nil;
}
if((unit = malloc(sizeof(SDunit))) == nil){
qunlock(&sdqlock);
return nil;
}
sdunitflg[index] = 1;
.
120c
* Probe the unit only once. This decision
* may be a little severe and reviewed later.
.
111,118c
/*
* Associate a unit with a given device and sub-unit
* number on that device.
* The device will be probed if it has not already been
* successfully accessed.
*/
qlock(&sdqlock);
index = sdev->index+subno;
unit = sdunit[index];
if(unit == nil){
.
107,109c
int index;
SDunit *unit;
.
104,105c
static SDunit*
sdgetunit(SDev* sdev, int subno)
.
95,100c
if(unit->dev->ifc->online)
unit->dev->ifc->online(unit);
if(unit->sectors){
sdaddpart(unit, "data", 0, unit->sectors);
/*
* Use partitions passed from boot program,
* e.g.
* sdC0=dos 63 123123/plan9 123123 456456
*/
for(p = getconf(unit->name); p != nil; p = q){
if(q = strchr(p, '/'))
*q++ = '\0';
nf = getfields(p, f, nelem(f), 1, " \t\r");
if(nf < 3)
continue;
start = strtoul(f[1], 0, 0);
end = strtoul(f[2], 0, 0);
if(!waserror()){
sdaddpart(unit, f[0], start, end);
poperror();
}
}
}
.
91,93d
86,89c
if(unit->inquiry[0] & 0xC0)
return 0;
switch(unit->inquiry[0] & 0x1F){
case 0x00: /* DA */
case 0x04: /* WORM */
case 0x05: /* CD-ROM */
case 0x07: /* MO */
break;
default:
return 0;
.
81,83c
unit->sectors = unit->secsize = 0;
unit->npart = 0;
if(unit->part){
free(unit->part);
unit->part = nil;
.
74,79c
int nf;
ulong start, end;
char *f[4], *p, *q;
.
72c
sdinitpart(SDunit* unit)
.
65,69c
unit->npart--;
if(unit->npart == 0){
free(unit->part);
unit->part = nil;
}
}
.
62,63c
/*
* Look for the partition to delete.
* Can't delete if someone still has it open.
* If it's the last valid partition zap the
* whole table.
*/
pp = unit->part;
for(i = 0; i < SDnpart; i++){
if(strncmp(name, pp->name, NAMELEN) == 0)
break;
pp++;
}
if(i >= SDnpart)
error(Ebadctl);
if(pp->nopen)
error(Einuse);
pp->valid = 0;
.
59,60c
static void
sddelpart(SDunit* unit, char* name)
{
int i;
SDpart *pp;
.
55,57c
/*
* Check there is a free slot and size and extent are valid.
*/
if(partno == -1 || start > end || end > unit->sectors)
error(Eio);
pp = &unit->part[partno];
pp->start = start;
pp->end = end;
strncpy(pp->name, name, NAMELEN);
strncpy(pp->user, eve, NAMELEN);
pp->perm = 0640;
pp->valid = 1;
unit->npart++;
}
.
49,53c
/*
* Check name not already used
* and look for a free slot.
*/
if(unit->part != nil){
partno = -1;
for(i = 0; i < SDnpart; i++){
pp = &unit->part[i];
if(!pp->valid){
if(partno == -1)
partno = i;
break;
}
if(strcmp(name, pp->name) == 0){
if(pp->start == start && pp->end == end)
return;
error(Ebadctl);
}
}
}
else{
if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil)
error(Enomem);
partno = 0;
}
.
43,47c
SDpart *pp;
int i, partno;
.
41c
#define TYPE(q) ((q).path & 0x0F)
#define PART(q) (((q).path>>4) & 0x0F)
#define UNIT(q) (((q).path>>8) & 0xFF)
#define QID(u, p, t) (((u)<<8)|((p)<<4)|(t))
static void
sdaddpart(SDunit* unit, char* name, ulong start, ulong end)
.
34,38c
Qunitdir, /* directory per unit */
Qunitbase,
Qctl = Qunitbase,
Qraw,
Qpart,
.
31,32c
enum {
Qtopdir = 1, /* top level directory */
Qtopbase,
.
28,29d
21,26c
extern Dev sddevtab;
extern SDifc* sdifc[];
static QLock sdqlock;
static SDev* sdlist;
static SDunit** sdunit;
static int* sdunitflg;
static int sdnunit;
enum {
Rawcmd,
Rawdata,
Rawstatus,
.
11,19c
#include "sd.h"
.
4,9c
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
.
2c
* Storage Device.
.
## diffname port/devsd.c 2000/0515
## diff -e /n/emeliedump/2000/0506/sys/src/9/port/devsd.c /n/emeliedump/2000/0515/sys/src/9/port/devsd.c
301a
/*
* BUG: no check is made here or later when a
* unit is attached that the id and name are set.
*/
.
## diffname port/devsd.c 2000/0524
## diff -e /n/emeliedump/2000/0515/sys/src/9/port/devsd.c /n/emeliedump/2000/0524/sys/src/9/port/devsd.c
875c
if(strncmp(up->user, pp->user, NAMELEN) && !iseve())
.
626c
l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
if(l < 0)
.
618c
l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno);
if(l < 0)
.
608c
l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
if(l < 0)
.
406a
if(pp->user[0] == '\0')
strncpy(pp->user, eve, NAMELEN);
.
334a
if(pp->user[0] == '\0')
strncpy(pp->user, eve, NAMELEN);
.
158a
* This happens before /boot sets hostname so the
* partitions will have the null-string for user.
* The gen functions patch it up.
.
112a
if(strncmp(up->user, pp->user, NAMELEN) && !iseve())
error(Eperm);
.
65c
if(strncmp(name, pp->name, NAMELEN) == 0){
.
## diffname port/devsd.c 2000/0526
## diff -e /n/emeliedump/2000/0524/sys/src/9/port/devsd.c /n/emeliedump/2000/0526/sys/src/9/port/devsd.c
846,849c
break;
case Rawstatus:
unit->state = Rawcmd;
free(unit->req);
unit->req = nil;
error(Ebadusefd);
case Rawdata:
.
844d
836d
832,834c
if((req = malloc(sizeof(SDreq))) == nil)
.
824,830c
switch(unit->state){
case Rawcmd:
if(n < 6 || n > sizeof(req->cmd))
.
821a
.
763d
759d
747,752d
531,535c
unlock(&unit->rawinuse);
.
494a
case Qraw:
unit = sdunit[UNIT(c->qid)];
if(!canlock(&unit->rawinuse))
error(Einuse);
unit->state = Rawcmd;
break;
.
331c
devdir(c, q, "raw", 0, eve, CHEXCL|0600, dp);
.
## diffname port/devsd.c 2000/0530
## diff -e /n/emeliedump/2000/0526/sys/src/9/port/devsd.c /n/emeliedump/2000/0530/sys/src/9/port/devsd.c
165c
snprint(buf, sizeof buf, "%spart", unit->name);
for(p = getconf(buf); p != nil; p = q){
.
160c
* sdC0part=dos 63 123123/plan9 123123 456456
.
131c
char *f[4], *p, *q, buf[10];
.
## diffname port/devsd.c 2000/0531
## diff -e /n/emeliedump/2000/0530/sys/src/9/port/devsd.c /n/emeliedump/2000/0531/sys/src/9/port/devsd.c
499a
}
.
498c
if(!canlock(&unit->rawinuse)){
c->flag &= ~COPEN;
.
## diffname port/devsd.c 2000/0607
## diff -e /n/emeliedump/2000/0531/sys/src/9/port/devsd.c /n/emeliedump/2000/0607/sys/src/9/port/devsd.c
725,732c
if(unit->dev->ifc->rctl == nil)
.
723a
/*
* If there's a device specific routine it must
* provide all information pertaining to night geometry
* and the garscadden trains.
*/
if(unit->dev->ifc->rctl)
l += unit->dev->ifc->rctl(unit, p+l, READSTR-l);
.
## diffname port/devsd.c 2000/0617
## diff -e /n/emeliedump/2000/0607/sys/src/9/port/devsd.c /n/emeliedump/2000/0617/sys/src/9/port/devsd.c
880c
if(unit->vers+pp->vers != c->qid.vers)
.
877,878d
798c
if(cb->nf != 4)
.
792c
if(unit->vers != c->qid.vers)
.
731c
if(unit->sectors == 0)
sdinitpart(unit);
if(unit->sectors){
.
591d
577c
pp = &unit->part[PART(c->qid)];
if(unit->vers+pp->vers != c->qid.vers)
.
573c
while(waserror()){
/* notification of media change; go around again */
if(strcmp(up->error, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
sdinitpart(unit);
continue;
}
/* other errors; give up */
.
571a
nchange = 0;
.
563a
int nchange;
.
542,557d
527d
515,516c
c->qid.vers = unit->vers+pp->vers;
.
512,513d
497a
c->qid.vers = unit->vers;
.
495a
case Qctl:
unit = sdunit[UNIT(c->qid)];
c->qid.vers = unit->vers;
break;
.
414c
q = (Qid){QID(UNIT(c->qid), i, Qpart), unit->vers+pp->vers};
.
409c
if(!pp->valid){
.
404c
if(unit->part == nil || i >= SDnpart){
.
396a
.
395c
/*
* Check for media change.
* If one has already been detected, sectors will be zero.
* If there is one waiting to be detected, online will return > 1.
* Online is a bit of a large hammer but does the job.
*/
if(unit->sectors == 0 || (unit->dev->ifc->online && unit->dev->ifc->online(unit) > 1))
.
340c
q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qpart), unit->vers+pp->vers};
.
335,337d
331c
q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qraw), unit->vers};
.
327c
q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qctl), unit->vers};
.
324a
unit = sdunit[UNIT(c->qid)];
.
136,137c
for(i = 0; i < SDnpart; i++){
unit->part[i].valid = 0;
unit->part[i].vers++;
}
.
134d
132a
unit->vers++;
.
129c
int i, nf;
.
118,123c
pp->vers++;
.
115,116d
102,103d
90d
81c
if(partno == -1)
error(Ebadctl);
if(start > end || end > unit->sectors)
.
## diffname port/devsd.c 2000/0706
## diff -e /n/emeliedump/2000/0617/sys/src/9/port/devsd.c /n/emeliedump/2000/0706/sys/src/9/port/devsd.c
880,881c
strncpy(perm->user, d.uid, NAMELEN);
perm->perm = (perm->perm & ~0777) | (d.mode & 0777);
.
878a
if(strncmp(up->user, perm->user, NAMELEN) && !iseve())
error(Eperm);
.
877a
case Qctl:
perm = &unit->ctlperm;
break;
case Qraw:
perm = &unit->rawperm;
break;
case Qpart:
pp = &unit->part[PART(c->qid)];
if(unit->vers+pp->vers != c->qid.vers)
error(Enonexist);
perm = &pp->SDperm;
break;
}
.
873,876c
switch(TYPE(c->qid)){
default:
.
863c
if(c->qid.path & CHDIR)
.
860a
SDperm *perm;
.
394c
if(unit->sectors == 0
|| (unit->dev->ifc->online && unit->dev->ifc->online(unit) > 1))
.
391c
* If there is one waiting to be detected, online
* will return > 1.
.
373c
if(unit->user[0] == '\0')
strncpy(unit->user, eve, NAMELEN);
devdir(c, q, unit->name, 0, unit->user, unit->perm, dp);
.
370,371c
if((unit = sdunit[s]) == nil){
if((unit = sdindex2unit(s)) == nil)
return 0;
}
.
327c
perm = &unit->rawperm;
if(perm->user[0] == '\0'){
strncpy(perm->user, eve, NAMELEN);
perm->perm = CHEXCL|0600;
}
devdir(c, q, "raw", 0, perm->user, perm->perm, dp);
.
323c
perm = &unit->ctlperm;
if(perm->user[0] == '\0'){
strncpy(perm->user, eve, NAMELEN);
perm->perm = 0640;
}
devdir(c, q, "ctl", 0, perm->user, perm->perm, dp);
.
316a
SDperm *perm;
.
213a
strncpy(unit->user, eve, NAMELEN);
unit->perm = 0555;
.
## diffname port/devsd.c 2000/0809
## diff -e /n/emeliedump/2000/0706/sys/src/9/port/devsd.c /n/emeliedump/2000/0809/sys/src/9/port/devsd.c
752c
for(i = 0; i < unit->npart; i++){
.
423c
if(unit->part == nil || i >= unit->npart){
.
128c
for(i = 0; i < unit->npart; i++){
.
110c
if(i >= unit->npart)
.
105c
for(i = 0; i < unit->npart; i++){
.
81,83c
if(partno == -1){
if((pp = malloc(sizeof(SDpart)*(unit->npart+SDnpart))) == nil)
error(Enomem);
memmove(pp, unit->part, sizeof(SDpart)*unit->npart);
free(unit->part);
unit->part = pp;
partno = unit->npart;
unit->npart += SDnpart;
}
/*
* Check size and extent are valid.
*/
if(start > end || end > unit->sectors)
.
79c
* If no free slot found then increase the
* array size (can't get here with unit->part == nil).
.
74a
unit->npart = SDnpart;
.
58c
for(i = 0; i < unit->npart; i++){
.
## diffname port/devsd.c 2000/1129
## diff -e /n/emeliedump/2000/0809/sys/src/9/port/devsd.c /n/emeliedump/2000/1129/sys/src/9/port/devsd.c
880c
qunlock(&unit->raw);
poperror();
return n;
.
878c
n = sdrio(unit->req, a, n);
.
849a
qlock(&unit->raw);
if(waserror()){
qunlock(&unit->raw);
nexterror();
}
.
809a
case Qlog:
error(Ebadctl);
.
789,791c
i = readnum(0, a, n, status, NUMSIZE);
} else
i = 0;
qunlock(&unit->raw);
poperror();
return i;
.
782c
i = sdrio(unit->req, a, n);
.
779a
qlock(&unit->raw);
if(waserror()){
qunlock(&unit->raw);
nexterror();
}
.
743a
case Qlog:
unit = sdunit[UNIT(c->qid)];
return logread(&unit->log, a, 0, n);
.
636a
if(unit->log.opens) {
int i;
uchar lbuf[1+4+8], *p;
ulong x[3];
p = lbuf;
*p++ = write ? 'w' : 'r';
x[0] = off>>32;
x[1] = off;
x[2] = len;
for(i=0; i<3; i++) {
*p++ = x[i]>>24;
*p++ = x[i]>>16;
*p++ = x[i]>>8;
*p++ = x[i];
}
logn(&unit->log, 1, lbuf, 1+4+8);
}
.
570a
case Qlog:
unit = sdunit[UNIT(c->qid)];
logclose(&unit->log);
break;
.
527a
case Qlog:
unit = sdunit[UNIT(c->qid)];
logopen(&unit->log);
break;
.
454a
case Qlog:
.
336a
case Qlog:
q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qlog), unit->vers};
perm = &unit->rawperm;
if(perm->user[0] == '\0'){
strncpy(perm->user, eve, NAMELEN);
perm->perm = 0666;
}
devdir(c, q, "log", 0, perm->user, perm->perm, dp);
return 1;
.
231a
unit->log.logmask = ~0;
unit->log.nlog = 16*1024;
unit->log.minread = 4*1024;
.
36a
Qlog,
.
13c
#include "../port/sd.h"
.
## diffname port/devsd.c 2001/0213
## diff -e /n/emeliedump/2000/1129/sys/src/9/port/devsd.c /n/emeliedump/2001/0213/sys/src/9/port/devsd.c
126,127d
## diffname port/devsd.c 2001/0527
## diff -e /n/emeliedump/2001/0213/sys/src/9/port/devsd.c /n/emeliedump/2001/0527/sys/src/9/port/devsd.c
1004d
994a
return n;
.
989,991c
n = convM2D(dp, n, &d[0], (char*)&d[1]);
if(n == 0)
error(Eshortstat);
kstrdup(&perm->user, d[0].uid);
perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
.
987c
if(strcmp(up->user, perm->user) && !iseve())
.
960c
if(c->qid.type & QTDIR)
.
955c
Dir d[2];
.
952,953c
static int
sdwstat(Chan* c, uchar* dp, int n)
.
943,944c
break;
.
862,865d
812,814c
"part %s %lud %lud\n",
pp->name, pp->start, pp->end);
.
785,787d
658,677d
588,591d
580c
if(c->qid.type & QTDIR)
.
541,544d
525,530d
522c
return devstat(c, db, n, nil, 0, sdgen);
.
520c
sdstat(Chan* c, uchar* db, int n)
.
516c
return devwalk(c, nc, name, nname, nil, 0, sdgen);
.
513,514c
static Walkqid*
sdwalk(Chan* c, Chan* nc, char** name, int nname)
.
508c
mkqid(&c->qid, QID(sdev->index+subno, 0, Qunitdir), 0, QTDIR);
.
490c
mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR);
.
467d
458,460c
mkqid(&q, QID(UNIT(c->qid), i, Qpart), unit->vers+pp->vers, QTFILE);
if(emptystr(pp->user))
kstrdup(&pp->user, eve);
.
422,424c
mkqid(&q, QID(s, 0, Qtopdir), 0, QTDIR);
sprint(up->genbuf, "#%C", sddevtab.dc);
devdir(c, q, up->genbuf, 0, eve, 0555, dp);
.
412,414c
mkqid(&q, QID(s, 0, Qunitdir), 0, QTDIR);
if(emptystr(unit->user))
kstrdup(&unit->user, eve);
.
402,404c
mkqid(&q, QID(s, 0, Qtopdir), 0, QTDIR);
sprint(up->genbuf, "#%C", sddevtab.dc);
devdir(c, q, up->genbuf, 0, eve, 0555, dp);
.
397d
390c
sdgen(Chan* c, char*, Dirtab*, int, int s, Dir* dp)
.
370,372c
mkqid(&q, QID(UNIT(c->qid), PART(c->qid), Qpart), unit->vers+pp->vers, QTFILE);
if(emptystr(pp->user))
kstrdup(&pp->user, eve);
.
361,363c
if(emptystr(perm->user)){
kstrdup(&perm->user, eve);
perm->perm = DMEXCL|0600;
.
359c
mkqid(&q, QID(UNIT(c->qid), PART(c->qid), Qraw), unit->vers, QTFILE);
.
352,353c
if(emptystr(perm->user)){
kstrdup(&perm->user, eve);
.
350c
mkqid(&q, QID(UNIT(c->qid), PART(c->qid), Qctl), unit->vers, QTFILE);
.
340,348d
231,234d
225,226c
snprint(buf, sizeof(buf), "%s%d", sdev->name, subno);
kstrdup(&unit->name, buf);
kstrdup(&unit->user, eve);
.
195a
char buf[32];
.
125a
if(strcmp(up->user, pp->user) && !iseve())
error(Eperm);
.
120c
if(strcmp(name, pp->name) == 0)
.
102,103c
kstrdup(&pp->name, name);
kstrdup(&pp->user, eve);
.
66c
if(strcmp(name, pp->name) == 0){
.
42,44c
#define TYPE(q) (((ulong)(q).path) & 0x0F)
#define PART(q) ((((ulong)(q).path)>>4) & 0x0F)
#define UNIT(q) ((((ulong)(q).path)>>8) & 0xFF)
.
37d
## diffname port/devsd.c 2001/0613
## diff -e /n/emeliedump/2001/0527/sys/src/9/port/devsd.c /n/emeliedump/2001/0613/sys/src/9/port/devsd.c
310a
if(sdnunit > NUnit)
sdnunit = NUnit;
.
83a
if(unit->npart >= NPart)
error(Enomem);
.
41,44c
#define TYPE(q) ((((ulong)(q).path)>>TypeSHIFT) & TypeMASK)
#define PART(q) ((((ulong)(q).path)>>PartSHIFT) & PartMASK)
#define UNIT(q) ((((ulong)(q).path)>>UnitSHIFT) & UnitMASK)
#define QID(u, p, t) (((u)<<UnitSHIFT)|((p)<<PartSHIFT)|((t)<<TypeSHIFT))
.
38a
TypeLOG = 4,
NType = (1<<TypeLOG),
TypeMASK = (NType-1),
TypeSHIFT = 0,
PartLOG = 8,
NPart = (1<<PartLOG),
PartMASK = (NPart-1),
PartSHIFT = TypeLOG,
UnitLOG = 8,
NUnit = (1<<UnitLOG),
UnitMASK = (NUnit-1),
UnitSHIFT = (PartLOG+TypeLOG),
.
## diffname port/devsd.c 2001/0905
## diff -e /n/emeliedump/2001/0613/sys/src/9/port/devsd.c /n/emeliedump/2001/0905/sys/src/9/port/devsd.c
981a
devpower,
sdconfig,
.
963a
static char
getspec(char base)
{
while (1) {
int i;
SDev *sdev;
for (i = 0; i != ndevs; i++)
if ((sdev = devs[i].dt_dev) != nil && (char)sdev->idno == base)
break;
if (i == ndevs)
return base;
base++;
}
return '\0';
}
static int
configure(char *spec, DevConf *cf)
{
ISAConf isa;
dev_t *_devs;
SDev *tail, *sdev, *(*probe)(DevConf *);
char *p, name[32];
int i, added_devs;
if ((p = strchr(cf->type, '/')) != nil)
*p++ = '\0';
for(i = 0; sdifc[i] != nil; i++)
if(!strcmp(sdifc[i]->name, cf->type))
break;
if (sdifc[i] == nil)
error("type not found");
if ((probe = sdifc[i]->probe) == nil)
error("No probe function");
if (p) {
/* Try to find the card on the ISA bus. This code really belongs
in sdata and I'll move it later. Really! */
memset(&isa, 0, sizeof(isa));
isa.port = cf->ports[0].port;
isa.irq = cf->interrupt;
if (pcmspecial(p, &isa) < 0)
error("Cannot find controller");
}
qlock(&devslock);
if (waserror()) {
qunlock(&devslock);
nexterror();
}
for (i = 0; i != ndevs; i++)
if ((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec)
break;
if (i != ndevs)
error(Eexist);
if ((sdev = (*probe)(cf)) == nil)
error("Cannot probe controller");
poperror();
added_devs = 0;
tail = sdev;
while (tail) {
added_devs++;
tail = tail->next;
}
_devs = (dev_t *)malloc((ndevs + added_devs) * sizeof(dev_t));
memmove(_devs, devs, ndevs * sizeof(dev_t));
free(devs);
devs = _devs;
while (sdev) {
/* Assign `spec' to the device */
*spec = getspec(*spec);
snprint(name, sizeof(name), "sd%c", *spec);
kstrdup(&sdev->name, name);
sdev->idno = *spec;
devs[ndevs].dt_dev = sdev;
devs[ndevs].dt_nunits = sdev->nunit;
sdev = sdev->next;
devs[ndevs].dt_dev->next = nil;
ndevs++;
}
qunlock(&devslock);
return 0;
}
static int
unconfigure(char *spec)
{
int i;
SDev *sdev;
qlock(&devslock);
if (waserror()) {
qunlock(&devslock);
nexterror();
}
for (sdev = nil, i = 0; i != ndevs; i++)
if ((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec)
break;
if (i == ndevs)
error(Enonexist);
if (sdev->r.ref)
error(Einuse);
/* make sure no interrupts arrive anymore before removing resources */
if (sdev->enabled && sdev->ifc->disable)
sdev->ifc->disable(sdev);
/* we're alone and the device tab is locked; make the device unavailable */
memmove(&devs[i], &devs[ndevs - 1], sizeof(dev_t));
memset(&devs[ndevs - 1], 0, sizeof(dev_t));
ndevs--;
qunlock(&devslock);
poperror();
for (i = 0; i != sdev->nunit; i++)
if (sdev->unit[i]) {
SDunit *unit = sdev->unit[i];
free(unit->name);
free(unit->user);
free(unit);
}
if (sdev->ifc->clear)
sdev->ifc->clear(sdev);
return 0;
}
static int
sdconfig(int on, char *spec, DevConf *cf)
{
return on? configure(spec, cf): unconfigure(spec);
}
.
959a
decref(&sdev->r);
.
930a
decref(&sdev->r);
.
927c
sdev = sdgetdev(DEV(c->qid));
if (sdev == nil)
error(Enonexist);
unit = sdev->unit[UNIT(c->qid)];
.
925c
error(Eperm);
.
922a
SDev *sdev;
.
906a
decref(&sdev->r);
.
873a
decref(&sdev->r);
.
870c
sdev = sdgetdev(DEV(c->qid));
if (sdev == nil)
error(Enonexist);
unit = sdev->unit[UNIT(c->qid)];
.
864a
decref(&sdev->r);
.
837a
decref(&sdev->r);
.
833c
sdev = sdgetdev(DEV(c->qid));
if (sdev == nil)
error(Enonexist);
unit = sdev->unit[UNIT(c->qid)];
.
830a
case Qtopctl: {
confdata_t cd;
char buf[256], *field[Ncmd];
int nf, i, j;
memset(&cd, 0, sizeof(confdata_t));
if(n > sizeof(buf)-1) n = sizeof(buf)-1;
memmove(buf, a, n);
buf[n] = '\0';
cd.o_on = -1;
cd.o_spec = '\0';
memset(&cd.o_cf, 0, sizeof(DevConf));
nf = getfields(buf, field, Ncmd, 1, " \t\n");
for (i = 0; i < nf; i++) {
char *opt = field[i++];
if (i >= nf)
error(Ebadarg);
for (j = 0; j != nelem(options); j++)
if (!strcmp(opt, options[j].option))
break;
if (j == nelem(options))
error(Ebadarg);
options[j].parse(&cd, field[i]);
}
if (cd.o_on < 0)
error(Ebadarg);
if (cd.o_on) {
if (cd.o_spec == '\0' || cd.o_cf.nports == 0 ||
cd.o_cf.interrupt == 0 || cd.o_cf.type == nil)
error(Ebadarg);
}
else {
if (cd.o_spec == '\0')
error(Ebadarg);
}
if (sddevtab.config == nil)
error("No configuration function");
sddevtab.config(cd.o_on, cd.o_spec, &cd.o_cf);
break;
}
.
825a
SDev *sdev;
.
819a
typedef struct {
int o_on;
char *o_spec;
DevConf o_cf;
} confdata_t;
static void
parse_switch(confdata_t *cd, char *option)
{
if (!strcmp("on", option))
cd->o_on = 1;
else if (!strcmp("off", option))
cd->o_on = 0;
else
error(Ebadarg);
}
static void
parse_spec(confdata_t *cd, char *option)
{
if (strlen(option) > 1)
error(Ebadarg);
cd->o_spec = option;
}
static port_t *
getnewport(DevConf *dc)
{
port_t *p;
p = (port_t *)malloc((dc->nports + 1) * sizeof(port_t));
if (dc->nports > 0) {
memmove(p, dc->ports, dc->nports * sizeof(port_t));
free(dc->ports);
}
dc->ports = p;
p = &dc->ports[dc->nports++];
p->size = -1;
p->port = (ulong)-1;
return p;
}
static void
parse_port(confdata_t *cd, char *option)
{
char *e;
port_t *p;
p = (cd->o_cf.nports == 0 ||
cd->o_cf.ports[cd->o_cf.nports -1].port != (ulong)-1)?
getnewport(&cd->o_cf): &cd->o_cf.ports[cd->o_cf.nports - 1];
p->port = strtol(option, &e, 0);
if (e == nil || *e != '\0')
error(Ebadarg);
}
static void
parse_size(confdata_t *cd, char *option)
{
char *e;
port_t *p;
p = (cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports -1].size != -1)?
getnewport(&cd->o_cf): &cd->o_cf.ports[cd->o_cf.nports - 1];
p->size = (int)strtol(option, &e, 0);
if (e == nil || *e != '\0')
error(Ebadarg);
}
static void
parse_irq(confdata_t *cd, char *option)
{
char *e;
cd->o_cf.interrupt = strtoul(option, &e, 0);
if (e == nil || *e != '\0')
error(Ebadarg);
}
static void
parse_type(confdata_t *cd, char *option)
{
cd->o_cf.type = option;
}
static struct {
char *option;
void (*parse)(confdata_t *, char *);
} options[] = {
{ "switch", parse_switch, },
{ "spec", parse_spec, },
{ "port", parse_port, },
{ "size", parse_size, },
{ "irq", parse_irq, },
{ "type", parse_type, },
};
.
812a
.
810a
decref(&sdev->r);
.
795a
decref(&sdev->r);
.
792c
sdev = sdgetdev(DEV(c->qid));
if (sdev == nil)
error(Enonexist);
unit = sdev->unit[UNIT(c->qid)];
.
790a
.
787a
decref(&sdev->r);
.
759c
sdev = sdgetdev(DEV(c->qid));
if (sdev == nil)
error(Enonexist);
unit = sdev->unit[UNIT(c->qid)];
.
757a
.
754a
case Qtopstat:
p = buf = malloc(READSTR);
assert(p);
e = p + READSTR;
qlock(&devslock);
for (i = 0; i != ndevs; i++) {
SDev *sdev = devs[i].dt_dev;
if (sdev->ifc->stat)
p = sdev->ifc->stat(sdev, p, e);
else
p = seprint(e, "%s; no statistics available\n", sdev->name);
}
qunlock(&devslock);
n = readstr(off, a, n, buf);
free(buf);
return n;
.
747a
SDev *sdev;
.
745c
char *p, *e, *buf;
.
698a
decref(&sdev->r);
.
655a
if(!(unit->inquiry[1] & 0x80))
decref(&sdev->r); /* gadverdamme! */
.
642a
decref(&sdev->r);
.
614a
decref(&sdev->r);
.
602c
sdev = sdgetdev(DEV(c->qid));
if (sdev == nil)
error(Enonexist);
unit = sdev->unit[UNIT(c->qid)];
if (unit == nil)
error(Enonexist);
.
599a
SDev *sdev;
.
586,587c
sdev = sdgetdev(DEV(c->qid));
if (sdev) {
unit = sdev->unit[UNIT(c->qid)];
unlock(&unit->rawinuse);
decref(&sdev->r);
}
.
575a
SDev *sdev;
.
568a
decref(&sdev->r);
.
556d
547d
543d
540,541d
538a
if ((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart)
return c;
sdev = sdgetdev(DEV(c->qid));
if (sdev == nil)
error(Enonexist);
unit = sdev->unit[UNIT(c->qid)];
.
536a
SDev *sdev;
uchar tp;
.
515,516c
mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR);
c->dev = (sdev->idno << UnitLOG) + subno;
decref(&sdev->r);
.
512a
}
incref(&sdev->r);
qunlock(&devslock);
.
510,511c
if (i == ndevs || subno >= sdev->nunit || sdgetunit(sdev, subno) == nil) {
qunlock(&devslock);
.
507,508c
qlock(&devslock);
for (sdev = nil, i = 0; i != ndevs; i++)
if ((sdev = devs[i].dt_dev) != nil && sdev->idno == idno)
.
497c
mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR);
.
495c
if(ndevs == 0 || *spec == '\0'){
.
493c
int idno, subno, i;
.
478a
decref(&sdev->r);
.
475c
if ((sdev = sdgetdev(DEV(c->qid))) == nil) {
devdir(c, q, "unavailable", 0, eve, 0, dp);
return 1;
}
unit = sdev->unit[UNIT(c->qid)];
.
470a
decref(&sdev->r);
.
466c
mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),
unit->vers+pp->vers, QTFILE);
.
462a
decref(&sdev->r);
.
457a
decref(&sdev->r);
.
452a
decref(&sdev->r);
.
435c
if ((sdev = sdgetdev(DEV(c->qid))) == nil) {
devdir(c, q, "unavailable", 0, eve, 0, dp);
return 1;
}
unit = sdev->unit[UNIT(c->qid)];
.
430c
mkqid(&q, QID(0, s, 0, Qtopdir), 0, QTDIR);
.
426,427c
if (i == ndevs) {
/* Run of the end of the list */
qunlock(&devslock);
return -1;
}
if ((sdev = devs[i].dt_dev) == nil) {
qunlock(&devslock);
return 0;
}
incref(&sdev->r);
qunlock(&devslock);
if((unit = sdev->unit[s]) == nil)
if((unit = sdgetunit(sdev, s)) == nil) {
decref(&sdev->r);
return 0;
}
mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR);
if(emptystr(unit->user))
kstrdup(&unit->user, eve);
devdir(c, q, unit->name, 0, unit->user, unit->perm, dp);
decref(&sdev->r);
return 1;
}
.
415,424c
if (s == 0 || s == 1)
return sd1gen(c, s + Qtopbase, dp);
s -= 2;
qlock(&devslock);
for (i = 0; i != ndevs; i++) {
if (s < devs[i].dt_nunits)
break;
s -= devs[i].dt_nunits;
.
410c
mkqid(&q, QID(0, s, 0, Qtopdir), 0, QTDIR);
.
408c
case Qtopdir: {
.
405a
SDev *sdev;
.
392,393c
case Qtopctl:
mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE);
devdir(c, q, "sdctl", 0, eve, 0640, dp);
return 1;
case Qtopstat:
mkqid(&q, QID(0, 0, 0, Qtopstat), 0, QTFILE);
devdir(c, q, "sdstat", 0, eve, 0640, dp);
return 1;
.
390a
Qid q;
.
389c
sd1gen(Chan* c, int i, Dir* dp)
.
383,385c
rv = 1;
break;
}
decref(&sdev->r);
return rv;
.
379c
mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart),
unit->vers+pp->vers, QTFILE);
.
375c
rv = 1;
break;
.
368c
mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),
unit->vers, QTFILE);
.
366c
rv = 1;
break;
.
359c
mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),
unit->vers, QTFILE);
.
356c
sdev = sdgetdev(DEV(c->qid));
assert(sdev);
unit = sdev->unit[UNIT(c->qid)];
rv = -1;
.
354a
SDev *sdev;
int rv;
.
344a
/*
* The IDs have been set, unlink the sdlist and copy the spec to
* the devtab.
*/
devs = (dev_t *)malloc(ndevs * sizeof(dev_t));
memset(devs, 0, ndevs * sizeof(dev_t));
i = 0;
while (sdlist != nil) {
devs[i].dt_dev = sdlist;
devs[i].dt_nunits = sdlist->nunit;
sdlist = sdlist->next;
devs[i].dt_dev->next = nil;
i++;
}
.
328,336d
326c
if(ndevs == 0)
.
315c
.
308,313c
for(tail = sdev; tail->next != nil; tail = tail->next)
ndevs++;
ndevs++;
.
300c
tail = sdlist = nil;
.
292c
SDev *sdev, *tail, *sdlist;
.
268,287d
263,264c
qunlock(&sdev->unitlock);
.
261c
sdev->unit[subno] = unit;
.
257c
qunlock(&sdev->unitlock);
.
238c
sdev->unitflg[subno] = 1;
.
235c
qunlock(&sdev->unitlock);
.
230,231c
if(sdev->unitflg[subno]){
qunlock(&sdev->unitlock);
.
222,224c
qlock(&sdev->unitlock);
if (subno > sdev->nunit) {
qunlock(&sdev->unitlock);
return nil;
}
unit = sdev->unit[subno];
.
212d
208a
static SDev *
sdgetdev(int idno)
{
SDev *sdev;
int i;
qlock(&devslock);
for (i = 0; i != ndevs; i++)
if (devs[i].dt_dev->idno == idno)
break;
if (i == ndevs)
sdev = nil;
else {
sdev = devs[i].dt_dev;
incref(&sdev->r);
}
qunlock(&devslock);
return sdev;
}
.
60a
.
59c
#define DEV(q) ((((ulong)(q).path)>>DevSHIFT) & DevMASK)
#define QID(d,u, p, t) (((d)<<DevSHIFT)|((u)<<UnitSHIFT)|\
((p)<<PartSHIFT)|((t)<<TypeSHIFT))
.
53a
DevLOG = 8,
NDev = (1 << DevLOG),
DevMASK = (NDev-1),
DevSHIFT = (UnitLOG+PartLOG+TypeLOG),
Ncmd = 20,
.
32a
Qtopctl = Qtopbase,
Qtopstat,
.
23a
static dev_t *devs; /* all devices */
static QLock devslock; /* insertion and removal of devices */
static int ndevs; /* total number of devices in the system */
.
18,22c
typedef struct {
SDev *dt_dev;
int dt_nunits; /* num units in dev */
} dev_t;
.
## diffname port/devsd.c 2001/0907
## diff -e /n/emeliedump/2001/0905/sys/src/9/port/devsd.c /n/emeliedump/2001/0907/sys/src/9/port/devsd.c
568a
case Qtopctl:
case Qtopstat:
return sd1gen(c, TYPE(c->qid), dp);
.
327a
}
tail->unit = (SDunit **)malloc(tail->nunit * sizeof(SDunit *));
tail->unitflg = (int *)malloc(tail->nunit * sizeof(int));
.
326c
for(tail = sdev; tail->next != nil; tail = tail->next) {
tail->unit = (SDunit **)malloc(tail->nunit * sizeof(SDunit *));
tail->unitflg = (int *)malloc(tail->nunit * sizeof(int));
assert(tail->unit && tail->unitflg);
.
## diffname port/devsd.c 2001/0911
## diff -e /n/emeliedump/2001/0907/sys/src/9/port/devsd.c /n/emeliedump/2001/0911/sys/src/9/port/devsd.c
1368a
sdev->unit = (SDunit **)malloc(sdev->nunit * sizeof(SDunit *));
sdev->unitflg = (int *)malloc(sdev->nunit * sizeof(int));
assert(sdev->unit && sdev->unitflg);
.
## diffname port/devsd.c 2001/0924
## diff -e /n/emeliedump/2001/0911/sys/src/9/port/devsd.c /n/emeliedump/2001/0924/sys/src/9/port/devsd.c
730c
if(strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
.
## diffname port/devsd.c 2001/1106
## diff -e /n/emeliedump/2001/0924/sys/src/9/port/devsd.c /n/emeliedump/2001/1106/sys/src/9/port/devsd.c
1277a
free(d);
.
1275,1276c
if(!emptystr(d[0].uid))
kstrdup(&perm->user, d[0].uid);
if(d[0].mode != ~0UL)
perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
.
1271a
d = smalloc(sizeof(Dir)+n);
.
1247a
free(d);
.
1246a
d = nil;
.
1233c
Dir *d;
.
## diffname port/devsd.c 2001/1117
## diff -e /n/emeliedump/2001/1106/sys/src/9/port/devsd.c /n/emeliedump/2001/1117/sys/src/9/port/devsd.c
1103c
nf = tokenize(buf, field, Ncmd);
.
208c
nf = tokenize(p, f, nelem(f));
.
## diffname port/devsd.c 2002/0109
## diff -e /n/emeliedump/2001/1117/sys/src/9/port/devsd.c /n/emeliedump/2002/0109/sys/src/9/port/devsd.c
1450a
devshutdown,
.
## diffname port/devsd.c 2002/0316
## diff -e /n/emeliedump/2002/0109/sys/src/9/port/devsd.c /n/emeliedump/2002/0316/sys/src/9/port/devsd.c
1442c
if(on)
return configure(spec, cf);
return unconfigure(spec);
.
1440c
sdconfig(int on, char* spec, DevConf* cf)
.
1434c
if(sdev->ifc->clear)
.
1425,1426c
for(i = 0; i != sdev->nunit; i++)
if(sdev->unit[i]){
.
1414c
if(sdev->enabled && sdev->ifc->disable)
.
1410c
if(sdev->r.ref)
.
1407c
if(i == ndevs)
.
1403,1404c
sdev = nil;
for(i = 0; i != ndevs; i++)
if((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec)
.
1398c
if(waserror()){
.
1392c
unconfigure(char* spec)
.
1376c
sdev->unit = (SDunit **)malloc(sdev->nunit * sizeof(SDunit*));
.
1370c
while(sdev){
.
1365c
_devs = (dev_t*)malloc((ndevs + added_devs) * sizeof(dev_t));
.
1360c
while(tail){
.
1354c
if((sdev = (*probe)(cf)) == nil)
.
1351c
if(i != ndevs)
.
1348,1349c
for(i = 0; i != ndevs; i++)
if((sdev = devs[i].dt_dev) != nil && sdev->idno == *spec)
.
1343c
if(waserror()){
.
1338c
if(pcmspecial(p, &isa) < 0)
.
1331c
if(p){
.
1328c
if((probe = sdifc[i]->probe) == nil)
.
1325c
if(sdifc[i] == nil)
.
1318c
if((p = strchr(cf->type, '/')) != nil)
.
1314c
SDev *tail, *sdev, *(*probe)(DevConf*);
.
1310c
configure(char* spec, DevConf* cf)
.
1302c
if(i == ndevs)
.
1298,1299c
for(i = 0; i != ndevs; i++)
if((sdev = devs[i].dt_dev) != nil && (char)sdev->idno == base)
.
1294c
while(1){
.
1180c
if(sdev == nil)
.
1130c
if(sddevtab.config == nil)
.
1125,1126c
else{
if(cd.o_spec == '\0')
.
1120,1121c
if(cd.o_on){
if(cd.o_spec == '\0' || cd.o_cf.nports == 0 ||
.
1117c
if(cd.o_on < 0)
.
1112c
if(j == nelem(options))
.
1108,1109c
for(j = 0; j != nelem(options); j++)
if(!strcmp(opt, options[j].option))
.
1106c
if(i >= nf)
.
1104c
for(i = 0; i < nf; i++){
.
1078c
sdwrite(Chan* c, void* a, long n, vlong off)
.
1073c
{ "irq", parse_irq, },
.
1069c
{ "switch", parse_switch, },
.
1066,1067c
char *option;
void (*parse)(confdata_t*, char*);
.
1060c
parse_type(confdata_t* cd, char* option)
.
1055c
if(e == nil || *e != '\0')
.
1050c
parse_irq(confdata_t* cd, char* option)
.
1042,1045c
if(cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports-1].size != -1)
p = getnewport(&cd->o_cf);
else
p = &cd->o_cf.ports[cd->o_cf.nports-1];
p->size = (int)strtol(option, &e, 0);
if(e == nil || *e != '\0')
.
1037c
parse_size(confdata_t* cd, char* option)
.
1032c
if(e == nil || *e != '\0')
.
1027,1030c
if(cd->o_cf.nports == 0 || cd->o_cf.ports[cd->o_cf.nports-1].port != (ulong)-1)
p = getnewport(&cd->o_cf);
else
p = &cd->o_cf.ports[cd->o_cf.nports-1];
.
1023c
parse_port(confdata_t* cd, char* option)
.
1011c
if(dc->nports > 0){
.
1005,1006c
static port_t*
getnewport(DevConf* dc)
.
1000c
if(strlen(option) > 1)
.
998c
parse_spec(confdata_t* cd, char* option)
.
991c
else if(!strcmp("off", option))
.
989c
if(!strcmp("on", option))
.
987c
parse_switch(confdata_t* cd, char* option)
.
981,982c
int o_on;
char* o_spec;
.
891c
if(sdev->ifc->stat)
.
888c
for(i = 0; i != ndevs; i++){
.
807c
else{
.
723c
if(unit == nil)
.
720c
if(sdev == nil)
.
650c
if(sdev == nil)
.
646c
if((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart)
.
611c
if(i == ndevs || subno >= sdev->nunit || sdgetunit(sdev, subno) == nil){
.
565c
if((sdev = sdgetdev(DEV(c->qid))) == nil){
.
515c
if((sdev = sdgetdev(DEV(c->qid))) == nil){
.
505d
494c
if((unit = sdgetunit(sdev, s)) == nil){
.
485c
if ((sdev = devs[i].dt_dev) == nil){
.
479c
if(i == ndevs){
.
473c
for(i = 0; i != ndevs; i++){
.
468c
if(s == 0 || s == 1)
.
460c
case Qtopdir:
.
365c
while(sdlist != nil){
.
362c
devs = (dev_t*)malloc(ndevs * sizeof(dev_t));
.
332,333c
tail->unit = (SDunit**)malloc(tail->nunit * sizeof(SDunit*));
tail->unitflg = (int*)malloc(tail->nunit * sizeof(int));
.
326,328c
for(tail = sdev; tail->next != nil; tail = tail->next){
tail->unit = (SDunit**)malloc(tail->nunit * sizeof(SDunit*));
tail->unitflg = (int*)malloc(tail->nunit * sizeof(int));
.
258c
if(subno > sdev->nunit){
.
237c
else{
.
235c
if(i == ndevs)
.
231c
for(i = 0; i != ndevs; i++)
.
224c
static SDev*
.
71c
#define DEV(q) ((((ulong)(q).path)>>DevSHIFT) & DevMASK)
.
23,25c
static dev_t* devs; /* all devices */
static QLock devslock; /* insertion and removal of devices */
static int ndevs; /* total number of devices in the system */
.
19,20c
SDev* dt_dev;
int dt_nunits; /* num units in dev */
.
## diffname port/devsd.c 2002/0330
## diff -e /n/emeliedump/2002/0316/sys/src/9/port/devsd.c /n/emeliedump/2002/0330/sys/src/9/port/devsd.c
784a
if(offset+len > nb*unit->secsize)
len = nb*unit->secsize - offset;
.
## diffname port/devsd.c 2002/0402
## diff -e /n/emeliedump/2002/0330/sys/src/9/port/devsd.c /n/emeliedump/2002/0402/sys/src/9/port/devsd.c
700c
unit->rawinuse = 0;
.
659c
if(tas(&unit->rawinuse) != 0){
.
## diffname port/devsd.c 2002/0703
## diff -e /n/emeliedump/2002/0402/sys/src/9/port/devsd.c /n/emeliedump/2002/0703/sys/src/9/port/devsd.c
1340c
isa.irq = cf->intnum;
.
1126c
cd.o_cf.intnum == 0 || cd.o_cf.type == nil)
.
1058c
cd->o_cf.intnum = strtoul(option, &e, 0);
.
## diffname port/devsd.c 2003/0406
## diff -e /n/emeliedump/2002/0703/sys/src/9/port/devsd.c /n/emeliedump/2003/0406/sys/src/9/port/devsd.c
1247c
if(sdev == nil)
.
1142c
if(sdev == nil)
.
947c
if(sdev == nil)
.
908c
if(sdev == nil)
.
698c
if(sdev) {
.
607c
if((sdev = devs[i].dt_dev) != nil && sdev->idno == idno)
.
485c
if((sdev = devs[i].dt_dev) == nil){
.
474c
if(s < devs[i].dt_nunits)
.
232c
if(devs[i].dt_dev->idno == idno)
.
## diffname port/devsd.c 2003/0507
## diff -e /n/emeliedump/2003/0406/sys/src/9/port/devsd.c /n/emeliedump/2003/0507/sys/src/9/port/devsd.c
288a
if(sdev->enabled == 0 && sdev->ifc->enable)
sdev->ifc->enable(sdev);
sdev->enabled = 1;
.
279,282d
|