henesyinit from p9f47575dc5 years agoHistory
995 lines · 18.5 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"../port/error.h" #include	"devtab.h" #define DPRINT if(1)print typedef	struct Drive		Drive;typedef	struct Ident		Ident;typedef	struct Controller	Controller;typedef struct Partition	Partition;typedef struct Repl		Repl; enum{	/* ports */	Pbase=		0x1F0,	Pdata=		0,	/* data port (16 bits) */	Perror=		1,	/* error port (read) */	Pprecomp=	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) */	 Sbusy=		 (1<<7),	 Sready=	 (1<<6),	 Sdrq=		 (1<<3),	 Serr=		 (1<<0),	Pcmd=		7,	/* cmd port (write) */ 	/* commands */	Crecal=		0x10,	Cread=		0x20,	Cwrite=		0x30,	Cident=		0xEC,	Cident2=	0xFF,	/* pseudo command for post Cident interrupt */	Csetbuf=	0xEF,	Cinitparam=	0x91, 	/* file types */	Qdir=		0, 	Maxxfer=	BY2PG,		/* maximum transfer size/cmd */	Npart=		8+2,		/* 8 sub partitions, disk, and partition */	Nrepl=		64,		/* maximum replacement blocks */};#define PART(x)		((x)&0xF)#define DRIVE(x)	(((x)>>4)&0x7)#define MKQID(d,p)	(((d)<<4) | (p)) struct Partition{	ulong	start;	ulong	end;	char	name[NAMELEN+1];}; struct Repl{	Partition *p;	int	nrepl;	ulong	blk[Nrepl];}; #define PARTMAGIC	"plan9 partitions"#define REPLMAGIC	"block replacements" /* *  a hard drive */struct Drive{	QLock; 	Controller *cp;	int	drive;	int	confused;	/* needs to be recalibrated (or worse) */	int	online;	int	npart;		/* number of real partitions */	Partition p[Npart];	Repl	repl; 	ulong	cap;		/* total bytes */	int	bytes;		/* bytes/sector */	int	sectors;	/* sectors/track */	int	heads;		/* heads/cyl */	long	cyl;		/* cylinders/drive */}; /* *  a controller for 2 drives */struct Controller{	QLock;			/* exclusive access to the drive */ 	int	confused;	/* needs to be recalibrated (or worse) */	int	pbase;		/* base port */ 	/*	 *  current operation	 */	int	cmd;		/* current command */	int	lastcmd;	/* debugging info */	Rendez	r;		/* wait here for command termination */	char	*buf;		/* xfer buffer */	int	nsecs;		/* length of transfer (sectors) */	int	sofar;		/* sectors transferred so far */	int	status;	int	error;	Drive	*dp;		/* drive being accessed */}; Controller	*hardc;Drive		*hard; static void	hardintr(Ureg*);static long	hardxfer(Drive*, Partition*, int, long, long, char*);static void	hardident(Drive*);static void	hardsetbuf(Drive*, int);static void	hardparams(Drive*);static void	hardpart(Drive*);static int	hardprobe(Drive*, int, int, int); static inthardgen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp){	Qid qid;	int drive;	char name[NAMELEN+4];	Drive *dp;	Partition *pp;	ulong l; 	USED(tab, ntab);	qid.vers = 0;	drive = s/Npart;	s = s % Npart;	if(drive >= conf.nhard)		return -1;	dp = &hard[drive]; 	if(s >= dp->npart)		return 0; 	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;	devdir(c, qid, name, l, eve, 0666, dirp);	return 1;} /* *  we assume drives 0 and 1 are on the first controller, 2 and 3 on the *  second, etc. */voidhardreset(void){	Drive *dp;	Controller *cp;	int drive;	uchar equip; 	hard = xalloc(conf.nhard * sizeof(Drive));	hardc = xalloc(((conf.nhard+1)/2) * sizeof(Controller));		/*	 *  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; 	for(drive = 0; drive < conf.nhard; drive++){		dp = &hard[drive];		cp = &hardc[drive/2];		dp->drive = drive&1;		dp->online = 0;		dp->cp = cp;		if((drive&1) == 0){			cp->buf = 0;			cp->lastcmd = cp->cmd;			cp->cmd = 0;			cp->pbase = Pbase + (cp-hardc)*8;	/* BUG!! guessing */			setvec(Hardvec + (cp-hardc)*8, hardintr); /* BUG!! guessing */		}	}} voidhardinit(void){} /* *  Get the characteristics of each drive.  Mark unresponsive ones *  off line. */Chan*hardattach(char *spec){	Drive *dp; 	for(dp = hard; dp < &hard[conf.nhard]; dp++){		if(waserror()){			dp->online = 0;			qunlock(dp);			continue;		}		qlock(dp);		if(!dp->online){			hardparams(dp);			dp->online = 1;			hardsetbuf(dp, 1);		} 		/*		 *  read Plan 9 partition table		 */		hardpart(dp);		qunlock(dp);		poperror();	}	return devattach('w', spec);} Chan*hardclone(Chan *c, Chan *nc){	return devclone(c, nc);} inthardwalk(Chan *c, char *name){	return devwalk(c, name, 0, 0, hardgen);} voidhardstat(Chan *c, char *dp){	devstat(c, dp, 0, 0, hardgen);} Chan*hardopen(Chan *c, int omode){	return devopen(c, omode, 0, 0, hardgen);} voidhardcreate(Chan *c, char *name, int omode, ulong perm){	USED(c, name, omode, perm);	error(Eperm);} voidhardclose(Chan *c){	USED(c);} voidhardremove(Chan *c){	USED(c);	error(Eperm);} voidhardwstat(Chan *c, char *dp){	USED(c, dp);	error(Eperm);} longhardread(Chan *c, void *a, long n, ulong offset){	Drive *dp;	long rv, i;	int skip;	uchar *aa = a;	Partition *pp;	char *buf; 	if(c->qid.path == CHDIR)		return devdirread(c, a, n, 0, 0, hardgen); 	buf = smalloc(Maxxfer);	if(waserror()){		free(buf);		nexterror();	} 	dp = &hard[DRIVE(c->qid.path)];	pp = &dp->p[PART(c->qid.path)]; 	skip = offset % dp->bytes;	for(rv = 0; rv < n; rv += i){		i = hardxfer(dp, pp, Cread, offset+rv-skip, n-rv+skip, buf);		if(i == 0)			break;		i -= skip;		if(i > n - rv)			i = n - rv;		memmove(aa+rv, buf + skip, i);		skip = 0;	} 	free(buf);	poperror(); 	return rv;} longhardwrite(Chan *c, void *a, long n, ulong offset){	Drive *dp;	long rv, i, partial;	uchar *aa = a;	Partition *pp;	char *buf; 	if(c->qid.path == CHDIR)		error(Eisdir); 	dp = &hard[DRIVE(c->qid.path)];	pp = &dp->p[PART(c->qid.path)];	buf = smalloc(Maxxfer);	if(waserror()){		free(buf);		nexterror();	} 	/*	 *  if not starting on a sector boundary,	 *  read in the first sector before writing	 *  it out.	 */	partial = offset % dp->bytes;	if(partial){		hardxfer(dp, pp, Cread, offset-partial, dp->bytes, buf);		if(partial+n > dp->bytes)			rv = dp->bytes - partial;		else			rv = n;		memmove(buf+partial, aa, rv);		hardxfer(dp, pp, Cwrite, offset-partial, dp->bytes, buf);	} else		rv = 0; 	/*	 *  write out the full sectors	 */	partial = (n - rv) % dp->bytes;	n -= partial;	for(; rv < n; rv += i){		i = n - rv;		if(i > Maxxfer)			i = Maxxfer;		memmove(buf, aa+rv, i);		i = hardxfer(dp, pp, Cwrite, offset+rv, i, buf);		if(i == 0)			break;	} 	/*	 *  if not ending on a sector boundary,	 *  read in the last sector before writing	 *  it out.	 */	if(partial){		hardxfer(dp, pp, Cread, offset+rv, dp->bytes, buf);		memmove(buf, aa+rv, partial);		hardxfer(dp, pp, Cwrite, offset+rv, dp->bytes, buf);		rv += partial;	} 	free(buf);	poperror(); 	return rv;} /* *  did an interrupt happen? */static intcmddone(void *a){	Controller *cp = a; 	return cp->cmd == 0;} /* *  wait for the controller to be ready to accept a command */static voidcmdreadywait(Controller *cp){	long start; 	start = m->ticks;	while((inb(cp->pbase+Pstatus) & (Sready|Sbusy)) != Sready)		if(TK2MS(m->ticks - start) > 5){			DPRINT("cmdreadywait failed\n");			error(Eio);		}} static voidhardrepl(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)			DPRINT("found bblk %ld at offset %ld\n", bblk, i);	}} /* *  transfer a number of sectors.  hardintr will perform all the iterative *  parts. */static longhardxfer(Drive *dp, Partition *pp, int cmd, long start, long len, char *buf){	Controller *cp;	long lblk;	int cyl, sec, head;	int loop, s; 	if(dp->online == 0)		error(Eio); 	/*	 *  cut transfer size down to disk buffer size	 */	start = start / dp->bytes;	if(len > Maxxfer)		len = Maxxfer;	len = (len + dp->bytes - 1) / dp->bytes;	if(len == 0)		return 0; 	/*	 *  calculate physical address	 */	lblk = start + pp->start;	if(lblk >= pp->end)		return 0;	if(lblk+len > pp->end)		len = pp->end - lblk;	cyl = lblk/(dp->sectors*dp->heads);	sec = (lblk % dp->sectors) + 1;	head =  ((lblk/dp->sectors) % dp->heads); 	cp = dp->cp;	qlock(cp);	if(waserror()){		cp->buf = 0;		qunlock(cp);		nexterror();	} 	cmdreadywait(cp); 	/*	 *  splhi to make command atomic	 */	s = splhi();	cp->sofar = 0;	cp->buf = buf;	cp->nsecs = len;	cp->cmd = cmd;	cp->dp = dp;	cp->status = 0;	outb(cp->pbase+Pcount, cp->nsecs);	outb(cp->pbase+Psector, sec);	outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4) | head);	outb(cp->pbase+Pcyllsb, cyl);

Lines 1–500 of 995.