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

1992/1006/pc/devfloppy.c (diff list | history)

1992/1003/sys/src/9/pc/devfloppy.c:37,421992/1006/sys/src/9/pc/devfloppy.c:37,43 (short | long | prev | next)
1991/0924    
	Freadid=	0x4a,	/* read track id */ 
	Fspec=		0x03,	/* set hold times */ 
	Fwrite=		0x45,	/* write cmd */ 
1992/1006    
	Fformat=	0x4d,	/* format cmd */ 
1991/0924    
	Fmulti=		0x80,	/* or'd with Fread or Fwrite for multi-head */ 
	Fdumpreg=	0x0e,	/* dump internal registers */ 
1991/0727    
 
1992/1003/sys/src/9/pc/devfloppy.c:60,701992/1006/sys/src/9/pc/devfloppy.c:61,84
1991/0727    
}; 
 
/* 
1992/1006    
 *  types of drive (from PC equipment byte) 
 */ 
enum 
{ 
	Tnone=		0, 
	T360kb=		1, 
	T1200kb=	2, 
	T720kb=		3, 
	T1440kb=	4, 
}; 
 
/* 
1992/1003    
 *  floppy types (all MFM encoding) 
1991/0727    
 */ 
struct Type 
{ 
	char	*name; 
1992/1006    
	int	dt;		/* compatible drive type */ 
1991/0727    
	int	bytes;		/* bytes/sector */ 
	int	sectors;	/* sectors/track */ 
	int	heads;		/* number of heads */ 
1992/1003/sys/src/9/pc/devfloppy.c:84,951992/1006/sys/src/9/pc/devfloppy.c:98,109
1991/0727    
}; 
Type floppytype[] = 
{ 
1992/1003    
 { "3½HD",	512,	18,	2,	1,	80,	0x1B,	0x54,	0, }, 
 { "3½DD",	512,	9,	2,	1,	80,	0x1B,	0x54,	2, }, 
 { "5¼HD",	512,	15,	2,	1,	80,	0x2A,	0x50,	0, }, 
 { "5¼DD2",	512,	9,	2,	2,	40,	0x2A,	0x50,	2, }, 
 { "5¼DD1",	512,	9,	2,	2,	40,	0x2A,	0x50,	1, }, 
 { "3½ED",	1024,	18,	2,	1,	80,	0x1B,	0x54,	3, }, 
1992/1006    
 { "3½HD",	T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54,	0, }, 
 { "3½DD",	T1440kb, 512,  9, 2, 1, 80, 0x1B, 0x54, 2, }, 
 { "3½DD",	T720kb,  512,  9, 2, 1, 80, 0x1B, 0x54, 2, }, 
 { "5¼HD",	T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, }, 
 { "5¼DD",	T1200kb, 512,  9, 2, 2, 40, 0x2A, 0x50, 1, }, 
 { "5¼DD",	T360kb,  512,  9, 2, 1, 40, 0x2A, 0x50, 2, }, 
1991/0727    
}; 
1991/0731    
#define NTYPES (sizeof(floppytype)/sizeof(Type)) 
 
1992/1003/sys/src/9/pc/devfloppy.c:118,1281992/1006/sys/src/9/pc/devfloppy.c:132,143
1991/0727    
 */ 
struct Drive 
{ 
	Type	*t; 
1992/1006    
	Type	*t;		/* floppy type */ 
	int	dt;		/* drive type */ 
1991/0727    
	int	dev; 
 
	ulong	lasttouched;	/* time last touched */ 
1992/1003    
	int	arm;		/* current arm position */ 
1992/1006    
	int	cyl;		/* current arm position */ 
1991/0924    
	int	confused;	/* needs to be recalibrated */ 
1991/0925    
	int	vers; 
1991/0727    
 
1992/1003/sys/src/9/pc/devfloppy.c:179,1841992/1006/sys/src/9/pc/devfloppy.c:194,200
1991/0924    
static int	floppysense(void); 
static void	floppywait(void); 
1991/0802    
static long	floppyxfer(Drive*, int, void*, long, long); 
1992/1006    
static int	floppyformat(Chan*, Drive*, int, char); 
1991/1006    
static long	floppythrice(Drive*, int, void*, long, long); 
1991/0924    
static int	cmddone(void*); 
void Xdelay(int); 
1992/1003/sys/src/9/pc/devfloppy.c:195,2051992/1006/sys/src/9/pc/devfloppy.c:211,238
1991/0802    
}; 
1991/0811    
#define NFDIR	2	/* directory entries/drive */ 
1991/0731    
 
