plan 9 kernel history: overview | file list | diff list

1991/0925/pc/devfloppy.c (diff list | history)

1991/0924/sys/src/9/pc/devfloppy.c:39,451991/0925/sys/src/9/pc/devfloppy.c:39,46 (short | long | prev | next)
1991/0924    
	Fdumpreg=	0x0e,	/* dump internal registers */ 
1991/0727    
 
1991/0924    
	/* digital input register */ 
	Pdir=		0x3F7,	/* disk changed port */ 
1991/0925    
	Pdir=		0x3F7,	/* disk changed port (read only) */ 
	Pdsr=		0x3F7,	/* data rate select port (write only) */ 
1991/0924    
	Fchange=	0x80,	/* disk has changed */ 
1991/0831    
 
1991/0727    
	/* status 0 byte */ 
1991/0924/sys/src/9/pc/devfloppy.c:114,1211991/0925/sys/src/9/pc/devfloppy.c:115,120
1991/0727    
 */ 
struct Drive 
{ 
1991/0731    
	QLock;			/* exclusive access to the drive */ 
                 
1991/0727    
	Type	*t; 
	int	dev; 
 
1991/0924/sys/src/9/pc/devfloppy.c:122,1271991/0925/sys/src/9/pc/devfloppy.c:121,127
1991/0727    
	ulong	lasttouched;	/* time last touched */ 
	int	cyl;		/* current cylinder */ 
1991/0924    
	int	confused;	/* needs to be recalibrated */ 
1991/0925    
	int	vers; 
1991/0727    
 
	int	tcyl;		/* target cylinder */ 
	int	thead;		/* target head */ 
1991/0924/sys/src/9/pc/devfloppy.c:143,1481991/0925/sys/src/9/pc/devfloppy.c:143,149
1991/0731    
	QLock;			/* exclusive access to the contoller */ 
 
1991/0809    
	Drive	*d;		/* the floppy drives */ 
1991/0925    
	Drive	*selected; 
1991/0924    
	uchar	cmd[14];	/* command */ 
	int	ncmd;		  /* # command bytes */ 
	uchar	stat[14];	/* command status */ 
1991/0924/sys/src/9/pc/devfloppy.c:162,1671991/0925/sys/src/9/pc/devfloppy.c:163,169
1991/0731    
 */ 
1991/0924    
static int	floppycmd(void); 
static void	floppyeject(Drive*); 
1991/0925    
static void	floppyintr(Ureg*); 
1991/0731    
static void	floppykproc(void*); 
1991/0924    
static void	floppyon(Drive*); 
static void	floppyoff(Drive*); 
1991/0924/sys/src/9/pc/devfloppy.c:210,2151991/0925/sys/src/9/pc/devfloppy.c:212,218
1991/0809    
	 *  allocate the drive storage 
	 */ 
1991/0924    
	fl.d = ialloc(conf.nfloppy*sizeof(Drive), 0); 
1991/0925    
	fl.selected = fl.d; 
1991/0809    
 
	/* 
1991/0802    
	 *  stop the motors 
1991/0924/sys/src/9/pc/devfloppy.c:229,2341991/0925/sys/src/9/pc/devfloppy.c:232,238
1991/0802    
		dp->cyl = -1;		/* because we don't know */ 
1991/0924    
		dp->cache = (uchar*)ialloc(dp->t->tsize, 1); 
		dp->ccyl = -1; 
1991/0925    
		dp->vers = 1; 
1991/0731    
	} 
1991/0809    
 
	/* 
1991/0924/sys/src/9/pc/devfloppy.c:235,2401991/0925/sys/src/9/pc/devfloppy.c:239,245
1991/0924    
	 *  first operation will recalibrate 
1991/0809    
	 */ 
1991/0924    
	fl.confused = 1; 
1991/0925    
	setvec(Floppyvec, floppyintr); 
1991/0731    
} 
 
void 
1991/0924/sys/src/9/pc/devfloppy.c:278,2841991/0925/sys/src/9/pc/devfloppy.c:283,289
1991/0802    
Chan* 
floppyopen(Chan *c, int omode) 
{ 
1991/0811    
	return devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen); 
