## diffname pc/devhard.c 1991/0802
## diff -e /dev/null /n/bootesdump/1991/0802/sys/src/9/safari/devhard.c
0a
#include "u.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "errno.h"
typedef struct Drive Drive;
typedef struct Ident Ident;
typedef struct Controller Controller;
enum
{
/* ports */
Pbase= 0x10,
Pdata= Pbase+0, /* data port (16 bits) */
Perror= Pbase+1, /* error port */
Pcount= Pbase+2, /* sector count port */
Psector= Pbase+3, /* sector number port */
Pcyllsb= Pbase+4, /* least significant byte cylinder # */
Pcylmsb= Pbase+5, /* most significant byte cylinder # */
Pdh= Pbase+6, /* drive/head port */
Pstatus= Pbase+7, /* status port */
Pcmd= Pbase+7, /* cmd port */
/* commands */
Crecal= 0x10,
Cread= 0x20,
Cwrite= 0x30,
Cident= 0xEC,
/* file types */
Qdir= 0,
Qdata= (1<<1),
Qstruct= (2<<1),
Qmask= (3<<1),
};
/*
* ident sector from drive
*/
struct Ident
{
ushort magic; /* must be 0x0A5A */
ushort lcyls; /* logical number of cylinders */
ushort rcyl; /* number of removable cylinders */
ushort lheads; /* logical number of heads */
ushort b2t; /* unformatted bytes/track */
ushort b2s; /* unformated bytes/sector */
ushort ls2t; /* logical sectors/track */
ushort gap; /* bytes in inter-sector gaps */
ushort sync; /* bytes in sync fields */
ushort magic2; /* must be 0x0000 */
ushort serial[10]; /* serial number */
ushort type; /* controller type (0x0003) */
ushort bsize; /* buffer size/512 */
ushort ecc; /* ecc bytes returned by read long */
ushort firm[4]; /* firmware revision */
ushort model[20]; /* model number */
ushort s2i; /* number of sectors/interrupt */
ushort dwtf; /* double word transfer flag */
ushort alernate;
ushort piomode;
ushort dmamode;
ushort reserved[76];
ushort ncyls; /* native number of cylinders */
ushort nheads; /* native number of heads, sectors */
ushort dlcyls; /* default logical number of cyinders */
ushort dlheads; /* default logical number of heads, sectors */
ushort interface;
ushort power; /* 0xFFFF if power commands supported */
ushort flags;
ushort ageprog; /* MSB = age, LSB = program */
ushort reserved2[120];
};
/*
* a hard drive
*/
struct Drive
{
int dev;
ulong cap; /* drive capacity */
int bytes; /* bytes/sector */
int cyl; /* current cylinder */
int confused; /* needs to be recalibrated (or worse) */
int tcyl; /* target cylinder */
int thead; /* target head */
int tsec; /* target sector */
long len; /* size of xfer */
Ident id;
};
/*
* a controller for 2 drives
*/
struct Controller
{
QLock; /* exclusive access to the drive */
int intr; /* true if interrupt occured */
Rendez r; /* wait here for command termination */
int confused; /* needs to be recalibrated (or worse) */
Drive d[2];
};
Controller hard;
Dirtab harddir[]={
"hddata", {Qdata}, 0, 0600,
"hdstruct", {Qstruct}, 8, 0600,
};
#define NHDIR (sizeof(harddir)/sizeof(Dirtab))
void
hardreset(void)
{
hard.d[0].dev = 0;
hard.d[1].dev = 1;
setvec(Hardvec, hardintr);
}
void
hardinit(void)
{
}
Chan*
hardattach(char *spec)
{
return devattach('f', spec);
}
Chan*
hardclone(Chan *c, Chan *nc)
{
return devclone(c, nc);
}
int
hardwalk(Chan *c, char *name)
{
return devwalk(c, name, harddir, NHDIR, devgen);
}
void
hardstat(Chan *c, char *dp)
{
devstat(c, dp, harddir, NHDIR, devgen);
}
Chan*
hardopen(Chan *c, int omode)
{
return devopen(c, omode, harddir, NHDIR, devgen);
}
void
hardcreate(Chan *c, char *name, int omode, ulong perm)
{
error(Eperm);
}
void
hardclose(Chan *c)
{
}
void
hardremove(Chan *c)
{
error(Eperm);
}
void
hardwstat(Chan *c, char *dp)
{
error(Eperm);
}
static void
ul2user(uchar *a, ulong x)
{
a[0] = x >> 24;
a[1] = x >> 16;
a[2] = x >> 8;
a[3] = x;
}
long
hardread(Chan *c, void *a, long n)
{
Drive *dp;
long rv, i;
uchar *aa = a;
if(c->qid.path == CHDIR)
return devdirread(c, a, n, harddir, NHDIR, devgen);
rv = 0;
dp = &hard.d[c->qid.path & ~Qmask];
switch ((int)(c->qid.path & Qmask)) {
case Qdata:
for(rv = 0; rv < n; rv += i){
i = hardxfer(dp, Fread, aa+rv, c->offset+rv, n-rv);
if(i <= 0)
break;
}
break;
case Qstruct:
hardident(dp);
if (n < 2*sizeof(ulong))
error(Ebadarg);
if (c->offset >= 2*sizeof(ulong))
return 0;
rv = 2*sizeof(ulong);
ul2user((uchar*)a, dp->cap);
ul2user((uchar*)a+sizeof(ulong), dp->bytes);
break;
default:
panic("hardread: bad qid");
}
return rv;
}
long
hardwrite(Chan *c, void *a, long n)
{
Drive *dp;
long rv, i;
uchar *aa = a;
rv = 0;
dp = &hard.d[c->qid.path & ~Qmask];
switch ((int)(c->qid.path & Qmask)) {
case Qdata:
for(rv = 0; rv < n; rv += i){
i = hardxfer(dp, Fwrite, aa+rv, c->offset+rv, n-rv);
if(i <= 0)
break;
}
break;
case Qstruct:
error(Eperm);
break;
default:
panic("hardwrite: bad qid");
}
return rv;
}
/*
* did an interrupt happen?
*/
static int
interrupted(Drive *dp)
{
return hard.intr;
}
/*
* get parameters from the drive
*/
hardident(Drive *dp)
{
hard.intr = 0;
outb(Pdh, dp->dev<<4);
outb(Pcmd, Cident);
}
long
hardxfer(Drive *dp, int cmd, void *va, long off, long len)
{
errors("not implemented");
}
.
## diffname pc/devhard.c 1991/0803
## diff -e /n/bootesdump/1991/0802/sys/src/9/safari/devhard.c /n/bootesdump/1991/0803/sys/src/9/safari/devhard.c
278a
}
/*
* take/clear a disk interrupt
*/
static void
hardintr(Ureg *ur)
{
hard.status = inb(Pstatus);
hard.intr = 1;
print("hardintr\n");
wakeup(&hard.r);
.
275c
static long
.
272a
sleep(&hard.r, interrupted, 0);
insw(Pdata, &hard.id, 512);
qunlock(&hard);
.
269a
qlock(&hard);
.
267a
static long
.
260c
interrupted(void *a)
.
215a
dp->cap = 512 * dp->id->lcyls * dp->id->lheads *dp->id->ls2t;
dp->bytes = 512;
.
118a
static void hardintr(Ureg*);
static long hardxfer(Drive*, int, void*, long, long);
static long hardident(Drive*);
.
## diffname pc/devhard.c 1991/0809
## diff -e /n/bootesdump/1991/0803/sys/src/9/safari/devhard.c /n/bootesdump/1991/0809/sys/src/9/safari/devhard.c
301a
}
/*
* calculate physical address of a logical byte offset into the disk
*
* truncate dp->len if it crosses a cylinder boundary
*/
static void
hardpos(Drive *dp, long off)
{
int lsec;
int end;
int cyl;
lsec = off/dp->bytes;
dp->tcyl = lsec/(dp->sectors*dp->heads);
dp->tsec = (lsec % dp->sectors) + 1;
dp->thead = (lsec/dp->sectors) % dp->heads;
/*
* can't read across cylinder boundaries.
* if so, decrement the bytes to be read.
*/
lsec = (off+dp->len)/dp->bytes;
cyl = lsec/(dp->sectors*dp->heads);
if(cyl != dp->tcyl){
dp->len -= (lsec % dp->sectors)*dp->bytes;
dp->len -= ((lsec/dp->sectors) % dp->heads)*dp->bytes*dp->sectors;
}
.
300c
print("hardintr\n");
.
298a
if(hard.status & Sbusy)
panic("disk busy");
.
289c
int secs;
int i;
uchar *aa = va;
if(off % dp->bytes)
errors("bad offset");
if(len % dp->bytes)
errors("bad length");
if(waserror()){
qunlock(&hard);
nexterror();
}
qlock(&hard);
dp->len = len;
hardpos(dp, off);
secs = dp->len/dp->bytes;
outb(Pcount, secs);
outb(Psector, dp->tsec);
outb(Pdh, (1<<5) | (dp->dev<<4) | dp->thead);
outb(Pcyllsb, dp->tcyl);
outb(Pcylmsb, dp->tcyl>>8);
outb(Pcmd, cmd);
if(cmd == Cwrite)
outss(Pdata, aa, dp->bytes/2);
for(i = 0; i < secs; i++){
hard.intr = 0;
sleep(&hard.r, interrupted, 0);
if(hard.status & Serr)
errors("disk error");
if(cmd == Cread){
if((hard.status & Sdrq) == 0)
panic("disk read");
inss(Pdata, aa + i*dp->bytes, dp->bytes/2);
} else {
if((hard.status & Sdrq) == 0){
if(i+1 != secs)
panic("disk write");
} else
outss(Pdata, aa + (i+1)*dp->bytes, dp->bytes/2);
}
}
qunlock(&hard);
.
282,283c
print("getting hard drive ident\n");
inss(Pdata, &hard.id, 512/2);
print(" magic %lux lcyls %d rcyl %d lheads %d b2t %d b2s %d ls2t %d\n",
hard.id.magic, hard.id.lcyls, hard.id.rcyl, hard.id.lheads,
hard.id.b2t, hard.id.b2s, hard.id.ls2t);
.
280a
print("waiting for hard drive interupt\n");
.
277c
print("identify hard drive\n");
.
248c
i = hardxfer(dp, Cwrite, aa+rv, c->offset+rv, n-rv);
.
219,221d
213c
i = hardxfer(dp, Cread, aa+rv, c->offset+rv, n-rv);
.
138a
Drive *dp;
qlock(&hard);
for(dp = hard.d; dp < &hard.d[conf.nhard]; dp++){
if(!waserror()){
hardident(dp);
dp->cyl = hard.id.lcyls;
dp->heads = hard.id.lheads;
dp->sectors = hard.id.ls2t;
dp->bytes = 512;
dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
dp->online = 1;
}
}
.
133a
qunlock(&hard);
.
126,127c
Drive *dp;
hard.d = ialloc(conf.nhard * sizeof(Drive), 0);
for(dp = hard.d; dp < &hard.d[conf.nhard]; dp++){
dp->dev = dp - hard.d;
dp->online = 0;
}
.
121a
static void hardpos(Drive*, long);
.
108c
Drive *d;
Ident id;
.
104a
int status; /* status of last interupt */
.
93,94d
86,87c
int sectors; /* sectors/track */
int heads; /* heads/cyl */
long cyl; /* cylinders/drive */
.
83a
int confused; /* needs to be recalibrated (or worse) */
int online;
.
24a
Sbusy= (1<<7),
Sready= (1<<6),
Sdrq= (1<<5),
Serr= (1<<0),
.
## diffname pc/devhard.c 1991/0810
## diff -e /n/bootesdump/1991/0809/sys/src/9/safari/devhard.c /n/bootesdump/1991/0810/sys/src/9/safari/devhard.c
377d
312,314d
310d
308d
304d
169c
qunlock(&hard);
return devattach('h', spec);
.
166a
poperror();
.
16c
Pbase= 0x1F0,
.
## diffname pc/devhard.c 1991/0811
## diff -e /n/bootesdump/1991/0810/sys/src/9/safari/devhard.c /n/bootesdump/1991/0811/sys/src/9/safari/devhard.c
404d
402a
wakeup(&cp->r);
.
397,401c
cp = &hardc[0];
cp->status = inb(cp->pbase+Pstatus);
switch(cp->cmd){
case Cwrite:
if(cp->status & Serr){
cp->cmd = 0;
cp->error = inb(cp->pbase+Perror);
wakeup(&cp->r);
return;
}
cp->sofar++;
if(cp->sofar != cp->secs){
while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
;
outss(cp->pbase+Pdata, &cp->buf[cp->sofar*cp->dp->bytes],
cp->dp->bytes/2);
} else{
cp->cmd = 0;
wakeup(&cp->r);
}
break;
case Cread:
case Cident:
if(cp->status & Serr){
cp->cmd = 0;
cp->error = inb(cp->pbase+Perror);
wakeup(&cp->r);
return;
}
while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
;
inss(cp->pbase+Pdata, &cp->buf[cp->sofar*cp->dp->bytes],
cp->dp->bytes/2);
cp->sofar++;
if(cp->sofar == cp->secs){
cp->cmd = 0;
wakeup(&cp->r);
}
break;
default:
print("wierd disk interrupt\n");
break;
.
394,395c
* BUG!! if there is ever more than one controller, we need a way to
* distinguish which interrupted
.
392a
cp->len = 512;
cp->secs = 1;
cp->sofar = 0;
cp->cmd = Cident;
outb(cp->pbase+Pdh, (1<<5) | dp->drive<<4);
outb(cp->pbase+Pcmd, Cident);
sleep(&cp->r, cmddone, cp);
if(cp->status & Serr){
print("bad disk magic\n");
errors("disk I/O error");
}
memmove(&dp->id, cp->buf, cp->len);
if(dp->id.magic != 0xA5A){
print("bad disk magic\n");
errors("bad disk magic");
}
if((dp->id.interface & 0x4000) == 0)
print("lookaheads disabled\n");
poperror();
qunlock(cp);
}
/*
* we get an interrupt for every sector transferred
*/
static void
hardintr(Ureg *ur)
{
Controller *cp;
.
388,391c
cp = dp->cp;
qlock(cp);
if(waserror()){
qunlock(cp);
nexterror();
}
.
384,386c
Controller *cp;
.
381,382c
static long
hardident(Drive *dp)
.
377,379c
* get parameters from the drive
.
369,373c
Controller *cp = dp->cp;
qlock(cp);
if(waserror()){
qunlock(cp);
nexterror();
}
outb(cp->pbase+Pbmode, on ? 0xAA : 0x55);
outb(cp->pbase+Pdh, (1<<5) | dp->drive<<4);
outb(cp->pbase+Pcmd, Csetbuf);
poperror();
qunlock(cp);
.
367c
hardsetbuf(Drive *dp, int on)
.
364c
* set read ahead mode (1 == on, 0 == off)
.
360c
sleep(&cp->r, cmddone, cp);
if(cp->status & Serr){
print("hd%d err: status %lux, err %lux\n", dp-hard, cp->status, cp->error);
print("\ttcyl %d, tsec %d, thead %d\n", cp->tcyl, cp->tsec, cp->thead);
print("\tsecs %d, sofar %d\n", cp->secs, cp->sofar);
errors("disk I/O error");
}
if(cmd == Cread)
memmove(va, cp->buf, cp->len);
poperror();
qunlock(cp);
return cp->len;
.
341,358c
/*
* can't xfer across cylinder boundaries.
*/
lsec = (off+len)/dp->bytes;
cyl = lsec/(dp->sectors*dp->heads);
if(cyl == cp->tcyl)
cp->len = len;
else
cp->len = cyl*dp->sectors*dp->heads*dp->bytes - off;
/*
* wait for the controller to accept commands
*/
while(inb(cp->pbase+Pstatus) & Sbusy)
;
/*
* start the transfer
*/
cp->secs = cp->len/dp->bytes;
cp->sofar = 0;
cp->cmd = cmd;
outb(cp->pbase+Pcount, cp->secs);
outb(cp->pbase+Psector, cp->tsec);
outb(cp->pbase+Pdh, (1<<5) | (dp->drive<<4) | cp->thead);
outb(cp->pbase+Pcyllsb, cp->tcyl);
outb(cp->pbase+Pcylmsb, cp->tcyl>>8);
outb(cp->pbase+Pcmd, cmd);
if(cmd == Cwrite){
memmove(cp->buf, va, cp->len);
outss(Pdata, cp->buf, dp->bytes/2);
.
334,339c
/*
* calculate the physical address of off
*/
lsec = off/dp->bytes;
cp->tcyl = lsec/(dp->sectors*dp->heads);
cp->tsec = (lsec % dp->sectors) + 1;
cp->thead = (lsec/dp->sectors) % dp->heads;
.
329,332d
326c
qunlock(cp);
.
324a
cp = dp->cp;
qlock(cp);
.
323c
errors("bad length"); /* BUG - this shouldn't be a problem */
if(off % dp->bytes)
errors("bad offset"); /* BUG - this shouldn't be a problem */
.
320,321c
if(dp->online == 0)
errors("disk offline");
.
316,318c
Controller *cp;
int err;
int lsec;
int cyl;
.
304,313d
301c
* start a disk transfer. hardintr will performa all the iterative
* parts.
.
297c
Controller *cp;
return cp->cmd == 0;
.
295c
cmddone(void *a)
.
273c
dp = &hard[c->qid.path & ~Qmask];
.
241c
dp = &hard[c->qid.path & ~Qmask];
.
238c
return devdirread(c, a, n, harddir, conf.nhard*NHDIR, devgen);
.
195c
return devopen(c, omode, harddir, conf.nhard*NHDIR, devgen);
.
189c
devstat(c, dp, harddir, conf.nhard*NHDIR, devgen);
.
183c
return devwalk(c, name, harddir, conf.nhard*NHDIR, devgen);
.
170c
.
168c
} else
dp->online = 0;
.
165a
harddir[NHDIR*dp->drive].length = dp->cap;
print("drive %d online\n", dp - hard);
.
161,163c
dp->cyl = dp->id.lcyls;
dp->heads = dp->id.lheads;
dp->sectors = dp->id.ls2t;
.
159a
hardsetbuf(dp, 1);
.
157,158c
for(dp = hard; dp < &hard[conf.nhard]; dp++){
.
151a
/*
* Get the characteristics of each drive. Mark unresponsive ones
* off line.
*/
.
149d
142,143d
140a
dp->cp = cp;
if((drive&1) == 0){
cp->buf = ialloc(Maxxfer, 0);
cp->cmd = 0;
cp->pbase = Pbase + (cp-hardc)*8; /* BUG!! guessing */
setvec(Hardvec + (cp-hardc)*8, hardintr); /* BUG!! guessing */
}
sprint(harddir[drive*2].name, "hd%ddata", drive);
dir->length = 0;
dir->qid.path = Qdata + drive;
dir->perm = 0600;
dir++;
sprint(dir->name, "hd%dstruct", drive);
dir->length = 8;
dir->qid.path = Qstruct + drive;
dir->perm = 0600;
dir++;
.
137,139c
hard = ialloc(conf.nhard * sizeof(Drive), 0);
hardc = ialloc(((conf.nhard+1)/2 + 1) * sizeof(Controller), 0);
dir = harddir = ialloc(NHDIR * conf.nhard * sizeof(Dirtab), 0);
for(drive = 0; drive < conf.nhard; drive++){
dp = &hard[drive];
cp = &hardc[drive/2];
dp->drive = drive&1;
.
135a
Controller *cp;
int drive;
Dirtab *dir;
.
131a
/*
* we assume drives 0 and 1 are on the first controller, 2 and 3 on the
* second, etc.
*/
.
130c
static void hardsetbuf(Drive*, int);
.
121,126d
119c
Controller *hardc;
Drive *hard;
Dirtab *harddir;
#define NHDIR 2 /* directory entries/drive */
.
115,116c
/*
* current operation
*/
int cmd; /* current command */
Rendez r; /* wait here for command termination */
char *buf; /* xfer buffer */
int tcyl; /* target cylinder */
int thead; /* target head */
int tsec; /* target sector */
int tbyte; /* target byte */
int len; /* length of transfer (bytes) */
int secs; /* sectors to be xferred */
int sofar; /* bytes transferred so far */
int status;
int error;
Drive *dp; /* drive being accessed */
.
113a
int pbase; /* base port */
.
110,112d
97,100c
Ident id; /* disk properties */
.
87c
Controller *cp;
int drive;
.
39,41c
Qdata= (1<<4),
Qstruct= (2<<4),
Qmask= (3<<4),
Maxxfer= 4*1024, /* maximum transfer size/cmd */
.
35a
Csetbuf= 0xEF,
.
29c
Pcmd= 7, /* cmd port (write) */
.
17,24c
Pdata= 0, /* data port (16 bits) */
Perror= 1, /* error port (read) */
Pbmode= 1, /* buffer mode port (write) */
Pcount= 2, /* sector count port */
Psector= 3, /* sector number port */
Pcyllsb= 4, /* least significant byte cylinder # */
Pcylmsb= 5, /* most significant byte cylinder # */
Pdh= 6, /* drive/head port */
Pstatus= 7, /* status port (read) */
.
## diffname pc/devhard.c 1991/0812
## diff -e /n/bootesdump/1991/0811/sys/src/9/safari/devhard.c /n/bootesdump/1991/0812/sys/src/9/safari/devhard.c
546d
## diffname pc/devhard.c 1991/0813
## diff -e /n/bootesdump/1991/0812/sys/src/9/safari/devhard.c /n/bootesdump/1991/0813/sys/src/9/safari/devhard.c
533c
if(++loop > 10000)
panic("hardintr 2");
.
531a
loop = 0;
.
516c
if(++loop > 10000)
panic("hardintr 1");
.
496a
long loop;
.
490a
* read partition table
*/
static void
hardpart(Drive *dp)
{
Partition *pp;
Ptable *pt;
uchar buf[1024];
pp = &dp->p[0];
strcpy(pp->name, "disk");
pp->start = 0;
pp->end = pp->cap / dp->bytes;
qlock(dp->cp);
hardxfer(dp, Cread, buf, pp->end - 1, dp->bytes);
qunlock(dp->cp);
}
/*
.
483,485d
469c
cp->dp = dp;
outb(cp->pbase+Pdh, (dp->drive<<4));
.
464a
cmdreadywait(cp);
.
445a
sleep(&cp->r, cmddone, cp);
.
442,443c
cmdreadywait(cp);
outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55);
outb(cp->pbase+Pdh, (dp->drive<<4));
.
404c
outb(cp->pbase+Pdh, (dp->drive<<4) | cp->thead);
.
401a
cp->dp = dp;
.
390,394c
cmdreadywait(cp);
.
346a
* wait for the controller to be ready to accept a command
*/
static void
cmdreadywait(Controller *cp)
{
long start;
start = m->ticks;
while((inb(cp->pbase+Pstatus) & (Sready|Sbusy)) != Sready)
if(TK2MS(m->ticks - start) > 1){
print("cmdreadywait failed\n");
errors("disk not responding");
}
}
/*
.
341c
Controller *cp = a;
.
208d
201a
hardpart(dp);
.
199a
dp->bytes = 512;
.
142a
static int
hardgen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp)
{
Qid qid;
int drive;
char *name;
Drive *dp;
Partition *pp;
ulong l;
qid.vers = 0;
drive = s/(Npart+1);
s = s % (Npart+1);
if(drive >= conf.nhard)
return -1;
dp = &hard[drive];
if(s == 0){
sprint(name, "hd%dparition", drive);
qid.path = MKQID(Qpart, drive, 0);
l = dp->npart * sizeof(Partition);
} else if(s-1 < p.npart){
pp = &dp->p[s-1];
sprint(name, "hd%d%s", drive, pp->name);
qid.path = MKQID(Qdata, drive, s-1);
l = (pp->end - pp->start) * dp->cp->bytes;
} else
return 0;
devdir(c, qid, name, l, 0600, dirp);
return 1;
}
.
141a
static void hardpart(Drive*);
.
96c
ulong cap; /* total bytes */
.
94a
int npart; /* number of real partitions */
Partition p[Npart];
.
85a
struct Partition
{
ulong start;
ulong end;
uchar name[NAMELEN];
};
struct Ptable
{
uchar magic[4]; /* ascii "disk" */
uchar n[4]; /* number of partitions */
struct
{
uchar start[4]; /* starting block */
uchar end[4]; /* ending block */
uchar name[NAMELEN];
} p[1];
};
.
46a
#define PART(x) ((x)&0x3)
#define DRIVE(x) (((x)>>3)&0x7)
#define MKQID(t,d,p) ((t) | ((d)<<3) | (p))
.
45a
Npart= 8+1, /* 8 sub partitions and one for the disk */
.
41,43c
Qdata= (1<<(3+3)),
Qpart= (2<<(3+3)),
Qmask= (3<<(3+3)),
.
28c
Sdrq= (1<<3),
.
19c
Pprecomp= 1, /* buffer mode port (write) */
.
11a
typedef struct Partition Partition;
typedef struct Ptable Ptable;
.
## diffname pc/devhard.c 1991/0814
## diff -e /n/bootesdump/1991/0813/sys/src/9/safari/devhard.c /n/bootesdump/1991/0814/sys/src/9/safari/devhard.c
646c
print("weird disk interrupt\n");
.
644a
case Csetbuf:
cp->cmd = 0;
wakeup(&cp->r);
break;
.
583,586c
if(waserror()){
print("error in hardpart\n");
nexterror();
}
hardxfer(dp, pp, Cread, buf, (pp->end - 1)*dp->bytes, dp->bytes);
buf[dp->bytes] = 0;
n = getfields(buf, line, Npart+1, '\n');
if(strncmp(line[0], MAGIC, sizeof(MAGIC)-1) != 0){
print("bad partition table 1\n");
goto out;
}
for(i = 1; i < n; i++){
pp++;
if(getfields(line[i], field, 3, 0) != 3){
print("bad partition field\n");
goto out;
}
if(strlen(field[0]) > NAMELEN){
print("bad partition name\n");
goto out;
}
strcpy(pp->name, field[0]);
pp->start = strtoul(field[1], 0, 0);
pp->end = strtoul(field[2], 0, 0);
if(pp->start > pp->end || pp->start >= dp->p[0].end){
print("bad partition limit\n");
goto out;
}
print("partition %s from %d to %d\n", pp->name, pp->start, pp->end);
dp->npart++;
}
out:
poperror();
.
581c
pp->end = dp->cap / dp->bytes;
pp++;
strcpy(pp->name, "partition");
pp->start = dp->p[0].end - 1;
pp->end = dp->p[0].end;
dp->npart = 2;
.
575,576c
char *line[Npart+1];
char *field[3];
char buf[1024];
ulong n;
int i;
.
570a
#define MAGIC "plan9 partitions"
.
569c
* read partition table. The partition table is just ascii strings.
.
538a
print("waserror in hardident\n");
.
517a
cp->cmd = Csetbuf;
.
460a
lsec += pp->start;
if(lsec > pp->end)
errors("xfer past end of partition\n");
.
452a
lsec += pp->start;
if(lsec >= pp->end)
errors("xfer past end of partition\n");
.
441a
print("hardxfer %ld %ld\n", off, len);
print("hardxfer part %s %ld %ld\n", pp->name, pp->start, pp->end);
.
428c
hardxfer(Drive *dp, Partition *pp, int cmd, void *va, long off, long len)
.
387,388c
case Qpart:
.
382c
pp = &dp->p[PART(c->qid.path)];
i = hardxfer(dp, pp, Cwrite, aa+rv, c->offset+rv, n-rv);
.
375a
Partition *pp;
.
355,362c
case Qpart:
.
350c
pp = &dp->p[PART(c->qid.path)];
i = hardxfer(dp, pp, Cread, aa+rv, c->offset+rv, n-rv);
.
343c
return devdirread(c, a, n, 0, 0, hardgen);
.
340a
Partition *pp;
.
326,334d
300c
return devopen(c, omode, 0, 0, hardgen);
.
294c
devstat(c, dp, 0, 0, hardgen);
.
288c
return devwalk(c, name, 0, 0, hardgen);
.
270a
hardpart(dp);
.
269d
263d
231,240d
217d
213d
202a
.
195,196c
qid.path = MKQID(Qdata, drive, s);
l = (pp->end - pp->start) * dp->bytes;
.
188,193c
if(s < dp->npart){
pp = &dp->p[s];
.
182,183c
drive = s/Npart;
s = s % Npart;
.
176c
char name[NAMELEN];
.
166c
static long hardxfer(Drive*, Partition*, int, void*, long, long);
.
162,163d
99,110d
96c
char name[NAMELEN+1];
.
48c
Npart= 8+2, /* 8 sub partitions, disk, and partiiton */
.
13d
## diffname pc/devhard.c 1991/0815
## diff -e /n/bootesdump/1991/0814/sys/src/9/safari/devhard.c /n/bootesdump/1991/0815/sys/src/9/safari/devhard.c
646,647c
cp->sofar += cp->dp->bytes;
if(cp->sofar >= cp->len){
.
513c
cp->toskip = 0;
.
437c
cp->toskip = off % dp->bytes;
.
422c
lsec = (off+len+dp->bytes-1)/dp->bytes;
.
420c
* can't xfer across cylinder boundaries or end of disk
.
398,400d
393,396c
if(len > Maxxfer)
len = Maxxfer;
.
141a
int toskip; /* bytes to skip over */
.
140c
int toxfer; /* bytes to be xferred */
.
## diffname pc/devhard.c 1991/0817
## diff -e /n/bootesdump/1991/0815/sys/src/9/safari/devhard.c /n/bootesdump/1991/0817/sys/src/9/safari/devhard.c
642,643c
cp->sofar++;
if(cp->sofar >= cp->nsecs){
.
621,622c
outss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes],
dp->bytes/2);
.
617c
if(cp->sofar < cp->nsecs){
.
605a
dp = cp->dp;
.
598a
Drive *dp;
.
588a
qunlock(cp);
.
582c
print("bad partition limit\n");
.
575c
print("bad partition name\n");
.
571c
print("bad partition field\n");
.
565c
print("bad partition magic\n");
.
563c
n = getfields(cp->buf, line, Npart+1, '\n');
.
560,561c
hardxfer(dp, pp, Cread, 0, dp->bytes);
cp->buf[dp->bytes-1] = 0;
.
555a
qunlock(cp);
.
554a
cp = dp->cp;
qlock(cp);
.
541d
538a
Controller *cp;
.
520c
memmove(&dp->id, cp->buf, dp->bytes);
.
508,509c
cp->nsecs = 1;
.
458,460c
return cp->nsecs*dp->bytes;
.
455,456d
452c
print("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
.
448a
.
447a
.
445,446c
loop = 0;
while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
if(++loop > 10000)
panic("hardxfer");
outss(cp->pbase+Pdata, cp->buf, dp->bytes/2);
.
437c
cp->sofar = 0;
print("xfer:\ttcyl %d, tsec %d, thead %d\n", cp->tcyl, cp->tsec, cp->thead);
print("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
outb(cp->pbase+Pcount, cp->nsecs);
.
433,434d
418,426c
if(lsec+len > pp->end)
len = pp->end - lsec;
cp->nsecs = len;
.
416c
* can't xfer past end of disk
.
410c
return 0;
.
407,408c
cp = dp->cp;
lsec = start + pp->start;
.
405c
* calculate physical address
.
397,403d
395a
len = (len + dp->bytes - 1) / dp->bytes;
.
393a
/*
* cut transfer size down to disk buffer size
*/
start = start / dp->bytes;
.
390a
int loop;
.
389c
long lsec;
.
385c
hardxfer(Drive *dp, Partition *pp, int cmd, long start, long len)
.
381c
* transfer a number of sectors. hardintr will perform all the iterative
.
349a
/*
* if not starting on a sector boundary,
* read in the first sector before writing
* it out.
*/
i = c->offset % dp->bytes;
if(i){
hardxfer(dp, pp, Cread, c->offset-i, dp->bytes);
if(i+n > dp->bytes)
rv = dp->bytes - i;
else
rv = n;
memmove(cp->buf+i, aa, rv);
hardxfer(dp, pp, Cwrite, c->offset-i, dp->bytes);
} else
rv = 0;
/*
* write out the full sectors
*/
for(; rv + dp->bytes <= n; rv += i){
i = n - rv;
if(i > Maxxfer)
i = Maxxfer;
memmove(cp->buf, aa+rv, i);
i = hardxfer(dp, pp, Cwrite, c->offset+rv, i);
if(i == 0)
break;
}
/*
* if not ending on a sector boundary,
* read in the last sector before writing
* it out.
*/
if(n > rv){
hardxfer(dp, pp, Cread, c->offset+rv, dp->bytes);
memmove(cp->buf, aa+rv, n - rv);
hardxfer(dp, pp, Cwrite, c->offset+rv, dp->bytes);
rv = n;
}
qunlock(cp);
poperror();
.
334,348c
if(c->qid.path == CHDIR)
errors("can't write directory");
dp = &hard[DRIVE(c->qid.path)];
pp = &dp->p[PART(c->qid.path)];
cp = dp->cp;
qlock(cp);
if(waserror()){
qunlock(cp);
nexterror();
.
332a
Controller *cp;
.
322a
skip = c->offset % dp->bytes;
for(rv = 0; rv < n; rv += i){
i = hardxfer(dp, pp, Cread, c->offset+rv-skip, n-rv+skip);
if(i == 0)
break;
i -= skip;
if(i > n - rv)
i = n - rv;
memmove(aa+rv, cp->buf + skip, i);
skip = 0;
}
qunlock(cp);
poperror();
.
307,321c
dp = &hard[DRIVE(c->qid.path)];
pp = &dp->p[PART(c->qid.path)];
cp = dp->cp;
qlock(cp);
if(waserror()){
qunlock(cp);
nexterror();
.
302a
Controller *cp;
.
300a
int skip;
.
177c
qid.path = MKQID(drive, s);
.
152c
static long hardxfer(Drive*, Partition*, int, long, long);
.
142d
139,140c
int nsecs; /* length of transfer (sectors) */
.
51c
#define MKQID(d,p) (((d)<<3) | (p))
.
42,44d
## diffname pc/devhard.c 1991/0818
## diff -e /n/bootesdump/1991/0817/sys/src/9/safari/devhard.c /n/bootesdump/1991/0818/sys/src/9/safari/devhard.c
626c
break;
.
619c
break;
.
615c
break;
.
## diffname pc/devhard.c 1991/0819
## diff -e /n/bootesdump/1991/0818/sys/src/9/safari/devhard.c /n/bootesdump/1991/0819/sys/src/9/safari/devhard.c
617,621c
strncpy(pp->name, field[0], NAMELEN);
.
605a
/*
* parse partition table.
*/
.
595,602c
/*
* read partition table from disk, null terminate
*/
.
584a
cp = dp->cp;
qlock(cp);
if(waserror()){
qunlock(cp);
print("error in hardpart\n");
nexterror();
}
/*
* we always have a partition for the whole disk
* and one for the partition table
*/
.
475,476c
/*print("xfer:\ttcyl %d, tsec %d, thead %d\n", cp->tcyl, cp->tsec, cp->thead);
print("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);/**/
.
171a
name[NAMELEN] = 0;
.
157c
char name[NAMELEN+4];
.
## diffname pc/devhard.c 1991/0820
## diff -e /n/bootesdump/1991/0819/sys/src/9/safari/devhard.c /n/bootesdump/1991/0820/sys/src/9/safari/devhard.c
693,694c
inss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes],
dp->bytes/2);
.
635d
632d
624,625c
if(getfields(line[i], field, 3, ' ') != 3){
.
619d
476c
print("xfer:\ttcyl %d, tsec %d, thead %d\n", cp->tcyl, cp->tsec, cp->thead);
.
391c
rv += partial;
.
389c
memmove(cp->buf, aa+rv, partial);
.
387c
if(partial){
.
372c
partial = (n - rv) % dp->bytes;
n -= partial;
for(; rv < n; rv += i){
.
364,365c
memmove(cp->buf+partial, aa, rv);
hardxfer(dp, pp, Cwrite, c->offset-partial, dp->bytes);
.
357,361c
partial = c->offset % dp->bytes;
if(partial){
hardxfer(dp, pp, Cread, c->offset-partial, dp->bytes);
if(partial+n > dp->bytes)
rv = dp->bytes - partial;
.
335c
long rv, i, partial;
.
321a
{int j;
print("0x%lux(%d) <- ", aa+rv, i);
for(j = 0; j<32; j++)
print("%.2ux ", cp->buf[j+skip]);
print("\n");
}
.
## diffname pc/devhard.c 1991/0821
## diff -e /n/bootesdump/1991/0820/sys/src/9/safari/devhard.c /n/bootesdump/1991/0821/sys/src/9/safari/devhard.c
675a
loop = 0;
.
665c
loop = 0;
while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy)
if(++loop > 10000)
panic("hardintr 0");
.
657a
x = spllo(); /* let in other interrupts */
.
656a
int x;
.
485c
cp->status = 0;
/*print("xfer:\ttcyl %d, tsec %d, thead %d\n", cp->tcyl, cp->tsec, cp->thead);
.
322,328d
177a
pp = &dp->p[s];
sprint(name, "hd%d%s", drive, pp->name);
name[NAMELEN] = 0;
qid.path = MKQID(drive, s);
l = (pp->end - pp->start) * dp->bytes;
.
169,175c
if(s >= dp->npart)
.
46,48c
#define PART(x) ((x)&0xF)
#define DRIVE(x) (((x)>>4)&0x7)
#define MKQID(d,p) (((d)<<4) | (p))
.
44c
Npart= 8+2, /* 8 sub partitions, disk, and partition */
.
## diffname pc/devhard.c 1991/0906
## diff -e /n/bootesdump/1991/0821/sys/src/9/safari/devhard.c /n/bootesdump/1991/0906/sys/src/9/safari/devhard.c
652c
spllo(); /* let in other interrupts */
.
650d
## diffname pc/devhard.c 1991/0919
## diff -e /n/bootesdump/1991/0906/sys/src/9/safari/devhard.c /n/bootesdump/1991/0919/sys/src/9/safari/devhard.c
177c
devdir(c, qid, name, l, 0666, dirp);
.
## diffname pc/devhard.c 1991/0921
## diff -e /n/bootesdump/1991/0919/sys/src/9/safari/devhard.c /n/bootesdump/1991/0921/sys/src/9/safari/devhard.c
241c
return devattach('w', spec);
.
## diffname pc/devhard.c 1991/1109
## diff -e /n/bootesdump/1991/0921/sys/src/9/safari/devhard.c /n/bootesdump/1991/1109/sys/src/9/safari/devhard.c
177c
devdir(c, qid, name, l, eve, 0666, dirp);
.
## diffname pc/devhard.c 1991/1211
## diff -e /n/bootesdump/1991/1109/sys/src/9/safari/devhard.c /n/bootesdump/1991/1211/sys/src/9/safari/devhard.c
564,568d
560c
print("bad disk ident status\n");
.
545d
229,231c
switch(dp->id.magic){
case 0xA5A: /* conner drive on the AT&T NSX (safari) */
dp->cyl = dp->id.lcyls;
dp->heads = dp->id.lheads;
dp->sectors = dp->id.ls2t;
break;
case 0x324A: /* hard drive on the AT&T 6386 */
dp->cyl = dp->id.lcyls - 4;
dp->heads = dp->id.lheads;
dp->sectors = dp->id.ls2t - 1;
break;
default:
print("unknown hard disk type\n");
errors("unknown hard disk type");
}
.
## diffname pc/devhard.c 1992/0111
## diff -e /n/bootesdump/1991/1211/sys/src/9/safari/devhard.c /n/bootesdump/1992/0111/sys/src/9/safari/devhard.c
7c
#include "../port/error.h"
.
## diffname pc/devhard.c 1992/0114
## diff -e /n/bootesdump/1992/0111/sys/src/9/safari/devhard.c /n/bootesdump/1992/0114/sys/src/9/safari/devhard.c
572c
error(Eio);
.
513c
error(Eio);
.
453c
error(Eio);
.
435c
error(Eio);
.
352c
error(Eisdir);
.
242c
error(Egreg);
.
## diffname pc/devhard.c 1992/0219
## diff -e /n/bootesdump/1992/0114/sys/src/9/safari/devhard.c /n/bootesdump/1992/0219/sys/src/9/safari/devhard.c
642d
634,640d
626,632c
if(strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
for(i = 1; i < n; i++){
pp++;
if(getfields(line[i], field, 3, ' ') != 3)
break;
strncpy(pp->name, field[0], NAMELEN);
pp->start = strtoul(field[1], 0, 0);
pp->end = strtoul(field[2], 0, 0);
if(pp->start > pp->end || pp->start >= dp->p[0].end)
break;
dp->npart++;
.
## diffname pc/devhard.c 1992/0220
## diff -e /n/bootesdump/1992/0219/sys/src/9/safari/devhard.c /n/bootesdump/1992/0220/sys/src/9/safari/devhard.c
460a
if(cmd == Cread && len > Maxread)
len = Maxread;
.
43a
Maxread= 1024, /* maximum transfer size/read */
.
## diffname pc/devhard.c 1992/0321
## diff -e /n/bootesdump/1992/0220/sys/src/9/safari/devhard.c /n/bootesdump/1992/0321/sys/src/9/safari/devhard.c
2c
#include "../port/lib.h"
.
## diffname pc/devhard.c 1992/0402
## diff -e /n/bootesdump/1992/0321/sys/src/9/safari/devhard.c /n/bootesdump/1992/0402/sys/src/9/safari/devhard.c
570c
outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4));
.
539,540c
outb(cp->pbase+Pprecomp, on ? 0xAA : 0xFF);
outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4));
.
497c
outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4) | cp->thead);
.
234a
hardsetbuf(dp, 1);
.
228c
hardsetbuf(dp, 0);
.
## diffname pc/devhard.c 1992/0423
## diff -e /n/bootesdump/1992/0402/sys/src/9/safari/devhard.c /n/bootesdump/1992/0423/sys/src/9/safari/devhard.c
716c
print("weird disk interrupt, cmd=%02x\n",
cp->cmd);
.
254c
drivecomment=0; /* only the first time */
.
242,244c
default: /* others: we hope this works */
if (drivecomment) {
print("unknown hard disk type, magic=%04x\n",
dp->id.magic);
print(" lcyls=%d lheads=%d sectors=%d\n",
dp->id.lcyls, dp->id.lheads, dp->id.ls2t);
print(" ncyls=%d nheads=%d dlcyls=%d dlheads=%d\n",
dp->id.ncyls, dp->id.nheads, dp->id.dlcyls,
dp->id.dlheads);
}
dp->cyl = dp->id.lcyls;
dp->heads = dp->id.lheads;
dp->sectors = dp->id.ls2t;
break;
.
223a
static int drivecomment=1;
.
56c
ushort magic; /* drive type magic */
.
## diffname pc/devhard.c 1992/0424
## diff -e /n/bootesdump/1992/0423/sys/src/9/safari/devhard.c /n/bootesdump/1992/0424/sys/src/9/safari/devhard.c
728,729c
print("weird disk interrupt, cmd=%02x, status=%02x\n",
cp->cmd, cp->status);
.
726a
case 0: /*
* These don't seem to mean anything. Should we wakeup?
*/
break;
.
249,251d
247c
print(" cyl=%d h=%d sec=%d\n",
.
245c
print("unknown hard disk type, magic=%04x",
.
## diffname pc/devhard.c 1992/0425
## diff -e /n/bootesdump/1992/0424/sys/src/9/safari/devhard.c /n/bootesdump/1992/0425/sys/src/9/safari/devhard.c
724,726c
case 0:
print("interrupt cmd=0, lastcmd=%02x status=%02x\n",
cp->lastcmd, cp->status);
.
720a
cp->lastcmd = cp->cmd;
.
715a
cp->lastcmd = cp->cmd;
.
710,711c
if(++loop > 10000) {
print("cmd=%lux status=%lux\n",
cp->cmd, inb(cp->pbase+Pstatus));
panic("hardintr: read/ident");
}
.
702a
cp->lastcmd = cp->cmd;
.
701a
loop = 0;
while((inb(cp->pbase+Pstatus) & Sbusy) != 0)
if(++loop > 10000) {
print("cmd=%lux status=%lux\n",
cp->cmd, inb(cp->pbase+Pstatus));
panic("hardintr: wait busy");
}
.
695a
cp->lastcmd = cp->cmd;
.
691,692c
if(++loop > 10000) {
print("cmd=%lux status=%lux\n",
cp->cmd, inb(cp->pbase+Pstatus));
panic("hardintr: write");
}
.
681a
cp->lastcmd = cp->cmd;
.
677,678c
if(++loop > 10000) {
print("cmd=%lux status=%lux\n",
cp->cmd, inb(cp->pbase+Pstatus));
panic("hardintr: wait busy");
}
.
203a
cp->lastcmd = cp->cmd;
.
130a
int lastcmd; /* debugging info */
.
## diffname pc/devhard.c 1992/0429
## diff -e /n/bootesdump/1992/0425/sys/src/9/safari/devhard.c /n/bootesdump/1992/0429/sys/src/9/safari/devhard.c
745a
break;
case Cident2:
cp->lastcmd = cp->cmd;
cp->cmd = 0;
.
738c
if (cp->cmd == Cread)
cp->cmd = 0;
else
cp->cmd = Cident2;
.
590c
/*
* this function appears to respond with an extra interrupt after
* the indent information is read, except on the safari. The following
* delay gives this extra interrupt a chance to happen while we are quiet.
* Otherwise, the interrupt may come during a subsequent read or write,
* causing a panic and much confusion.
*/
if (cp->cmd == Cident2)
tsleep(&cp->r, return0, 0, 10);
cp->cmd = 0;
.
37a
Cident2= 0xFF, /* pseudo command for post Cident interrupt */
.
## diffname pc/devhard.c 1992/0509
## diff -e /n/bootesdump/1992/0429/sys/src/9/safari/devhard.c /n/bootesdump/1992/0509/sys/src/9/safari/devhard.c
663a
if(dp->repl.p)
hardreplinit(dp);
.
656a
if(strncmp(pp->name, "repl", NAMELEN) == 0)
dp->repl.p = pp;
.
651c
if(strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0){
.
641a
* initialise the bad-block replacement info
*/
dp->repl.p = 0;
/*
.
608d
605a
* Read block replacement table.
* The table is just ascii block numbers.
*/
static void
hardreplinit(Drive *dp)
{
Controller *cp;
char *line[Nrepl+1];
char *field[1];
ulong n;
int i;
/*
* check the partition is big enough
*/
if(dp->repl.p->end - dp->repl.p->start < Nrepl+1){
dp->repl.p = 0;
return;
}
cp = dp->cp;
/*
* read replacement table from disk, null terminate
*/
hardxfer(dp, dp->repl.p, Cread, 0, dp->bytes);
cp->buf[dp->bytes-1] = 0;
/*
* parse replacement table.
*/
n = getfields(cp->buf, line, Nrepl+1, '\n');
if(strncmp(line[0], REPLMAGIC, sizeof(REPLMAGIC)-1)){
dp->repl.p = 0;
return;
}
for(dp->repl.nrepl = 0, i = 1; i < n; i++, dp->repl.nrepl++){
if(getfields(line[i], field, 1, ' ') != 1)
break;
if((dp->repl.blk[dp->repl.nrepl] = strtoul(field[1], 0, 0)) <= 0)
break;
}
}
/*
.
604a
.
526c
print("hd%d err: lsec %ld status %lux, err %lux\n", dp-hard, lsec, cp->status, cp->error);
.
506,507c
.
107a
Repl repl;
.
96a
struct Repl
{
Partition *p;
int nrepl;
ulong blk[Nrepl];
};
#define PARTMAGIC "plan9 partitions"
#define REPLMAGIC "block replacements"
.
46a
Nrepl= 16, /* maximum replacement blocks */
.
45c
Maxread= 4*1024, /* maximum transfer size/read */
.
12a
typedef struct Repl Repl;
.
## diffname pc/devhard.c 1992/0512
## diff -e /n/bootesdump/1992/0509/sys/src/9/safari/devhard.c /n/bootesdump/1992/0512/sys/src/9/safari/devhard.c
46c
Maxread= 1*1024, /* maximum transfer size/read */
.
## diffname pc/devhard.c 1992/0513
## diff -e /n/bootesdump/1992/0512/sys/src/9/safari/devhard.c /n/bootesdump/1992/0513/sys/src/9/safari/devhard.c
658c
dp->repl.blk[dp->repl.nrepl] = strtoul(field[0], 0, 0);
if(dp->repl.blk[dp->repl.nrepl] <= 0)
.
544c
return cp->sofar*dp->bytes;
.
538,540c
print("hd%d err: lblk %ld status %lux, err %lux\n",
dp-hard, lblk, cp->status, cp->error);
print("\tcyl %d, sec %d, head %d\n", cyl, sec, head);
print("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
hardrepl(dp, lblk+cp->sofar);
.
520,524c
outb(cp->pbase+Pcount, cp->nsecs-cp->sofar);
outb(cp->pbase+Psector, sec);
outb(cp->pbase+Pdh, 0x20 | head);
outb(cp->pbase+Pcyllsb, cyl);
outb(cp->pbase+Pcylmsb, cyl>>8);
.
517d
506,507c
if(lblk+len > pp->end)
len = pp->end - lblk;
.
499,501c
cyl = lblk/(dp->sectors*dp->heads);
sec = (lblk % dp->sectors) + 1;
head = (dp->drive<<4) | ((lblk/dp->sectors) % dp->heads);
.
495,497c
lblk = start + pp->start;
if(lblk >= pp->end)
.
491a
retry:
if(len == 0)
return cp->sofar*dp->bytes;
.
481a
cp = dp->cp;
cp->sofar = 0;
.
475,476c
long lblk;
int cyl, sec, head;
.
465a
static void
hardrepl(Drive *dp, long bblk)
{
int i;
if(dp->repl.p == 0)
return;
for(i = 0; i < dp->repl.nrepl; i++){
if(dp->repl.blk[i] == bblk)
print("found bblk %ld at offset %ld\n", bblk, i);
}
}
.
153c
int sofar; /* sectors transferred so far */
.
148,151d
48c
Nrepl= 64, /* maximum replacement blocks */
.
## diffname pc/devhard.c 1992/0514
## diff -e /n/bootesdump/1992/0513/sys/src/9/safari/devhard.c /n/bootesdump/1992/0514/sys/src/9/safari/devhard.c
828c
cp->nsecs--;
if(cp->nsecs == 0){
.
796c
cp->nsecs--;
} else {
.
786c
if(cp->nsecs){
.
775a
if(cp->status & (Sdwf|Scorr))
print("hardintr: cmd=#%lux, status=#%lux\n", cp->cmd, cp->status);
.
545a
cp->nsecs--;
.
533c
outb(cp->pbase+Pcount, cp->nsecs);
.
531a
cmdreadywait(cp);
.
529,530d
524c
cp->cmd = cmd;
cp->dp = dp;
.
30a
Scorr= (1<<2),
.
29a
Sdwf= (1<<5),
.
## diffname pc/devhard.c 1992/05141
## diff -e /n/bootesdump/1992/0514/sys/src/9/safari/devhard.c /n/bootesdump/1992/05141/sys/src/9/safari/devhard.c
834,835c
if(cp->sofar >= cp->nsecs){
.
801,802c
} else{
.
791c
if(cp->sofar < cp->nsecs){
.
779,780d
548d
535c
outb(cp->pbase+Pcount, cp->nsecs-cp->sofar);
.
533d
531a
cp->cmd = cmd;
cp->dp = dp;
.
526,527c
cmdreadywait(cp);
.
32d
30d
## diffname pc/devhard.c 1992/0519
## diff -e /n/bootesdump/1992/05141/sys/src/9/safari/devhard.c /n/bootesdump/1992/0519/sys/src/9/safari/devhard.c
261a
case 0x427a: /* for now: a list of those that work */
.
## diffname pc/devhard.c 1992/0625
## diff -e /n/bootesdump/1992/0519/sys/src/9/safari/devhard.c /n/bootesdump/1992/0625/sys/src/9/safari/devhard.c
214c
cp->buf = xalloc(Maxxfer);
.
204,205c
hard = xalloc(conf.nhard * sizeof(Drive));
hardc = xalloc(((conf.nhard+1)/2 + 1) * sizeof(Controller));
.
## diffname pc/devhard.c 1992/0711
## diff -e /n/bootesdump/1992/0625/sys/src/9/safari/devhard.c /n/bootesdump/1992/0711/sys/src/9/safari/devhard.c
760a
USED(ur);
.
593c
static void
.
484d
323a
USED(c, dp);
.
317a
USED(c);
.
312a
USED(c);
.
306a
USED(c, name, omode, perm);
.
173a
USED(tab, ntab);
.
160c
static void hardident(Drive*);
.
## diffname pc/devhard.c 1992/0815
## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/devhard.c /n/bootesdump/1992/0815/sys/src/9/pc/devhard.c
831,832d
824,829c
addr = cp->buf;
if(addr){
addr += cp->sofar*dp->bytes;
inss(cp->pbase+Pdata, addr, dp->bytes/2);
.
815a
}
loop = 0;
while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
if(++loop > 10000) {
print("cmd=%lux status=%lux\n",
cp->cmd, inb(cp->pbase+Pstatus));
panic("hardintr: read/ident");
.
800,801c
addr = cp->buf;
if(addr){
addr += cp->sofar*dp->bytes;
outss(cp->pbase+Pdata, addr, dp->bytes/2);
}
.
763a
char *addr;
.
751,752d
748a
free(buf);
poperror();
.
733c
n = getfields(buf, line, Npart+1, '\n');
.
727,728c
hardxfer(dp, pp, Cread, 0, dp->bytes, buf);
buf[dp->bytes-1] = 0;
.
723a
buf = smalloc(Maxxfer);
if(waserror()){
free(buf);
nexterror();
}
.
697,704d
695a
char *buf;
.
691d
675,681c
free(buf);
poperror();
.
673c
} else {
for(dp->repl.nrepl = 0, i = 1; i < n; i++, dp->repl.nrepl++){
if(getfields(line[i], field, 1, ' ') != 1)
break;
dp->repl.blk[dp->repl.nrepl] = strtoul(field[0], 0, 0);
if(dp->repl.blk[dp->repl.nrepl] <= 0)
break;
}
.
670c
n = getfields(buf, line, Nrepl+1, '\n');
.
664,665c
hardxfer(dp, dp->repl.p, Cread, 0, dp->bytes, buf);
buf[dp->bytes-1] = 0;
.
659c
buf = smalloc(Maxxfer);
if(waserror()){
free(buf);
nexterror();
}
.
649a
char *buf;
.
645d
632a
cp->buf = 0;
.
622c
memmove(&dp->id, buf, dp->bytes);
.
614a
cp->buf = buf;
.
602a
buf = smalloc(Maxxfer);
.
600a
char *buf;
.
562a
cp->buf = 0;
qunlock(cp);
poperror();
.
522a
* go for it
*/
cp = dp->cp;
qlock(cp);
cp->sofar = 0;
cp->buf = buf;
if(waserror()){
cp->buf = 0;
qunlock(cp);
nexterror();
}
/*
.
511c
return 0;
.
508,509d
496,498d
486c
hardxfer(Drive *dp, Partition *pp, int cmd, long start, long len, char *buf)
.
435c
free(buf);
.
430,432c
hardxfer(dp, pp, Cread, c->offset+rv, dp->bytes, buf);
memmove(buf, aa+rv, partial);
hardxfer(dp, pp, Cwrite, c->offset+rv, dp->bytes, buf);
.
418,419c
memmove(buf, aa+rv, i);
i = hardxfer(dp, pp, Cwrite, c->offset+rv, i, buf);
.
404,405c
memmove(buf+partial, aa, rv);
hardxfer(dp, pp, Cwrite, c->offset-partial, dp->bytes, buf);
.
399c
hardxfer(dp, pp, Cread, c->offset-partial, dp->bytes, buf);
.
391a
.
389c
free(buf);
.
385,387c
buf = smalloc(Maxxfer);
.
378c
char *buf;
.
365c
free(buf);
.
362c
memmove(aa+rv, buf + skip, i);
.
356c
i = hardxfer(dp, pp, Cread, c->offset+rv-skip, n-rv+skip, buf);
.
353a
dp = &hard[DRIVE(c->qid.path)];
pp = &dp->p[PART(c->qid.path)];
.
351c
free(buf);
.
345,349c
buf = smalloc(Maxxfer);
.
340c
char *buf;
.
215c
cp->buf = 0;
.
159c
static long hardxfer(Drive*, Partition*, int, long, long, char*);
.
45,46c
Maxxfer= 512, /* maximum transfer size/cmd */
Maxread= 512, /* maximum transfer size/read */
.
## diffname pc/devhard.c 1992/0826
## diff -e /n/bootesdump/1992/0815/sys/src/9/pc/devhard.c /n/bootesdump/1992/0826/sys/src/9/pc/devhard.c
836,842d
817,818c
while(((cp->status = inb(cp->pbase+Pstatus)) & Sdrq) == 0)
if(++loop > 100) {
.
804a
}
.
799,800c
while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy){
if(++loop > 100) {
.
789d
649a
free(buf);
.
641c
* the ident information is read, except on the safari. The following
.
602a
if(cp->status & Serr)
print("hd%d setbuf err: status %lux, err %lux\n",
dp-hard, cp->status, cp->error);
.
597c
outb(cp->pbase+Pprecomp, 0xAA);
.
584c
hardsetbuf(Drive *dp)
.
581c
* set read ahead mode
.
503,504d
249c
hardsetbuf(dp);
.
242d
161c
static void hardsetbuf(Drive*);
.
45,46c
Maxxfer= 32*512, /* maximum transfer size/cmd */
.
## diffname pc/devhard.c 1992/0901
## diff -e /n/bootesdump/1992/0826/sys/src/9/pc/devhard.c /n/bootesdump/1992/0901/sys/src/9/pc/devhard.c
840c
DPRINT("cmd=%lux status=%lux\n",
.
820c
DPRINT("cmd=%lux status=%lux\n",
.
801c
DPRINT("cmd=%lux status=%lux\n",
.
635c
DPRINT("bad disk ident status\n");
.
600c
DPRINT("hd%d setbuf err: status %lux, err %lux\n",
.
564,565c
DPRINT("\tcyl %d, sec %d, head %d\n", cyl, sec, head);
DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
.
562c
DPRINT("hd%d err: lblk %ld status %lux, err %lux\n",
.
476c
DPRINT("found bblk %ld at offset %ld\n", bblk, i);
.
462c
DPRINT("cmdreadywait failed\n");
.
8a
#define DPRINT if(0)print
.
## diffname pc/devhard.c 1992/0902
## diff -e /n/bootesdump/1992/0901/sys/src/9/pc/devhard.c /n/bootesdump/1992/0902/sys/src/9/pc/devhard.c
876,879d
867a
case Cinitparam:
.
609a
* set the drive parameters
*/
static void
hardinitparam(Drive *dp)
{
Controller *cp = dp->cp;
qlock(cp);
if(waserror()){
qunlock(cp);
nexterror();
}
cmdreadywait(cp);
cp->cmd = Cinitparam;
outb(cp->pbase+Psector, dp->sectors);
outb(cp->pbase+Pdh, 0x20 | (dp->heads-1) | (dp->drive<<4));
outb(cp->pbase+Pcmd, Cinitparam);
sleep(&cp->r, cmddone, cp);
if(cp->status & Serr)
DPRINT("hd%d initparam err: status %lux, err %lux\n",
dp-hard, cp->status, cp->error);
poperror();
qunlock(cp);
}
/*
.
595c
outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55);
.
582c
hardsetbuf(Drive *dp, int on)
.
272c
/*
* Try reading the partition table (last disk sector).
* If an error occurs set the drive parameters and try
* again. This works if the parameters reported
* by the disk are the physical parameters rather than
* the current logical ones (as they are on the NCR 3170).
*
* We don't routinely set the parameters since it confuses
* some disks (on the Gateway and AT&T Safari for example).
*/
if(waserror()){
hardinitparam(dp); /* set drive parameters */
hardpart();
} else {
hardpart();
poperror();
}
.
257,263d
245,251c
case 0x324A: /* hard drive on the AT&T 6386, it lies */
.
243a
hardsetbuf(dp, 1);
/*
* for now use the configuration word to identify the
* wayward 6386 disk. BUG!!! This word isn't
* meant to identify disks, but we have nothing
* better.
*/
.
242c
/*
* the following is magic to determine the parameters
* (number of cylinders/sectors/heads) on an IDE drive.
* I haven't found a method that is guaranteed to work.
* For some drives, it may be necessary to compile the
* numbers into this driver and circumvent this code.
* The BIOS disk type & tables doesn't help since the
* types are inconsistent from one BIOS to the next.
*/
dp->bytes = 512; /* until we know better */
hardsetbuf(dp, 0); /* turned off during ident */
.
162c
static void hardsetbuf(Drive*, int);
static void hardinitparam(Drive*);
.
42a
Cinitparam= 0x91,
.
## diffname pc/devhard.c 1992/0903
## diff -e /n/bootesdump/1992/0902/sys/src/9/pc/devhard.c /n/bootesdump/1992/0903/sys/src/9/pc/devhard.c
709a
/*
* probe the given sector to see if it exists
*/
static int
hardprobe(Drive *dp, int cyl, int sec, int head)
{
Controller *cp;
char *buf;
int rv;
cp = dp->cp;
buf = smalloc(Maxxfer);
qlock(cp);
if(waserror()){
qunlock(cp);
nexterror();
}
cmdreadywait(cp);
cp->cmd = Cread;
cp->dp = dp;
cp->status = 0;
cp->nsecs = 1;
outb(cp->pbase+Pcount, 1);
outb(cp->pbase+Psector, sec+1);
outb(cp->pbase+Pdh, 0x20 | head);
outb(cp->pbase+Pcyllsb, cyl);
outb(cp->pbase+Pcylmsb, cyl>>8);
outb(cp->pbase+Pcmd, Cread);
sleep(&cp->r, cmddone, cp);
if(cp->status & Serr)
rv = -1;
else
rv = 0;
cp->buf = 0;
free(buf);
poperror();
qunlock(cp);
return rv;
}
/*
* figure out the drive parameters
*/
static void
hardparams(Drive *dp)
{
int i, hi, lo;
/*
* first try the easy way, ask the drive and make sure it
* isn't lying.
*/
dp->bytes = 512;
hardident(dp);
if(hardprobe(dp, dp->cyl-1, dp->sectors-1, dp->heads-1) == 0)
return;
/*
* the drive lied, determine parameters by seeing which ones
* work to read sectors.
*/
for(i = 0; i < 32; i++)
if(hardprobe(dp, 0, 0, i) < 0)
break;
dp->heads = i;
for(i = 0; i < 128; i++)
if(hardprobe(dp, 0, i, 0) < 0)
break;
dp->sectors = i;
for(i = 512; ; i += 512)
if(hardprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
break;
lo = i - 512;
hi = i;
for(; hi-lo > 1;){
i = lo + (hi - lo)/2;
if(hardprobe(dp, i, dp->sectors-1, dp->heads-1) < 0)
hi = i;
else
lo = i;
}
dp->cyl = lo + 1;
dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
}
.
702a
dp->cyl = ip->lcyls;
dp->heads = ip->lheads;
dp->sectors = ip->ls2t;
dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors;
.
693c
ip = (Ident*)buf;
.
669a
Ident *ip;
.
639,661d
637c
ushort magic; /* drive type magic */
ushort lcyls; /* logical number of cylinders */
ushort rcyl; /* number of removable cylinders */
ushort lheads; /* logical number of heads */
ushort b2t; /* unformatted bytes/track */
ushort b2s; /* unformated bytes/sector */
ushort ls2t; /* logical sectors/track */
ushort gap; /* bytes in inter-sector gaps */
ushort sync; /* bytes in sync fields */
ushort magic2; /* must be 0x0000 */
ushort serial[10]; /* serial number */
ushort type; /* controller type (0x0003) */
ushort bsize; /* buffer size/512 */
ushort ecc; /* ecc bytes returned by read long */
ushort firm[4]; /* firmware revision */
ushort model[20]; /* model number */
ushort s2i; /* number of sectors/interrupt */
ushort dwtf; /* double word transfer flag */
ushort alernate;
ushort piomode;
ushort dmamode;
ushort reserved[76];
ushort ncyls; /* native number of cylinders */
ushort nheads; /* native number of heads, sectors */
ushort dlcyls; /* default logical number of cyinders */
ushort dlheads; /* default logical number of heads, sectors */
ushort interface;
ushort power; /* 0xFFFF if power commands supported */
ushort flags;
ushort ageprog; /* MSB = age, LSB = program */
ushort reserved2[120];
};
.
634,635c
struct Ident
.
632c
* ident sector from drive
.
299d
278,297c
hardsetbuf(dp, 1);
}
/*
* read Plan 9 partition table
*/
hardpart(dp);
poperror();
.
243,276c
if(waserror()){
dp->online = 0;
continue;
}
if(!dp->online){
hardparams(dp);
.
240d
165a
static int hardprobe(Drive*, int, int, int);
.
164c
static void hardparams(Drive*);
.
129,130d
56,93d
9c
#define DPRINT if(1)print
.
## diffname pc/devhard.c 1992/0906
## diff -e /n/bootesdump/1992/0903/sys/src/9/pc/devhard.c /n/bootesdump/1992/0906/sys/src/9/pc/devhard.c
834c
if(n && strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0){
.
## diffname pc/devhard.c 1992/1001
## diff -e /n/bootesdump/1992/0906/sys/src/9/pc/devhard.c /n/bootesdump/1992/1001/sys/src/9/pc/devhard.c
934a
if(cp->sofar > cp->nsecs)
print("hardintr %d %d\n", cp->sofar, cp->nsecs);
.
666a
cp->sofar = 0;
.
656a
free(buf);
.
614a
splx(s);
.
607a
s = splhi();
.
596a
int s;
.
516c
return len;
.
512a
len = cp->sofar*dp->bytes;
.
502a
poperror();
if(loop)
nexterror();
.
501a
/*
* wait for command to complete. if we get a note,
* remember it but keep waiting to let the disk finish
* the current command.
*/
loop = 0;
while(waserror()){
DPRINT("interrupted hardxfer\n");
if(loop++ > 10){
print("hard disk error\n");
nexterror();
}
}
.
500a
splx(s);
.
493d
486,487c
outb(cp->pbase+Pcount, cp->nsecs);
.
482a
s = splhi();
cp->sofar = 0;
cp->buf = buf;
cp->nsecs = len;
.
481c
* splhi to make command atomic
.
471,477d
463,464d
458,460d
453a
if(lblk+len > pp->end)
len = pp->end - lblk;
.
433c
int loop, s;
.
404c
if(TK2MS(m->ticks - start) > 5){
.
332a
if(a&KZERO)print("wr k 0x%lux d 0x%lux\n", a, n);
.
328a
print("hard write error\n");
.
291a
if(a&KZERO)print("rd k 0x%lux d 0x%lux\n", a, n);
.
287a
print("hard read error\n");
.
170c
hardc = xalloc(((conf.nhard+1)/2) * sizeof(Controller));
.
48c
Maxxfer= BY2PG, /* maximum transfer size/cmd */
.
## diffname pc/devhard.c 1992/1002
## diff -e /n/bootesdump/1992/1001/sys/src/9/pc/devhard.c /n/bootesdump/1992/1002/sys/src/9/pc/devhard.c
379c
hardxfer(dp, pp, Cwrite, offset+rv, dp->bytes, buf);
.
377c
hardxfer(dp, pp, Cread, offset+rv, dp->bytes, buf);
.
366c
i = hardxfer(dp, pp, Cwrite, offset+rv, i, buf);
.
352c
hardxfer(dp, pp, Cwrite, offset-partial, dp->bytes, buf);
.
346c
hardxfer(dp, pp, Cread, offset-partial, dp->bytes, buf);
.
344c
partial = offset % dp->bytes;
.
337,338d
332d
317c
hardwrite(Chan *c, void *a, long n, ulong offset)
.
300c
i = hardxfer(dp, pp, Cread, offset+rv-skip, n-rv+skip, buf);
.
298c
skip = offset % dp->bytes;
.
293,294d
288d
274c
hardread(Chan *c, void *a, long n, ulong offset)
.
8a
#include "devtab.h"
.
## diffname pc/devhard.c 1992/1103
## diff -e /n/bootesdump/1992/1002/sys/src/9/pc/devhard.c /n/bootesdump/1992/1103/sys/src/9/pc/devhard.c
688c
outb(cp->pbase+Pdh, 0x20 | head | (dp->drive<<4));
.
484c
outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4) | head);
.
460c
head = ((lblk/dp->sectors) % dp->heads);
.
173a
/*
* read nvram for number of hard drives (2 max)
*/
equip = nvramread(0x12);
if(conf.nhard > 0 && (equip>>4) == 0)
conf.nhard = 0;
if(conf.nhard > 1 && (equip&0xf) == 0)
conf.nhard = 1;
.
169a
uchar equip;
.
## diffname pc/devhard.c 1992/1104
## diff -e /n/bootesdump/1992/1103/sys/src/9/pc/devhard.c /n/bootesdump/1992/1104/sys/src/9/pc/devhard.c
985c
print("weird disk interrupt, cmd=%.2ux, status=%.2ux\n",
.
## diffname pc/devhard.c 1992/1119
## diff -e /n/bootesdump/1992/1104/sys/src/9/pc/devhard.c /n/bootesdump/1992/1119/sys/src/9/pc/devhard.c
985,986c
print("weird disk interrupt, cmd=%.2ux, lastcmd= %.2ux status=%.2ux\n",
cp->cmd, cp->lastcmd, cp->status);
.
661a
cp->lastcmd = cp->cmd;
.
566c
dp-hard, cp->status, cp->error);/**/
.
564c
/* if(cp->status & Serr)
.
228a
qunlock(dp);
.
218a
qlock(dp);
.
216a
qunlock(dp);
.
79a
QLock;
.
## diffname pc/devhard.c 1993/0114
## diff -e /n/bootesdump/1992/1119/sys/src/9/pc/devhard.c /n/bootesdump/1993/0114/sys/src/9/pc/devhard.c
236c
return devattach('H', spec);
.
## diffname pc/devhard.c 1993/0915
## diff -e /n/bootesdump/1993/0114/sys/src/9/pc/devhard.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/devhard.c
961a
}
loop = 0;
while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
if(++loop > 10000) {
DPRINT("cmd=%lux status=%lux\n",
cp->cmd, inb(cp->pbase+Pstatus));
panic("hardintr: read/ident");
.
949,955d
867d
862a
n = getfields(buf, line, Npart+1, '\n');
if(n == 0 || strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1)){
dp->p[0].end--;
dp->p[1].start--;
dp->p[1].end--;
hardxfer(dp, pp, Cread, 0, dp->bytes, buf);
buf[dp->bytes-1] = 0;
n = getfields(buf, line, Npart+1, '\n');
}
.
859c
* read last sector from disk, null terminate. This used
* to be the sector we used for 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 first look to see if there is a valid partition
* table in the last sector. If so, we use it. Otherwise
* we switch to the second last.
.
510a
if(stat & Serr)
error(Eio);
.
509c
} else
stat = 0;
.
505c
while((stat = inb(cp->pbase+Pstatus) & (Serr|Sdrq)) == 0)
.
450c
int loop, s, stat;
.
158c
devdir(c, qid, name, l, eve, 0660, dirp);
.
## diffname pc/devhard.c 1993/1124
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/devhard.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/devhard.c
923c
* distinguish which interrupted (use arg).
.
919c
USED(ur, arg);
.
912c
hardintr(Ureg *ur, void *arg)
.
197c
setvec(Hardvec + (cp-hardc)*8, hardintr, 0); /* BUG!! guessing */
.
124c
static void hardintr(Ureg*, void*);
.
## diffname pc/devhard.c 1994/0128
## diff -e /n/fornaxdump/1993/1124/sys/src/brazil/pc/devhard.c /n/fornaxdump/1994/0128/sys/src/brazil/pc/devhard.c
1011a
}
}
void
hardclock(void)
{
int drive;
Drive *dp;
Controller *cp;
int diff;
if(spindowntime <= 0)
return;
for(drive = 0; drive < conf.nhard; drive++){
dp = &hard[drive];
cp = dp->cp;
if(canqlock(cp) == 0)
continue;
diff = TK2SEC(m->ticks - dp->usetime);
switch(dp->state){
case Sspinning:
if(diff >= spindowntime){
cp->cmd = Cstandby;
outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4) | 0);
outb(cp->pbase+Pcmd, cp->cmd);
dp->state = Sstandby;
}
break;
}
qunlock(dp->cp);
.
528a
dp->state = Sspinning;
dp->usetime = m->ticks;
.
421c
if(TK2MS(m->ticks - start) > 10){
.
176a
p = getconf("spindowntime");
if(p)
spindowntime = atoi(p);
.
172a
char *p;
.
122a
static int spindowntime;
.
96a
enum
{
Sspinning,
Sstandby,
Sidle,
Spowerdown,
};
.
88a
ulong usetime;
int state;
.
46a
/* conner specific commands */
Cstandby= 0xE0,
Cidle= 0xE1,
Cpowerdown= 0xE3,
.
## diffname pc/devhard.c 1994/0205
## diff -e /n/fornaxdump/1994/0128/sys/src/brazil/pc/devhard.c /n/fornaxdump/1994/0205/sys/src/brazil/pc/devhard.c
1059a
outb(cp->pbase+Pcount, 0);
.
104,111d
51a
/* disk states */
Sspinning,
Sstandby,
Sidle,
Spowerdown,
.
48c
Cstandby= 0xE2,
.
## diffname pc/devhard.c 1994/0222
## diff -e /n/fornaxdump/1994/0205/sys/src/brazil/pc/devhard.c /n/fornaxdump/1994/0222/sys/src/brazil/pc/devhard.c
910,919c
switch(getfields(line[i], field, 3, ' ')) {
case 2:
if(strcmp(field[0], "unit") == 0)
strncpy(dp->vol, field[1], NAMELEN);
break;
case 3:
strncpy(pp->name, field[0], NAMELEN);
if(strncmp(pp->name, "repl", NAMELEN) == 0)
dp->repl.p = pp;
pp->start = strtoul(field[1], 0, 0);
pp->end = strtoul(field[2], 0, 0);
if(pp->start > pp->end || pp->start >= dp->p[0].end)
break;
dp->npart++;
}
.
856a
sprint(dp->vol, "hd%d", dp - hard);
.
168c
sprint(name, "%s%s", dp->vol, pp->name);
.
101a
char vol[NAMELEN];
.
## diffname pc/devhard.c 1994/0413
## diff -e /n/fornaxdump/1994/0222/sys/src/brazil/pc/devhard.c /n/fornaxdump/1994/0413/sys/src/brazil/pc/devhard.c
1002,1008d
995a
loop = 0;
while((cp->status & (Serr|Sdrq)) == 0){
if(++loop > 10000) {
DPRINT("cmd=%lux status=%lux\n",
cp->cmd, inb(cp->pbase+Pstatus));
panic("hardintr: read/ident");
}
cp->status = inb(cp->pbase+Pstatus);
}
.
## diffname pc/devhard.c 1994/0428
## diff -e /n/fornaxdump/1994/0413/sys/src/brazil/pc/devhard.c /n/fornaxdump/1994/0428/sys/src/brazil/pc/devhard.c
719c
cmdreadywait(dp);
.
659c
cmdreadywait(dp);
.
585c
cmdreadywait(dp);
.
505c
cmdreadywait(dp);
.
441c
if(TK2MS(m->ticks - start) > period){
.
438a
/* give it 2 seconds to spin down and up */
if(dp->state == Sspinning)
period = 10;
else
period = 2000;
.
437a
int period;
Controller *cp = dp->cp;
.
435c
cmdreadywait(Drive *dp)
.
## diffname pc/devhard.c 1994/0505
## diff -e /n/fornaxdump/1994/0428/sys/src/brazil/pc/devhard.c /n/fornaxdump/1994/0505/sys/src/brazil/pc/devhard.c
1038a
case Cidle:
case Cstandby:
case Cpowerdown:
.
## diffname pc/devhard.c 1994/0913
## diff -e /n/fornaxdump/1994/0505/sys/src/brazil/pc/devhard.c /n/fornaxdump/1994/0913/sys/src/brazil/pc/devhard.c
293c
Drive *d;
Partition *p;
if(c->mode != OWRITE && c->mode != ORDWR)
return;
d = &hard[DRIVE(c->qid.path)];
p = &d->p[PART(c->qid.path)];
if(strcmp(p->name, "partition") != 0)
return;
if(waserror()){
qunlock(d);
nexterror();
}
qlock(d);
hardpart(d);
qunlock(d);
poperror();
.
## diffname pc/devhard.c 1995/0107
## diff -e /n/fornaxdump/1994/0913/sys/src/brazil/pc/devhard.c /n/fornaxdump/1995/0107/sys/src/brazil/pc/devhard.c
1104d
1093,1102c
if((dp->state == Sspinning) && (diff >= spindowntime)){
ilock(cp);
cp->cmd = Cstandby;
outb(cp->pbase+Pcount, 0);
outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4) | 0);
outb(cp->pbase+Pcmd, cp->cmd);
iunlock(cp);
dp->state = Sstandby;
.
1089,1090d
1072a
iunlock(cp);
.
1036c
break;
.
998c
break;
.
990a
.
982a
ilock(cp);
.
758a
iunlock(cp);
.
746a
ilock(cp);
.
695c
iunlock(cp);
.
687c
ilock(cp);
.
675d
616a
iunlock(cp);
.
612a
ilock(cp);
.
557c
iunlock(cp);
.
548a
.
542a
.
536c
dp->usetime = m->ticks;
cmdreadywait(dp);
ilock(cp);
.
534c
* Make sure hardclock() doesn't
* interfere.
.
531,532d
496c
int loop, stat;
.
450c
* Wait for the controller to be ready to accept a command.
* This is protected from intereference by hardclock() by
* setting dp->usetime before it is called.
.
243a
/*
* Make sure hardclock() doesn't
* interfere.
*/
dp->usetime = m->ticks;
.
219a
if(conf.nhard && (p = getconf("spindowntime")))
spindowntime = atoi(p);
.
193,196d
117a
Lock; /* exclusive access to the registers */
.
116c
QLock; /* exclusive access to the controller */
.
## diffname pc/devhard.c 1995/0108
## diff -e /n/fornaxdump/1995/0107/sys/src/brazil/pc/devhard.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devhard.c
441a
}
long
hardbwrite(Chan *c, Block *bp, ulong offset)
{
return devbwrite(c, bp, offset);
.
373a
Block*
hardbread(Chan *c, long n, ulong offset)
{
return devbread(c, n, offset);
}
.
## diffname pc/devhard.c 1995/0117
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devhard.c /n/fornaxdump/1995/0117/sys/src/brazil/pc/devhard.c
967c
switch(getfields(line[i], field, 3, " ")) {
.
958c
n = getfields(buf, line, Npart+1, "\n");
.
951c
n = getfields(buf, line, Npart+1, "\n");
.
888c
if(getfields(line[i], field, 1, " ") != 1)
.
883c
n = getfields(buf, line, Nrepl+1, "\n");
.
## diffname pc/devhard.c 1995/0726
## diff -e /n/fornaxdump/1995/0117/sys/src/brazil/pc/devhard.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devhard.c
292d
290c
hardcreate(Chan*, char*, int, ulong)
.
## diffname pc/devhard.c 1995/0912 # deleted
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devhard.c /n/fornaxdump/1995/0912/sys/src/brazil/pc/devhard.c
1,1133d
|