1992/1006    
/* 
 *  set floppy drive to its default type 
 */ 
static void 
setdef(Drive *dp) 
{ 
	Type *t; 
 
	for(t = floppytype; t < &floppytype[NTYPES]; t++) 
		if(dp->dt == t->dt){ 
			dp->t = t; 
			floppydir[NFDIR*dp->dev].length = dp->t->cap; 
			break; 
		} 
} 
 
1991/0731    
void 
floppyreset(void) 
{ 
	Drive *dp; 
1991/0802    
	Type *t; 
1992/1006    
	uchar equip; 
1991/0731    
 
1991/0802    
	/* 
	 *  init dependent parameters 
1992/1003/sys/src/9/pc/devfloppy.c:229,2371992/1006/sys/src/9/pc/devfloppy.c:262,270
1991/0924    
	 */ 
	for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){ 
		dp->dev = dp - fl.d; 
1991/0731    
		dp->t = &floppytype[0];		/* default type */ 
1991/0811    
		floppydir[NFDIR*dp->dev].length = dp->t->cap; 
1992/1003    
		dp->arm = -1;		/* because we don't know */ 
1992/1006    
		dp->dt = T1440kb; 
		setdef(dp); 
		dp->cyl = -1;			/* because we don't know */ 
1992/0625    
		dp->cache = (uchar*)xspanalloc(dp->t->tsize, BY2PG, 0); 
1991/0924    
		dp->ccyl = -1; 
1991/0925    
		dp->vers = 1; 
1992/1003/sys/src/9/pc/devfloppy.c:238,2431992/1006/sys/src/9/pc/devfloppy.c:271,289
1991/0731    
	} 
1991/0809    
 
	/* 
1992/1006    
	 *  read nvram for types of floppies 0 & 1 
	 */ 
	equip = nvramread(0x10); 
	if(conf.nfloppy > 0){ 
		fl.d[0].dt = (equip >> 4) & 0xf; 
		setdef(&fl.d[0]); 
	} 
	if(conf.nfloppy > 1){ 
		fl.d[1].dt = equip & 0xf; 
		setdef(&fl.d[1]); 
	} 
 
	/* 
1991/0924    
	 *  first operation will recalibrate 
1991/0809    
	 */ 
1991/0924    
	fl.confused = 1; 
1992/1003/sys/src/9/pc/devfloppy.c:336,3441992/1006/sys/src/9/pc/devfloppy.c:382,392
1991/0925    
	ulong old; 
 
1991/1003    
	if(inb(Pdir)&Fchange){ 
1992/1006    
		setdef(dp); 
1991/0925    
		dp->vers++; 
		dp->ccyl = -1; 
1992/1003    
		if(dp->arm) 
1992/1006    
		dp->confused = 1; 
		floppyon(dp); 
		if(dp->cyl) 
1992/1002    
			floppythrice(dp, Fread, dp->cache, 0, dp->t->tsize); 
1991/0925    
		else 
1992/1003    
			floppythrice(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize, 
1992/1003/sys/src/9/pc/devfloppy.c:427,4321992/1006/sys/src/9/pc/devfloppy.c:475,482
1991/0731    
	Drive *dp; 
	long rv, i; 
1991/0924    
	char *aa = a; 
1992/1006    
	char *f[3]; 
	char ctlmsg[64]; 
1991/0731    
 
1991/0802    
	rv = 0; 
1991/0924    
	dp = &fl.d[c->qid.path & ~Qmask]; 
1992/1003/sys/src/9/pc/devfloppy.c:444,4511992/1006/sys/src/9/pc/devfloppy.c:494,500
1991/0924    
			floppypos(dp, c->offset+rv); 
			if(dp->tcyl == dp->ccyl) 
				dp->ccyl = -1; 
1991/1006    
			i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv, 
1991/0924    
				n-rv); 
1992/1006    
			i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv, n-rv); 