1991/0925    
	devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen); 
1991/0802    
} 
 
void 
1991/0924/sys/src/9/pc/devfloppy.c:304,3091991/0925/sys/src/9/pc/devfloppy.c:309,348
1991/0802    
	error(Eperm); 
} 
 
1991/0925    
static void 
islegal(Chan *c, long n, Drive *dp) 
{ 
	if(c->offset % dp->t->bytes) 
		errors("bad offset"); 
	if(n % dp->t->bytes) 
		errors("bad len"); 
} 
 
/* 
 *  check if the floppy has been replaced under foot 
 * 
 *  a seek and a read clears the condition.  this was determined experimentally, 
 *  there has to be a better way. 
 */ 
static void 
changed(Chan *c, Drive *dp) 
{ 
	ulong old; 
 
	if(inb(Pdir)&Fchange) 
		dp->vers++; 
	old = c->qid.vers; 
	c->qid.vers = dp->vers; 
	if(old && old!=dp->vers){ 
		dp->ccyl = -1; 
		if(dp->cyl) 
			floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize); 
		else 
			floppyxfer(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize, dp->t->tsize); 
		errors("disk changed"); 
	} 
} 
 
1991/0731    
long 
floppyread(Chan *c, void *a, long n) 
{ 
1991/0924/sys/src/9/pc/devfloppy.c:319,3331991/0925/sys/src/9/pc/devfloppy.c:358,376
1991/0802    
 
	rv = 0; 
1991/0924    
	dp = &fl.d[c->qid.path & ~Qmask]; 
                 
1991/0802    
	switch ((int)(c->qid.path & Qmask)) { 
	case Qdata: 
1991/0809    
		if(c->offset % dp->t->bytes) 
			errors("bad offset"); 
		if(n % dp->t->bytes) 
			errors("bad len"); 
1991/0925    
		islegal(c, n, dp); 
1991/0924    
		aa = a; 
		nn = dp->t->tsize; 
1991/0925    
 
		qlock(&fl); 
		if(waserror()){ 
			qunlock(&fl); 
			nexterror(); 
		} 
		floppyon(dp); 
		changed(c, dp); 
1991/0809    
		for(rv = 0; rv < n; rv += len){ 
			/* 
1991/0924    
			 *  truncate xfer at track boundary 
1991/0924/sys/src/9/pc/devfloppy.c:356,3611991/0925/sys/src/9/pc/devfloppy.c:399,407
1991/0809    
			} 
1991/0924    
			memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len); 
1991/0802    
		} 
1991/0925    
		qunlock(&fl); 
		poperror(); 
 
1991/0802    
		break; 
1991/0924    
	case Qctl: 
		break; 
1991/0924/sys/src/9/pc/devfloppy.c:377,3891991/0925/sys/src/9/pc/devfloppy.c:423,438
1991/0731    
 
1991/0802    
	rv = 0; 
1991/0924    
	dp = &fl.d[c->qid.path & ~Qmask]; 
                 
1991/0802    
	switch ((int)(c->qid.path & Qmask)) { 
	case Qdata: 
1991/0924    
		if(c->offset % dp->t->bytes) 
			errors("bad offset"); 
		if(n % dp->t->bytes) 
			errors("bad len"); 
1991/0925    
		islegal(c, n, dp); 
		qlock(&fl); 
		if(waserror()){ 
			qunlock(&fl); 
			nexterror(); 
		} 
		floppyon(dp); 
		changed(c, dp); 
1991/0802    
		for(rv = 0; rv < n; rv += i){ 
1991/0924    
			floppypos(dp, c->offset+rv); 
			if(dp->tcyl == dp->ccyl) 
1991/0924/sys/src/9/pc/devfloppy.c:393,4141991/0925/sys/src/9/pc/devfloppy.c:442,459
1991/0802    
			if(i <= 0) 
				break; 
		} 
1991/0925    
		qunlock(&fl); 
		poperror(); 
1991/0802    
		break; 
1991/0924    
	case Qctl: 
1991/0925    
		qlock(&fl); 
1991/0924    
		if(SNCMP(aa, "eject") == 0){ 
			floppyeject(dp); 
		} else if(SNCMP(aa, "seek") == 0){ 
			aa += 5; 
			floppyseek(dp, strtoul(aa, 0, 0)); 
		} else if(SNCMP(aa, "den") == 0){ 
			aa += 4; 
			i = strtoul(aa, 0, 0); 
			USED(i); 
/*			devp->dsr = i; 
			devp->ccr = i;/**/ 
		} else if(SNCMP(aa, "reset") == 0){ 
1991/0925    
			fl.confused = 1; 
1991/0924    
			floppyon(dp); 
		} 
1991/0925    
		qunlock(&fl); 
1991/0924    
		break; 
1991/0802    
	default: 
		panic("floppywrite: bad qid"); 
1991/0924/sys/src/9/pc/devfloppy.c:421,4461991/0925/sys/src/9/pc/devfloppy.c:466,485
1991/0731    
floppykproc(void *a) 
1991/0727    
{ 
	Drive *dp; 
1991/0924    
int i; 
static int last; 
1991/0727    
 
1991/0919    
	while(waserror()) 
		; 
1991/0802    
	for(;;){ 
1991/0924    
i = inb(Pdir) & 0x80; 
if(i != last) 
	print("fromn %d to %d\n", last, i); 
last = i; 
		for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){ 
			if((fl.motor&MOTORBIT(dp->dev)) 
1991/0921    
			&& TK2SEC(m->ticks - dp->lasttouched) > 5 
1991/0802    
			&& canqlock(dp)){ 
1991/0925    
			&& canqlock(&fl)){ 
1991/0802    
				if(TK2SEC(m->ticks - dp->lasttouched) > 5) 
1991/0924    
					floppyoff(dp); 
1991/0802    
				qunlock(dp); 
1991/0925    
				qunlock(&fl); 
1991/0802    
			} 
1991/0728    
		} 
1991/0924    
		tsleep(&fl.kr, return0, 0, 5*100); 
1991/0925    
		tsleep(&fl.kr, return0, 0, 1000); 
1991/0727    
	} 
} 
 
1991/0924/sys/src/9/pc/devfloppy.c:469,4741991/0925/sys/src/9/pc/devfloppy.c:508,514
1991/0924    
			if(floppyrecal(dp) >= 0) 
				break; 
1991/0921    
	dp->lasttouched = m->ticks; 
1991/0925    
	fl.selected = dp; 
1991/0921    
} 
 