1991/1006    
			if(i < 0) 
1991/0802    
				break; 
1991/1006    
			if(i == 0) 
1992/1003/sys/src/9/pc/devfloppy.c:456,4701992/1006/sys/src/9/pc/devfloppy.c:505,523
1991/0802    
		break; 
1991/0924    
	case Qctl: 
1991/0925    
		qlock(&fl); 
1991/0924    
		if(SNCMP(aa, "eject") == 0){ 
1992/1006    
		if(n >= sizeof(ctlmsg)) 
			n = sizeof(ctlmsg) - 1; 
		memmove(ctlmsg, aa, n); 
		ctlmsg[n] = 0; 
		if(SNCMP(ctlmsg, "eject") == 0){ 
1991/0924    
			floppyeject(dp); 
		} else if(SNCMP(aa, "reset") == 0){ 
1992/1006    
		} else if(SNCMP(ctlmsg, "reset") == 0){ 
1991/0925    
			fl.confused = 1; 
1991/0924    
			floppyon(dp); 
1991/1029    
		} else if(SNCMP(aa, "fast") == 0){ 
			cpuspeed(1); 
		} else if(SNCMP(aa, "slow") == 0){ 
			cpuspeed(0); 
1992/1006    
		} else if(SNCMP(ctlmsg, "format") == 0){ 
			if(getfields(ctlmsg, f, 3, ' ') != 3) 
				error(Ebadarg); 
			rv = n*floppyformat(c, dp, atoi(f[1]), *f[2]); 
1991/0924    
		} 
1991/0925    
		qunlock(&fl); 
1991/0924    
		break; 
1992/1003/sys/src/9/pc/devfloppy.c:693,7011992/1006/sys/src/9/pc/devfloppy.c:746,754
1991/0727    
		dp->confused = 1; 
		return -1; 
	} 
1992/1003    
	dp->arm = fl.stat[1]; 
	if(dp->arm != 0){ 
		DPRINT("recalibrate went to wrong cylinder %d\n", dp->arm); 
1992/1006    
	dp->cyl = fl.stat[1]; 
	if(dp->cyl != 0){ 
		DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl); 
1991/0727    
		dp->confused = 1; 
		return -1; 
	} 
1992/1003/sys/src/9/pc/devfloppy.c:743,7491992/1006/sys/src/9/pc/devfloppy.c:796,802
1991/0924    
floppyseek(Drive *dp, long off) 
1991/0727    
{ 
1991/0924    
	floppypos(dp, off); 
1992/1003    
	if(dp->arm*dp->t->steps == dp->tcyl) 
1992/1006    
	if(dp->cyl == dp->tcyl) 
1992/1003    
		return dp->tcyl; 
1991/0727    
 
1992/0901    
	DPRINT("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead); 
1992/1003/sys/src/9/pc/devfloppy.c:767,7731992/1006/sys/src/9/pc/devfloppy.c:820,826
1991/0727    
		return -1; 
	} 
 
1992/1003    
	dp->arm = dp->tcyl*dp->t->steps; 
1992/1006    
	dp->cyl = dp->tcyl; 
1992/1003    
	return dp->tcyl; 
1991/0727    
} 
 