/* 
1991/0924/sys/src/9/pc/devfloppy.c:479,4841991/0925/sys/src/9/pc/devfloppy.c:519,525
1991/0921    
{ 
1991/0924    
	fl.motor &= ~MOTORBIT(dp->dev); 
	outb(Pdor, fl.motor | Fintena | Fena | dp->dev); 
1991/0925    
	fl.selected = dp; 
1991/0921    
} 
 
/* 
1991/0924/sys/src/9/pc/devfloppy.c:488,4931991/0925/sys/src/9/pc/devfloppy.c:529,535
1991/0924    
floppyeject(Drive *dp) 
1991/0727    
{ 
1991/0924    
	floppyon(dp); 
1991/0925    
	dp->vers++; 
1991/0924    
	floppyoff(dp); 
1991/0727    
} 
 
1991/0924/sys/src/9/pc/devfloppy.c:670,6771991/0925/sys/src/9/pc/devfloppy.c:712,718
1991/0924    
		fl.motor = 0; 
		floppywait(); 
		fl.confused = 0; 
/*		devp->dsr = 0; 
		devp->ccr = 0; /**/ 
1991/0925    
		outb(Pdsr, 0); 
1991/0727    
	} 
} 
 
1991/0924/sys/src/9/pc/devfloppy.c:683,6891991/0925/sys/src/9/pc/devfloppy.c:724,729
1991/0731    
static long 
1991/0924    
floppyseek(Drive *dp, long off) 
1991/0727    
{ 
1991/0924    
	floppyon(dp); 
	floppypos(dp, off); 
1991/0802    
	if(dp->cyl == dp->tcyl) 
		return dp->cyl; 
1991/0924/sys/src/9/pc/devfloppy.c:723,7381991/0925/sys/src/9/pc/devfloppy.c:763,768
1991/0924    
	if(off + n > dp->t->cap) 
		n = dp->t->cap - off; 
 
	qlock(&fl); 
1991/0731    
	qlock(dp); 
1991/0802    
	if(waserror()){ 
1991/0924    
		dmaend(DMAchan); 
		qunlock(&fl); 
1991/0731    
		qunlock(dp); 
1991/0924    
		fl.confused = 1; 
		nexterror(); 
1991/0731    
	} 
                 
1991/0727    
	/* 
1991/0731    
	 *  calculate new position and seek to it (dp->len may be trimmed) 
	 */ 
1991/0924/sys/src/9/pc/devfloppy.c:739,7451991/0925/sys/src/9/pc/devfloppy.c:769,775
1991/0727    
	dp->len = n; 
1991/0924    
	if(floppyseek(dp, off) < 0) 
1991/0731    
		errors("seeking floppy"); 
1991/0906    
	                 
1991/0925    
 
1991/0823    
/*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n", 
1991/0924    
	dp->tcyl, dp->thead, dp->tsec, a, dp->len);/**/ 
1991/0727    
 
1991/0924/sys/src/9/pc/devfloppy.c:751,7571991/0925/sys/src/9/pc/devfloppy.c:781,787
1991/0727    
	/* 
1991/0731    
	 *  start operation 
1991/0727    
	 */ 
1991/0924    
/*	cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);/**/ 
1991/0925    
	cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0); 
1991/0924    
	fl.ncmd = 0; 
	fl.cmd[fl.ncmd++] = cmd; 
	fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev; 
1991/0924/sys/src/9/pc/devfloppy.c:783,7961991/0925/sys/src/9/pc/devfloppy.c:813,823
1991/0731    
		errors("floppy result failed"); 
1991/0727    
	} 
1991/0924    
	if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){ 
		if(fl.stat[1] != 0x80){ 
			print("xfer failed %lux %lux %lux\n", fl.stat[0], 
				fl.stat[1], fl.stat[2]); 
			print("offset %lud len %d\n", off, dp->len); 
			dp->confused = 1; 
			errors("floppy drive lost"); 
		} else 
			fl.stat[5]++; 
1991/0925    
		print("xfer failed %lux %lux %lux\n", fl.stat[0], 
			fl.stat[1], fl.stat[2]); 
		print("offset %lud len %d\n", off, dp->len); 
		dp->confused = 1; 
		errors("floppy drive lost"); 
1991/0727    
	} 
 
1991/0924    
	/* 
1991/0924/sys/src/9/pc/devfloppy.c:801,8201991/0925/sys/src/9/pc/devfloppy.c:828,844
1991/0924    
	offset = offset * c2b[fl.stat[6]]; 
1991/0802    
	if(offset != off+dp->len){ 
1991/0924    
		print("new offset %d instead of %d\n", offset, off+dp->len); 
1991/0925    
		print("	%d %d %d\n", fl.stat[3], fl.stat[4], fl.stat[5]); 
1991/0727    
		dp->confused = 1; 
1991/0731    
		errors("floppy drive lost"); 
1991/0727    
	} 
 
1991/0802    
	dp->lasttouched = m->ticks; 
1991/0924    
	qunlock(&fl); 
1991/0731    
	qunlock(dp); 
	poperror(); 
                 
1991/0727    
	return dp->len; 
} 
 
1991/0924    
void 
floppyintr(void) 
1991/0925    
static void 
floppyintr(Ureg *ur) 
1991/0727    
{ 
1991/0924    
	switch(fl.cmd[0]&~Fmulti){ 
	case Fread: 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)