1992/1003/sys/src/9/pc/devfloppy.c:790,7971992/1006/sys/src/9/pc/devfloppy.c:843,856
1992/1003    
 
			/* walk through the compatible types */ 
			if(tries == 3){ 
				if(++dp->t == &floppytype[NTYPES]) 
					dp->t = floppytype; 
1992/1006    
				while(++dp->t){ 
					if(dp->t == &floppytype[NTYPES]) 
						dp->t = floppytype; 
					if(dp->dt == Tnone) 
						break; 
					if(dp->dt == dp->t->dt) 
						break; 
				} 
1992/1003    
				floppydir[NFDIR*dp->dev].length = dp->t->cap; 
				if(dp->t == start) 
					nexterror(); 
1992/1003/sys/src/9/pc/devfloppy.c:838,8441992/1006/sys/src/9/pc/devfloppy.c:897,903
1991/0924    
	fl.ncmd = 0; 
	fl.cmd[fl.ncmd++] = cmd; 
	fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev; 
	fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps; 
1992/1006    
	fl.cmd[fl.ncmd++] = dp->tcyl; 
1991/0924    
	fl.cmd[fl.ncmd++] = dp->thead; 
	fl.cmd[fl.ncmd++] = dp->tsec; 
	fl.cmd[fl.ncmd++] = dp->t->bcode; 
1992/1003/sys/src/9/pc/devfloppy.c:876,8821992/1006/sys/src/9/pc/devfloppy.c:935,941
1991/0924    
	/* 
	 *  check for correct cylinder 
	 */ 
1992/1003    
	offset = ((fl.stat[3]+dp->t->steps-1)/dp->t->steps) * dp->t->heads + fl.stat[4]; 
1992/1006    
	offset = fl.stat[3] * dp->t->heads + fl.stat[4]; 
1991/0924    
	offset = offset*dp->t->sectors + fl.stat[5] - 1; 
	offset = offset * c2b[fl.stat[6]]; 
1991/0802    
	if(offset != off+dp->len){ 
1992/1003/sys/src/9/pc/devfloppy.c:889,8941992/1006/sys/src/9/pc/devfloppy.c:948,1033
1991/0727    
	return dp->len; 
} 
 
1992/1006    
/* 
 *  format a track 
 */ 
static int 
floppyformat(Chan *c, Drive *dp, int track, char filler) 
{ 
 	int cyl, h, sec; 
	uchar *buf, *bp; 
	Type *t; 
 
	t = dp->t; 
	cyl = track/t->heads; 
	h = track % t->heads; 
	if(track >= t->tracks * t->heads) 
		return 0; 
	buf = smalloc(t->sectors*4); 
 
	qlock(&fl); 
	if(waserror()){ 
		qunlock(&fl); 
		free(buf); 
		nexterror(); 
	} 
	floppyon(dp); 
	changed(c, dp); 
	if(floppyseek(dp, track*t->tsize) < 0) 
		error(Eio); 
 
	/* 
	 *  set up the dma (dp->len may be trimmed) 
	 */ 
	bp = buf; 
	for(sec = 1; sec <= t->sectors; sec++){ 
		*bp++ = cyl; 
		*bp++ = h; 
		*bp++ = sec; 
		*bp++ = t->bcode; 
	} 
	dmasetup(DMAchan, buf, bp-buf, 0); 
 
	/* 
	 *  start operation 
	 */ 
	fl.ncmd = 0; 
	fl.cmd[fl.ncmd++] = Fformat; 
	fl.cmd[fl.ncmd++] = (h<<2) | dp->dev; 
	fl.cmd[fl.ncmd++] = t->bcode; 
	fl.cmd[fl.ncmd++] = t->sectors; 
	fl.cmd[fl.ncmd++] = t->fgpl; 
	fl.cmd[fl.ncmd++] = filler; 
	if(floppycmd() < 0){ 
		DPRINT("xfer cmd failed\n"); 
		error(Eio); 
	} 
 
	/* 
	 *  give bus to DMA, floppyintr() will read result 
	 */ 
	floppywait(); 
	dmaend(DMAchan); 
 
	/* 
	 *  check for errors 
	 */ 
	if(fl.nstat < 7){ 
		DPRINT("format result failed %lux\n", inb(Pmsr)); 
		fl.confused = 1; 
		error(Eio); 
	} 
	if((fl.stat[0]&Codemask)!=0 || fl.stat[1] || fl.stat[2]){ 
		DPRINT("format failed %lux %lux %lux\n", 
			fl.stat[0], fl.stat[1], fl.stat[2]); 
		dp->confused = 1; 
		error(Eio); 
	} 
	qunlock(&fl); 
	free(buf); 
	return 1; 
} 
 
1991/0925    
static void 
floppyintr(Ureg *ur) 
1991/0727    
{ 
1992/1003/sys/src/9/pc/devfloppy.c:896,9041992/1006/sys/src/9/pc/devfloppy.c:1035,1041
1991/0924    
	switch(fl.cmd[0]&~Fmulti){ 
	case Fread: 
	case Fwrite: 
		floppyresult(); 
		break; 
	case Freadid: 
1992/1006    
	case Fformat: 
1991/0924    
		floppyresult(); 
		break; 
	case Fseek: 


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