Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/pc/devfloppy.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname pc/devfloppy.c 1991/0727
## diff -e /dev/null /n/bootesdump/1991/0727/sys/src/9/safari/devfloppy.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"ureg.h"

typedef	struct Drive	Drive;
typedef	struct Controller	Controller;
typedef struct Type	Type;

enum
{
	Fmotor=		0x3f2,	/* motor port */
	 Fintena=	 0x4,	/* enable floppy interrupt */
	 Fena=		 0x8,	/* 0 == reset controller */

	Fstatus=	0x3f4,	/* controller main status port */
	 Fready=	 0x80,	/* ready to be touched */
	 Ffrom=		 0x40,	/* data from controller */
	 Fbusy=		 0x10,	/* operation not over */

	Fdata=		0x3f5,	/* controller data port */
	 Frecal=	 0x7,	/* recalibrate cmd */
	 Fseek=		 0xf,	/* seek cmd */
	 Fsense=	 0x8,	/* sense cmd */
	 Fread=		 0x66,	/* read cmd */
	 Fwrite=	 0x47,	/* write cmd */
	 Fmulti=	 0x80,	/* or'd with Fread or Fwrite for multi-head */

	DMAmode0=	0xb,
	DMAmode1=	0xc,
	DMAaddr=	0x4,
	DMAtop=		0x81,
	DMAinit=	0xa,
	DMAcount=	0x5,

	Nfloppy=	4,	/* floppies/controller */

	/* sector size encodings */
	S128=		0,
	S256=		1,
	S512=		2,
	S1024=		3,

	/* status 0 byte */
	Drivemask=	3<<0,
	Seekend=	1<<5,
	Codemask=	(3<<6)|(3<<3),
};

/*
 *  floppy types
 */
struct Type
{
	char	*name;
	int	bytes;		/* bytes/sector */
	int	sectors;	/* sectors/track */
	int	heads;		/* number of heads */
	int	steps;		/* steps per cylinder */
	int	tracks;		/* tracks/disk */
	int	gpl;		/* intersector gap length for read/write */	
	int	fgpl;		/* intersector gap length for format */	
	long	cap;		/* drive capacity in bytes */
};
Type floppytype[] =
{
 { "MF2HD",	S512,	18,	2,	1,	80,	0x1B,	0x54,	512*2*18*80 },
 { "MF2DD",	S512,	9,	2,	1,	80,	0x1B,	0x54,	512*2*9*80 },
 { "F2HD",	S512,	15,	2,	1,	80,	0x2A,	0x50,	512*15*2*80 },
 { "F2DD",	S512,	8,	2,	1,	40,	0x2A,	0x50,	512*8*2*40 },
 { "F1DD",	S512,	8,	1,	1,	40,	0x2A,	0x50,	512*8*1*40 },
};
static int secbytes[] =
{
	128,
	256,
	512,
	1024
};

/*
 *  a floppy drive
 */
struct Drive
{
	QLock;
	Type	*t;
	int	dev;

	ulong	lasttouched;	/* time last touched */
	int	motoron;	/* motor is on */
	int	cyl;		/* current cylinder */
	long	offset;		/* current offset */
	int	confused;	/* needs to be recalibrated (or worse) */

	int	tcyl;		/* target cylinder */
	int	thead;		/* target head */
	int	tsec;		/* target sector */
	long	len;

	int	busy;		/* true if drive is seeking */
	Rendez	r;		/* waiting for operation termination */
};

/*
 *  NEC PD765A controller for 4 floppys
 */
struct Controller
{
	QLock;
	Drive	d[Nfloppy];	/* the floppy drives */
	int	busy;		/* true if a read or write in progress */
	uchar	stat[8];	/* status of an operation */
	int	confused;
};

Controller	floppy[1];

/*
 *  start a floppy drive's motor.  set an alarm for 1 second later to
 *  mark it as started (we get no interrupt to tell us).
 *
 *  assume the caller qlocked the drive.
 */
void
floppystart(Drive *dp)
{
	int cmd;

	dp->lasttouched = m->ticks;	
	if(dp->motoron)
		return;

	cmd = (1<<(dp->dev+4)) | Fintena | Fena | dp->dev;
	outb(Fmotor, cmd);
	dp->busy = 1;
	tsleep(&dp->r, noreturn, 0, 1000);
	dp->motoron = 1;
	dp->busy = 0;
	dp->lasttouched = m->ticks;
}

/*
 *  stop the floppy if it hasn't been used in 5 seconds
 */
void
floppystop(Drive *dp)
{
	int cmd;

	if(!canqlock(dp))
		return;
	cmd = Fintena | Fena | dp->dev;
	outb(Fmotor, cmd);
	dp->motoron = 0;	
}
void
floppykproc(Alarm* a)
{
	Drive *dp;

	if(waserror())
	for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
		if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5)
			floppystop(dp);
	}
		
	alarm(5*1000, floppyalarm, 0);
	cancel(a);
}

int
floppysend(int data)
{
	int tries;
	uchar c;

	for(tries = 0; tries < 100; tries++){
		/*
		 *  see if its ready for data
		 */
		c = inb(Fstatus);
		if((c&(Ffrom|Fready)) != Fready)
			continue;

		/*
		 *  send the data
		 */
		outb(Fdata, data);
		return 0;
	}
	return -1;
}

int
floppyrcv(void)
{
	int tries;
	uchar c;

	for(tries = 0; tries < 100; tries++){
		/*
		 *  see if its ready for data
		 */
		c = inb(Fstatus);
		if((c&(Ffrom|Fready)) != (Ffrom|Fready))
			continue;

		/*
		 *  get data
		 */
		return inb(Fdata)&0xff;
	}
	return -1;
}

int
floppyrdstat(int n)
{
	int i;
	int c;

	for(i = 0; i < n; i++){
		c = floppyrcv();
		if(c < 0)
			return -1;
		floppy.stat[i] = c;
	}
	return 0;
}

void
floppypos(Drive *dp, long off)
{
	int lsec;
	int end;
	int cyl;

	lsec = off/secbytes[dp->t->bytes];
	dp->tcyl = lsec/(dp->t->sectors*dp->t->heads);
	dp->tsec = (lsec % dp->t->sectors) + 1;
	dp->thead = (lsec/dp->t->sectors) % dp->t->heads;

	/*
	 *  can't read across cylinder boundaries.
	 *  if so, decrement the bytes to be read.
	 */
	lsec = (off+dp->len)/secbytes[dp->t->bytes];
	cyl = lsec/(dp->t->sectors*dp->t->heads);
	if(cyl != dp->tcyl){
		dp->len -= (lsec % dp->t->sectors)*secbytes[dp->t->bytes];
		dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*secbytes[dp->t->bytes]
				*dp->t->sectors;
	}

	dp->lasttouched = m->ticks;	
	floppy.intr = 0;
}

void
floppywait(void)
{
	int tries;

	for(tries = 0; tries < 100 && floppy.intr == 0; tries++)
		delay(5);
	if(tries >= 100)
		print("tired floopy\n");
	floppy.intr = 0;
}

int
floppysense(Drive *dp)
{
	/*
	 *  ask for floppy status
	 */
	if(floppysend(Fsense) < 0){
		floppy.confused = 1;
		return -1;
	}
	if(floppyrdstat(2) < 0){
		floppy.confused = 1;
		dp->confused = 1;
		return -1;
	}

	/*
	 *  make sure it's the right drive
	 */
	if((floppy.stat[0] & Drivemask) != dp-floppy.d){
		print("sense failed\n");
		dp->confused = 1;
		return -1;
	}
	return 0;
}

int
floppyrecal(Drive *dp)
{
	floppy.intr = 0;
	if(floppysend(Frecal) < 0
	|| floppysend(dp - floppy.d) < 0){
		floppy.confused = 0;
		return -1;
	}
	floppywait();

	/*
	 *  get return values
	 */
	if(floppysense(dp) < 0)
		return -1;

	/*
	 *  see if it worked
	 */
	if((floppy.stat[0] & (Codemask|Seekend)) != Seekend){
		print("recalibrate failed\n");
		dp->confused = 1;
		return -1;
	}

	/*
	 *  see what cylinder we got to
	 */
	dp->tcyl = 0;
	dp->cyl = floppy.stat[1]/dp->t->steps;
	if(dp->cyl != dp->tcyl){
		print("recalibrate went to wrong cylinder %d\n", dp->cyl);
		dp->confused = 1;
		return -1;
	}

	dp->confused = 0;
	return 0;
}

void
floppyinit(void)
{
	Drive *dp;

	for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
		dp->t = &floppytype[0];
		dp->cyl = -1;
		dp->motoron = 1;
		floppystop(dp);
	}
	setvec(22, floppyintr);
	alarm(5*1000, floppyalarm, (void *)0);
}

void
floppyreset(void)
{
	Drive *dp;

	/*
	 *  reset the floppy if'n it's confused
	 */
	if(floppy.confused){
		/* reset controller and turn all motors off */
		floppy.intr = 0;
		splhi();
		outb(Fmotor, 0);
		delay(1);
		outb(Fmotor, Fintena|Fena);
		spllo();
		for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
			dp->motoron = 0;
			dp->confused = 1;
		}
		floppywait();
		floppy.confused = 0;
	}

	/*
	 *  recalibrate any confused drives
	 */
	for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[Nfloppy]; dp++){
		if(dp->confused == 0)
			floppyrecal(dp);

	}

}

long
floppyseek(int dev, long off)
{
	Drive *dp;

	dp = &floppy.d[dev];

	if(floppy.confused || dp->confused)
		floppyreset();

	floppystart(dp);

	floppypos(dp, off);
	if(dp->cyl == dp->tcyl){
		dp->offset = off;
		return off;
	}

	/*
	 *  tell floppy to seek
	 */
	if(floppysend(Fseek) < 0
	|| floppysend((dp->thead<<2) | dev) < 0
	|| floppysend(dp->tcyl * dp->t->steps) < 0){
		print("seek cmd failed\n");
		floppy.confused = 1;
		return -1;
	}

	/*
	 *  wait for interrupt
	 */
	floppywait();

	/*
	 *  get floppy status
	 */
	if(floppysense(dp) < 0)
		return -1;

	/*
 	 *  see if it worked
	 */
	if((floppy.stat[0] & (Codemask|Seekend)) != Seekend){
		print("seek failed\n");
		dp->confused = 1;
		return -1;
	}

	/*
	 *  see what cylinder we got to
	 */
	dp->cyl = floppy.stat[1]/dp->t->steps;
	if(dp->cyl != dp->tcyl){
		print("seek went to wrong cylinder %d instead of %d\n", dp->cyl, dp->tcyl);
		dp->confused = 1;
		return -1;
	}

	dp->offset = off;
	return dp->offset;
}

long
floppyxfer(Drive *dp, int cmd, void *a, long n)
{
	int dev;
	ulong addr;
	long offset;

	addr = (ulong)a;
	dev = dp - floppy.d;

	/*
	 *  dma can't cross 64 k boundaries
	 */
	if((addr & 0xffff0000) != ((addr+n) & 0xffff0000))
		n -= (addr+n)&0xffff;

	dp->len = n;
	floppyseek(dev, dp->offset);

/*	print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
		dp->tcyl, dp->thead, dp->tsec, addr, n);/**/

	/*
	 *  set up the dma
	 */
	outb(DMAmode1, cmd==Fread ? 0x46 : 0x4a);
	outb(DMAmode0, cmd==Fread ? 0x46 : 0x4a);
	outb(DMAaddr, addr);
	outb(DMAaddr, addr>>8);
	outb(DMAtop, addr>>16);
	outb(DMAcount, n-1);
	outb(DMAcount, (n-1)>>8);
	outb(DMAinit, 2);

	/*
	 *  tell floppy to go
	 */
	cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);
	if(floppysend(cmd) < 0
	|| floppysend((dp->thead<<2) | dev) < 0
	|| floppysend(dp->tcyl * dp->t->steps) < 0
	|| floppysend(dp->thead) < 0
	|| floppysend(dp->tsec) < 0
	|| floppysend(dp->t->bytes) < 0
	|| floppysend(dp->t->sectors) < 0
	|| floppysend(dp->t->gpl) < 0
	|| floppysend(0xFF) < 0){
		print("xfer cmd failed\n");
		floppy.confused = 1;
		return -1;
	}

	floppywait();

	/*
	 *  get status
 	 */
	if(floppyrdstat(7) < 0){
		print("xfer status failed\n");
		floppy.confused = 1;
		return -1;
	}

	if((floppy.stat[0] & Codemask)!=0 || floppy.stat[1] || floppy.stat[2]){
print("xfer failed %lux %lux %lux\n", floppy.stat[0],
			floppy.stat[1], floppy.stat[2]);
		dp->confused = 1;
		return -1;
	}

	offset = (floppy.stat[3]/dp->t->steps) * dp->t->heads + floppy.stat[4];
	offset = offset*dp->t->sectors + floppy.stat[5] - 1;
	offset = offset * secbytes[floppy.stat[6]];
	if(offset != dp->offset+n){
		print("new offset %d instead of %d\n", offset, dp->offset+dp->len);
		dp->confused = 1;
		return -1;/**/
	}

	dp->offset += dp->len;
	return dp->len;
}

long
floppyread(int dev, void *a, long n)
{
	Drive *dp;
	long rv, i;
	uchar *aa = a;

	dp = &floppy.d[dev];
	for(rv = 0; rv < n; rv += i){
		i = floppyxfer(dp, Fread, aa+rv, n-rv);
		if(i <= 0)
			break;
	}
	return rv;
}

void
floppyintr(Ureg *ur)
{
	floppy.intr = 1;
}
.
## diffname pc/devfloppy.c 1991/0728
## diff -e /n/bootesdump/1991/0727/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0728/sys/src/9/safari/devfloppy.c
354,355c
}

void
floppyinit(void)
{
	kproc(floppykproc, 0);
.
351a
		dp->cyl = -1;
.
349,350c
		dp->dev = dp - floppy.d;
		dp->t = &floppytype[0];		/* default type */
.
344c
floppyreset(void)
.
170,172d
168a
			qunlock(dp);
		}
.
167c
		if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5
		&& canqlock(dp)){
.
165d
154,155d
120c
Controller	floppy;
.
50a

	/* file types */
	Qdir=		0,
	Qdata=		16,
	Qstruct=	32,
.
40a
	DMAchan=	2,	/* floppy dma channel */

.
32,38d
## diffname pc/devfloppy.c 1991/0729
## diff -e /n/bootesdump/1991/0728/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0729/sys/src/9/safari/devfloppy.c
166c
			if(TK2SEC(m->ticks - dp->lasttouched) > 5)
				floppystop(dp);
.
## diffname pc/devfloppy.c 1991/0730
## diff -e /n/bootesdump/1991/0729/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0730/sys/src/9/safari/devfloppy.c
256,270d
## diffname pc/devfloppy.c 1991/0731
## diff -e /n/bootesdump/1991/0730/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0731/sys/src/9/safari/devfloppy.c
546a
	wakeup(&floppy.r);
.
527,543c
static void
.
522a
	qunlock(&floppy);
	qunlock(dp);
	poperror();

.
520c
		errors("floppy drive lost");
.
518c
print("new offset %d instead of %d\n", offset, dp->offset+dp->len);
.
516c
	offset = offset * c2b[floppy.stat[6]];
.
511c
		errors("floppy drive lost");
.
504c
		errors("floppy result failed");
.
501,502c
	if(floppyresult(7) < 0){
print("xfer status failed\n");
.
496c
	sleep(&floppy.r, interrupted, 0);
.
493c
		errors("floppy command failed");
.
487c
	|| floppysend(dp->t->bcode) < 0
.
479c
	 *  start operation
.
469,476c
	dp->len = dmasetup(2, a, dp->len, cmd==Fread);
.
467c
	 *  set up the dma (dp->len may be trimmed)
.
463c
print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
.
461c
	floppypos(dp);
	if(floppyseek(dp) < 0)
		errors("seeking floppy");
.
459a
	/*
	 *  calculate new position and seek to it (dp->len may be trimmed)
	 */
.
457,458c
	if(floppy.confused || dp->confused)
		floppyrevive();
	if(!dp->motoron)
		motoron(dp);
.
455c
	 *  get floppy reset and spinning
.
453a
	qlock(&floppy);
	qlock(dp);
	if(waserror){
		qunlock(&floppy);
		qunlock(dp);
	}

.
452d
447d
444c
static long
.
413c
	sleep(&floppy.r, interrupted, 0);
.
403c
	|| floppysend((dp->thead<<2) | dp->dev) < 0
.
384,393d
381,382c
static long
floppyseek(Drive *dp)
.
373c
	for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[Ndrive]; dp++){
.
366c
		sleep(&floppy.r, interrupted, 0);
.
362c
		for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
.
352c
	 *  reset the floppy if it's confused
.
331,350d
327c
floppyrevive(void)
.
325a
/*
 *  if the controller or a specific drive is in a confused state,
 *  reset it and get back to a kown state
 */
.
294c
	sleep(&floppy.r, interrupted, 0);
.
285c
/*
 *  return true if interrupt occurred
 */
static int
interrupted(void *a)
{
	return floppy.intr;
}

/*
 *  we've lost the floppy position, go to cylinder 0.
 */
static int
.
268c
	if(floppyresult(2) < 0){
.
258c
/*
 *  get the interrupt cause from the floppy.  we need to do this
 *  after seeks and recalibrations since they don't return results.
 */
static int
.
252,253c
		dp->len -= (lsec % dp->t->sectors)*dp->t->bytes;
		dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*dp->t->bytes
.
249c
	lsec = (dp->off+dp->len)/dp->t->bytes;
.
240c
	lsec = dp->off/dp->t->bytes;
.
233,234c
/*
 *  calculate physical address of a logical byte offset into the disk
 *
 *  truncate dp->length if it crosses a cylinder boundary
 */
static void
floppypos(Drive *dp)
.
218,219c
/*
 *  read a command result message from the floppy
 */
static int
floppyresult(int n)
.
196c
/*
 *  get a byte from the floppy
 */
static int
.
173c
/*
 *  send a byte to the floppy
 */
static int
.
167c
				motoroff(dp);
.
163c
	for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
.
158,159c
static void
floppykproc(void *a)
.
149,150c
static void
motoroff(Drive *dp)
.
133,136d
128,129c
static void
motoron(Drive *dp)
.
122a
 *  predeclared
 */
static void	motoron(Drive*);
static void	motoroff(Drive*);
static void	floppykproc(void*);
static int	floppysend(int);
static int	floppyrcv(void);
static int	floppyresult(int);
static void	floppypos(Drive*);
static int	floppysense(Drive*);
static int	interrupted(void*);
static int	floppyrecal(Drive*);
static void	floppyrevive(void);
static long	floppyseek(Drive*);
static long	floppyxfer(Drive*, int, void*, long);
static void	floppyintr(Ureg*);

static int
floppygen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp)
{
	long l;
	Drive *dp;

	if(s >= ntab)
		return -1;
	if(c->dev >= Ndrive)
		return -1;

	tab += s;
	dp = &floppy.d[c->dev];
	if((tab->qid.path&~Mask) == Qdata)
		l = dp->t->cap;
	else
		l = 8;
	devdir(c, tab->qid, tab->name, l, tab->perm, dp);
	return 1;
}

void
floppyreset(void)
{
	Drive *dp;

	for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
		dp->dev = dp - floppy.d;
		dp->t = &floppytype[0];		/* default type */
		dp->motoron = 1;
		dp->cyl = -1;
		motoroff(dp);
	}
	setvec(Floppyvec, floppyintr);
}

void
floppyinit(void)
{
	Type *t;

	/*
	 *  init dependent parameters
	 */
	for(t = floppytype; t < &floppytype[NTYPES], t++){
		t->cap = t->bytes * t->heads * t->sectors * t->tracks;
		t->bcode = bcode[t->bytes/128];
	}

	/*
	 *  watchdog to turn off the motors
	 */
	kproc(floppykproc, 0);
}
long
floppyread(Chan *c, void *a, long n)
{
	Drive *dp;
	long rv, i;
	uchar *aa = a;

	dp = &floppy.d[c->dev];
	for(rv = 0; rv < n; rv += i){
		i = floppyxfer(dp, Fread, aa+rv, n-rv);
		if(i <= 0)
			break;
	}
	return rv;
}

long
floppywrite(Chan *c, void *a, long n)
{
	Drive *dp;
	long rv, i;
	uchar *aa = a;

	dp = &floppy.d[c->dev];
	for(rv = 0; rv < n; rv += i){
		i = floppyxfer(dp, Fwrite, aa+rv, n-rv);
		if(i <= 0)
			break;
	}
	return rv;
}

/*
.
117a
	int	intr;		/* true if interrupt occured */
	Rendez	r;		/* wait here for command termination */
.
113,114c
	QLock;			/* exclusive access to the contoller */

	Drive	d[Ndrive];	/* the floppy drives */
.
105c
	Rendez	r;		/* waiting here for motor to spin up */
.
102c
	long	len;		/* size of xfer */
.
89c
	QLock;			/* exclusive access to the drive */

.
81c
	1024,
.
77a
[1]	0,
[2]	1,
[4]	2,
[8]	3,
};
static int c2b[] =
{
.
76c
#define NTYPES (sizeof(floppytype)/sizeof(Type))

/*
 *  bytes/sector encoding for the controller, index is (bytes per sector/128)
 */
static int b2c[] =
.
70,74c
	{ "MF2HD",	512,	18,	2,	1,	80,	0x1B,	0x54, },
	{ "MF2DD",	512,	9,	2,	1,	80,	0x1B,	0x54, },
	{ "F2HD",	512,	15,	2,	1,	80,	0x2A,	0x50, },
	{ "F2DD",	512,	8,	2,	2,	40,	0x2A,	0x50, },
	{ "F1DD",	512,	8,	1,	2,	40,	0x2A,	0x50, },
.
65c
	int	fgpl;		/* intersector gap length for format */

	/*
	 *  these depend on previous entries and are set filled in
	 *  by floppyinit
	 */
	int	bcode;		/* coded version of bytes for the controller */
.
49,50c
	Qdata=		1,
	Qstruct=	2,
.
32c
	Ndrive=	4,	/* floppies/controller */
.
## diffname pc/devfloppy.c 1991/0802
## diff -e /n/bootesdump/1991/0731/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0802/sys/src/9/safari/devfloppy.c
658d
653a
	dp->lasttouched = m->ticks;
.
648,649c
	if(offset != off+dp->len){
print("new offset %d instead of %d\n", offset, off+dp->len);
.
626d
614c
	|| floppysend((dp->thead<<2) | dp->dev) < 0
.
611a
	floppy.intr = 0;
.
597c
	floppypos(dp, off);
.
580c
	if(waserror()){
.
571c
floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
.
566,567c
	return dp->cyl;
.
535,538d
527a
	floppy.intr = 0;
	dp->cyl = -1;	/* once the seek starts it could end anywhere */
.
520,523c
	if(dp->cyl == dp->tcyl)
		return dp->cyl;
.
417c
	if((floppy.stat[0] & Drivemask) != dp->dev){
.
385c
	lsec = (off+dp->len)/dp->t->bytes;
.
376c
	lsec = off/dp->t->bytes;
.
370c
floppypos(Drive *dp, long off)
.
291a
		tsleep(&floppy.kr, return0, 0, 5*1000);
.
285,290c
	waserror();
	for(;;){
		for(dp = floppy.d; dp < &floppy.d[Ndrive]; dp++){
			if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5
			&& canqlock(dp)){
				if(TK2SEC(m->ticks - dp->lasttouched) > 5)
					motoroff(dp);
				qunlock(dp);
			}
.
264d
261,262c
	tsleep(&dp->r, return0, 0, 750);
.
249c
 *  start a floppy drive's motor.  set an alarm for .75 second later to
.
239,243c
	rv = 0;
	dp = &floppy.d[c->qid.path & ~Qmask];
	switch ((int)(c->qid.path & Qmask)) {
	case Qdata:
		for(rv = 0; rv < n; rv += i){
			i = floppyxfer(dp, Fwrite, aa+rv, c->offset+rv, n-rv);
			if(i <= 0)
				break;
		}
		break;
	case Qstruct:
		error(Eperm);
		break;
	default:
		panic("floppywrite: bad qid");
.
223,227c
	if(c->qid.path == CHDIR)
		return devdirread(c, a, n, floppydir, NFDIR, devgen);

	rv = 0;
	dp = &floppy.d[c->qid.path & ~Qmask];
	switch ((int)(c->qid.path & Qmask)) {
	case Qdata:
		for(rv = 0; rv < n; rv += i){
			i = floppyxfer(dp, Fread, aa+rv, c->offset+rv, n-rv);
			if(i <= 0)
				break;
		}
		break;
	case Qstruct:
		if (n < 2*sizeof(ulong))
			error(Ebadarg);
		if (c->offset >= 2*sizeof(ulong))
			return 0;
		rv = 2*sizeof(ulong);
		ul2user((uchar*)a, dp->t->cap);
		ul2user((uchar*)a+sizeof(ulong), dp->t->bytes);
		break;
	default:
		panic("floppyread: bad qid");
.
215a

Chan*
floppyattach(char *spec)
{
	return devattach('f', spec);
}

Chan*
floppyclone(Chan *c, Chan *nc)
{
	return devclone(c, nc);
}

int
floppywalk(Chan *c, char *name)
{
	return devwalk(c, name, floppydir, NFDIR, devgen);
}

void
floppystat(Chan *c, char *dp)
{
	devstat(c, dp, floppydir, NFDIR, devgen);
}

Chan*
floppyopen(Chan *c, int omode)
{
	return devopen(c, omode, floppydir, NFDIR, devgen);
}

void
floppycreate(Chan *c, char *name, int omode, ulong perm)
{
	error(Eperm);
}

void
floppyclose(Chan *c)
{
}

void
floppyremove(Chan *c)
{
	error(Eperm);
}

void
floppywstat(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;
}

.
214c
	kproc("floppy", floppykproc, 0);
.
204,211d
201,202d
192c
		dp->cyl = -1;		/* because we don't know */
.
190a
		floppydir[2*dp->dev].length = dp->t->cap;
.
187a
	/*
	 *  init dependent parameters
	 */
	for(t = floppytype; t < &floppytype[NTYPES]; t++){
		t->cap = t->bytes * t->heads * t->sectors * t->tracks;
		t->bcode = b2c[t->bytes/128];
	}

	/*
	 *  stop the motors
	 */
.
186a
	Type *t;
.
168,182d
162,166c
Dirtab floppydir[]={
	"fd0data",		{Qdata + 0},	0,	0600,
	"fd0struct",		{Qstruct + 0},	8,	0600,
	"fd1data",		{Qdata + 1},	0,	0600,
	"fd1struct",		{Qstruct + 1},	8,	0600,
	"fd2data",		{Qdata + 2},	0,	0600,
	"fd2struct",		{Qstruct + 2},	8,	0600,
	"fd3data",		{Qdata + 3},	0,	0600,
	"fd3struct",		{Qstruct + 3},	8,	0600,
};
#define NFDIR	(sizeof(floppydir)/sizeof(Dirtab))
.
159c
static long	floppyxfer(Drive*, int, void*, long, long);
.
153c
static void	floppypos(Drive*,long);
.
139a

	Rendez	kr;		/* for motor watcher */
.
135d
123d
115d
85c
 *  bytes per sector encoding for the controller.
 *  - index for b2c is is (bytes per sector/128).
 *  - index for c2b is code from b2c
.
49,50c
	Qdata=		(1<<2),
	Qstruct=	(2<<2),
	Qmask=		(3<<2),
.
11c
typedef struct Type		Type;
.
9c
typedef	struct Drive		Drive;
.
7c
#include	"errno.h"
.
## diffname pc/devfloppy.c 1991/0803
## diff -e /n/bootesdump/1991/0802/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0803/sys/src/9/safari/devfloppy.c
381a
		
.
380a
		disp++;
		if(owl(disp&1) < 0)
			print("owl failed\n");
		if(mail((disp>>1)&1) < 0)
			print("mail failed\n");
.
369a
	int disp = 0;
.
## diffname pc/devfloppy.c 1991/0806
## diff -e /n/bootesdump/1991/0803/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0806/sys/src/9/safari/devfloppy.c
756a
print("floppy intr\n");
.
## diffname pc/devfloppy.c 1991/0809
## diff -e /n/bootesdump/1991/0806/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0809/sys/src/9/safari/devfloppy.c
606c
	for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[conf.nfloppy]; dp++){
.
595c
		for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
.
385,386d
374c
		for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
.
289,292c
		if(c->offset % dp->t->bytes)
			errors("bad offset");
		if(n % dp->t->bytes)
			errors("bad len");
		nn = dp->t->bytes * dp->t->sectors * dp->t->heads;
		for(rv = 0; rv < n; rv += len){
			/*
			 *  truncate xfer at cylinder boundary
			 */
			dp->len = n - rv;
			floppypos(dp, c->offset+rv);
			cyl = dp->tcyl;
			len = dp->len;
			sec = dp->tsec + dp->thead * dp->t->sectors;

			/*
			 *  read the cylinder
			 */
			if(dp->ccyl != cyl){
				dp->ccyl = -1;
				if(floppyxfer(dp, Fread, dp->ccache, cyl * nn, nn) != nn)
					errors("floppy read err");
				dp->ccyl = cyl;
			}
			memmove(aa+rv, dp->ccache + (sec-1)*dp->t->bytes, len);
.
279c
	long rv, nn, len, cyl;
	int sec;
.
274a
/*
 *  the floppy is so slow, we always read a cylinder
 *  at a time and cache the extra bytes.
 */
.
200a

	/*
	 *  allocate cylinder caches that don't cross 64k boundaries
	 */
	for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
		do {
			dp->ccache = ialloc(dp->t->cap, 1);
		} while(k64(dp->ccache) != k64(dp->ccache+dp->t->cap));
		dp->ccyl = -1;
	}
.
193c
	for(dp = floppy.d; dp < &floppy.d[conf.nfloppy]; dp++){
.
190a
	 *  allocate the drive storage
	 */
	floppy.d = ialloc(conf.nfloppy*sizeof(Drive), 0);

	/*
.
175a
#define k64(x) (((ulong)(x))>>16)
.
135c
	Drive	*d;		/* the floppy drives */
.
125a

	uchar	*ccache;	/* cylinder cache (always read a whole cyl) */
	int	ccyl;		/* number of cached cylinder */
.
32,33d
## diffname pc/devfloppy.c 1991/0810
## diff -e /n/bootesdump/1991/0809/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0810/sys/src/9/safari/devfloppy.c
214,215c
			n = 512 * 18 * 2;	/* MF2HD cylinder size */
			dp->ccache = ialloc(n, 1);
		} while(k64(dp->ccache) != k64(dp->ccache+n));
.
182a
	int n;
.
## diffname pc/devfloppy.c 1991/0811
## diff -e /n/bootesdump/1991/0810/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0811/sys/src/9/safari/devfloppy.c
307c
		return devdirread(c, a, n, floppydir, conf.nfloppy*NFDIR, devgen);
.
259c
	return devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen);
.
253c
	devstat(c, dp, floppydir, conf.nfloppy*NFDIR, devgen);
.
247c
	return devwalk(c, name, floppydir, conf.nfloppy*NFDIR, devgen);
.
204c
		floppydir[NFDIR*dp->dev].length = dp->t->cap;
.
175c
#define NFDIR	2	/* directory entries/drive */
.
## diffname pc/devfloppy.c 1991/0823
## diff -e /n/bootesdump/1991/0811/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0823/sys/src/9/safari/devfloppy.c
800c
/*print("floppy intr\n");/**/
.
736c
/*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
.
372,374d
340,348d
166,173c
	"fd0disk",		{Qdata + 0},	0,	0600,
	"fd1disk",		{Qdata + 1},	0,	0600,
	"fd2disk",		{Qdata + 2},	0,	0600,
	"fd3disk",		{Qdata + 3},	0,	0600,
.
48d
34,39d
## diffname pc/devfloppy.c 1991/0831
## diff -e /n/bootesdump/1991/0823/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0831/sys/src/9/safari/devfloppy.c
345a
		floppychanged(dp);
		dp->ccyl = -1;
.
301a
		floppychanged(dp);
.
283a
 *  look for a floppy change
 */
void
floppychange(Drive *dp)
{
	if((inb(Fchanged) & Fchange) == 0)
		return;

	
}

/*
.
31a
	Fchanged=	0x3F7,	/* disk changed register */
	 Fchange=	 0x80,	/* disk has changed */

.
29c
	 Fwrite=	 0x45,	/* write cmd */
.
## diffname pc/devfloppy.c 1991/0902
## diff -e /n/bootesdump/1991/0831/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0902/sys/src/9/safari/devfloppy.c
290c
floppychanged(Drive *dp)
.
## diffname pc/devfloppy.c 1991/0906
## diff -e /n/bootesdump/1991/0902/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0906/sys/src/9/safari/devfloppy.c
732c
		dp->tcyl, dp->thead, dp->tsec, a, n);/**/
.
730a
	
.
706,707d
703d
## diffname pc/devfloppy.c 1991/0913
## diff -e /n/bootesdump/1991/0906/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0913/sys/src/9/safari/devfloppy.c
423,424d
## diffname pc/devfloppy.c 1991/0919
## diff -e /n/bootesdump/1991/0913/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0919/sys/src/9/safari/devfloppy.c
412c
	while(waserror())
		;
.
## diffname pc/devfloppy.c 1991/0920
## diff -e /n/bootesdump/1991/0919/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0920/sys/src/9/safari/devfloppy.c
295c
	print("floppy has changed\n");
.
277,285d
226a
	static int kstarted;

	if(kstarted == 0){
		/*
		 *  watchdog to turn off the motors
		 */
		kstarted = 1;
		kproc("floppy", floppykproc, 0);
	}
.
218,221d
165a
	"fd3ctl",		{Qctl + 3},	0,	0600,
.
164a
	"fd2ctl",		{Qctl + 2},	0,	0600,
.
163a
	"fd1ctl",		{Qctl + 1},	0,	0600,
.
162a
	"fd0ctl",		{Qctl + 0},	0,	0600,
.
44a
	Qctl=		(2<<2),
.
8a
/* NEC PD765A (8272A compatible) floppy controller */

.
## diffname pc/devfloppy.c 1991/0921
## diff -e /n/bootesdump/1991/0920/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0921/sys/src/9/safari/devfloppy.c
719,720c
	motoron(dp);
.
638a
		floppy.motor = 0;
.
636d
432a
 *  start a floppy drive's motor.  set an alarm for .75 second later to
 *  mark it as started (we get no interrupt to tell us).
 *
 *  assume the caller qlocked the drive.
 *
 *  this also selects the drive for subsequent operations
 */
static void
motoron(Drive *dp)
{
	int alreadyon;

	alreadyon = floppy.motor & MOTORBIT(dp->dev);
	floppy.motor |= MOTORBIT(dp->dev);
	driveselect(dp);
	if(!alreadyon)
		tsleep(&dp->r, return0, 0, 750);
	dp->lasttouched = m->ticks;
}

/*
 *  stop the floppy if it hasn't been used in 5 seconds
 */
static void
motoroff(Drive *dp)
{
	floppy.motor &= ~MOTORBIT(dp->dev);
	driveselect(dp);
}

/*
.
431a
static void
driveselect(Drive *dp)
{
	int cmd;

	cmd = floppy.motor | Fintena | Fena | dp->dev;
	outb(Fmotor, cmd);
}

.
419c
			if((floppy.motor&MOTORBIT(dp->dev))
			&& TK2SEC(m->ticks - dp->lasttouched) > 5
.
386,409d
379,384d
204c
		floppy.motor |= MOTORBIT(dp->dev);
.
145a
#define MOTORBIT(i)	(1<<((i)+4))

.
139a
	int	motor;
.
113d
## diffname pc/devfloppy.c 1991/0924
## diff -e /n/bootesdump/1991/0921/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0924/sys/src/9/safari/devfloppy.c
807,809c
	switch(fl.cmd[0]&~Fmulti){
	case Fread:
	case Fwrite:
		floppyresult();
		break;
	case Freadid:
		floppyresult();
		break;
	case Fseek:
	case Frecal:
	default:
		floppysense();	/* to clear interrupt */
		break;
	}
	fl.ncmd = 0;
	wakeup(&fl.r);
.
804,805c
void
floppyintr(void)
.
797c
	qunlock(&fl);
.
791c
		print("new offset %d instead of %d\n", offset, off+dp->len);
.
787,789c
	/*
	 *  check for correct cylinder
	 */
	offset = (fl.stat[3]/dp->t->steps) * dp->t->heads + fl.stat[4];
	offset = offset*dp->t->sectors + fl.stat[5] - 1;
	offset = offset * c2b[fl.stat[6]];
.
779,784c
	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]++;
.
772,776c
	 *  give bus to DMA, floppyintr() will read result
	 */
	floppywait();
	dmaend(DMAchan);

	/*
	 *  check for errors
	 */
	if(fl.nstat < 7){
		print("xfer result failed %lux\n", inb(Pmsr));
		fl.confused = 1;
.
769d
766d
754,764c
/*	cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);/**/
	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;
	fl.cmd[fl.ncmd++] = dp->thead;
	fl.cmd[fl.ncmd++] = dp->tsec;
	fl.cmd[fl.ncmd++] = dp->t->bcode;
	fl.cmd[fl.ncmd++] = dp->tsec + dp->len/dp->t->bytes - 1;
	fl.cmd[fl.ncmd++] = dp->t->gpl;
	fl.cmd[fl.ncmd++] = 0xFF;
	if(floppycmd() < 0){
		spllo();
.
749c
	dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
.
744c
	dp->tcyl, dp->thead, dp->tsec, a, dp->len);/**/
.
741d
738,739c
	if(floppyseek(dp, off) < 0)
.
728,734d
724a
		fl.confused = 1;
		nexterror();
.
723c
		dmaend(DMAchan);
		qunlock(&fl);
.
720c
	if(off >= dp->t->cap)
		return 0;
	if(off + n > dp->t->cap)
		n = dp->t->cap - off;

	qlock(&fl);
.
718a
	ulong up;
.
702,711c
	dp->cyl = dp->tcyl;
.
692,696c
	}
	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
.
685,690c
	floppywait();
	if(fl.nstat < 2){
		fl.confused = 1;
.
682d
673,680c
/* print("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead); /**/
	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = Fseek;
	fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
	fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
	if(floppycmd() < 0){
.
669a
	floppyon(dp);
	floppypos(dp, off);
.
668c
floppyseek(Drive *dp, long off)
.
666a
/*
 *  seek to the target cylinder
 *
 *	interrupt, no results
 */
.
655,664d
650,653c
		fl.motor = 0;
		floppywait();
		fl.confused = 0;
/*		devp->dsr = 0;
		devp->ccr = 0; /**/
.
648c
		for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++)
.
646c
		outb(Pdor, Fintena|Fena);
.
644c
		fl.cmd[0] = 0;
		outb(Pdor, 0);
.
642d
640c
	if(fl.confused){
.
638c
	 *  reset the controller if it's confused
.
612,618c
	dp->cyl = fl.stat[1]/dp->t->steps;
	if(dp->cyl != 0){
.
604,608c
	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = Frecal;
	fl.cmd[fl.ncmd++] = dp->dev;
	if(floppycmd() < 0)
		return -1;
	floppywait();
	if(fl.nstat < 2){
		fl.confused = 1;
		return -1;
	}
	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
.
598,602c
	dp->ccyl = -1;
.
590,596c
	int type;
.
581c
	tsleep(&fl.r, cmddone, 0, 2000);
.
578,579c
static void
floppywait(void)
.
576c
 *  wait for a floppy interrupt
.
574a
static int
cmddone(void *a)
{
	return fl.ncmd == 0;
}

.
563,571d
557,560c
	if(floppyresult() < 2){
print("can't read sense response\n");
		fl.confused = 1;
.
551,555c
	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = Fsense;
	if(floppycmd() < 0)
.
549c
floppysense(void)
.
545,546c
 *  get the interrupt cause from the floppy.
.
535,541c
	end = (ltrack+1)*dp->t->sectors*dp->t->bytes;
	if(off+dp->len > end)
		dp->len = end - off;
.
532c
	 *  can't read across track boundaries.
.
527c
	ltrack = lsec/dp->t->sectors;
	dp->tcyl = ltrack/dp->t->heads;
.
524a
	int track;
.
522a
	int ltrack;
.
517c
 *  truncate dp->length if it crosses a track boundary
.
511c
	fl.nstat = i;
	return i;
.
505,509c
	for(i = 0; i < sizeof(fl.stat); i++){
		for(tries = 0; ; tries++){
			if(tries > 1000){
				fl.confused = 1;
				return -1;
			}
			s = inb(Pmsr)&(Ffrom|Fready);
			if(s == Fready){
				fl.nstat = i;
				return i;
			}
			if(s == (Ffrom|Fready))
				break;
		}
		fl.stat[i] = inb(Pdata);
.
502,503c
	int i, s;
	int tries;
.
500c
floppyresult(void)
.
497c
 *  get a command result from the floppy
 *
 *  when the controller goes ready waiting for a command
 *  (instead of sending results), we're done
 * 
.
493c
	return 0;
.
480,491c
	for(i = 0; i < fl.ncmd; i++){
		for(tries = 0; ; tries++){
			if(tries > 1000){
print("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, inb(Pmsr));
				fl.confused = 1;
				return -1;
			}
			if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
				break;
		}
		outb(Pdata, fl.cmd[i]);
.
478d
476a
	int i;
.
475c
floppycmd(void)
.
472c
 *  send a command to the floppy
.
451,468c
	floppyon(dp);
	floppyoff(dp);
.
448,449c
static void
floppyeject(Drive *dp)
.
446c
 *  eject disk ( unknown on safari )
.
441,442c
	fl.motor &= ~MOTORBIT(dp->dev);
	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
.
439c
floppyoff(Drive *dp)
.
431a

	/* get drive to a known cylinder */
	if(dp->confused)
		for(tries = 0; tries < 4; tries++)
			if(floppyrecal(dp) >= 0)
				break;
.
427,429c
	if(fl.confused)
		floppyrevive();

	/* start motor and select drive */
	alreadyon = fl.motor & MOTORBIT(dp->dev);
	fl.motor |= MOTORBIT(dp->dev);
	outb(Pdor, fl.motor | Fintena | Fena | dp->dev);
.
425a
	int tries;
.
423c
floppyon(Drive *dp)
.
415,420c
 *  start a floppy drive's motor.
.
405,413d
399,401c
		tsleep(&fl.kr, return0, 0, 5*100);
.
395c
					floppyoff(dp);
.
390,391c
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))
.
385c
int i;
static int last;
.
377a

.
374a
	case Qctl:
		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){
			floppyon(dp);
		}
		break;
.
370c
			floppypos(dp, c->offset+rv);
			if(dp->tcyl == dp->ccyl)
				dp->ccyl = -1;
			i = floppyxfer(dp, Fwrite, aa+rv, c->offset+rv,
				n-rv);
.
367,368c
		if(c->offset % dp->t->bytes)
			errors("bad offset");
		if(n % dp->t->bytes)
			errors("bad len");
.
364c
	dp = &fl.d[c->qid.path & ~Qmask];

.
361c
	char *aa = a;
	int dev;
.
355a
#define SNCMP(a, b) strncmp(a, b, sizeof(b)-1)
.
352a

.
349a
	case Qctl:
		break;
.
347c
			memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
.
345a
				dp->chead = head;
.
344a
				}
.
343c
				i = floppyxfer(dp, Fread, dp->cache,
					(cyl*dp->t->heads+head)*nn, nn);
				if(i != nn){
					if(i == 0)
						break;
.
341c
			if(dp->ccyl!=cyl || dp->chead!=head){
.
339c
			 *  read the track
.
336c
			sec = dp->tsec;
.
334a
			head = dp->thead;
.
330c
			 *  truncate xfer at track boundary
.
327c
		aa = a;
		nn = dp->t->tsize;
.
322d
319c
	dp = &fl.d[c->qid.path & ~Qmask];

.
311,313c
	long rv, i;
	int nn, sec, head, cyl;
	long len;
	long noff;
	uchar *aa;
.
291,306d
214,221c
	fl.confused = 1;
.
212c
	 *  first operation will recalibrate
.
208c
		dp->cache = (uchar*)ialloc(dp->t->tsize, 1);
		dp->ccyl = -1;
.
206d
202,203c
	fl.motor = 0;
	delay(10);
	outb(Pdor, fl.motor | Fintena | Fena);
	delay(10);

	/*
	 *  init drives
	 */
	for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++){
		dp->dev = dp - fl.d;
.
197c
	fl.d = ialloc(conf.nfloppy*sizeof(Drive), 0);
.
191a
		t->tsize = t->bytes * t->sectors;
.
184a
	ulong p;
	long l;
.
178d
164c
static int	cmddone(void*);
void Xdelay(int);
.
162c
static long	floppyseek(Drive*, long);
static int	floppysense(void);
static void	floppywait(void);
.
160a
static int	floppyresult(void);
.
158,159d
154,156c
static void	floppyon(Drive*);
static void	floppyoff(Drive*);
.
151,152c
static int	floppycmd(void);
static void	floppyeject(Drive*);
.
144c
Controller	fl;
.
139,140c
	int	motor;		/* bit mask of spinning disks */
.
135,137c
	uchar	cmd[14];	/* command */
	int	ncmd;		  /* # command bytes */
	uchar	stat[14];	/* command status */
	int	nstat;		  /* # status bytes */
	int	confused;	/* controler needs to be reset */
.
128c
 *  controller for 4 floppys
.
123,124c
	Rendez	r;		/* waiting here for motor to spin up */
.
121c
	uchar	*cache;	/* track cache */
	int	ccyl;
	int	chead;
.
114c
	int	confused;	/* needs to be recalibrated */
.
75c
	{ "MF1DD",	512,	9,	2,	1,	80,	0x1B,	0x54, },
	{ "MF4HD",	1024,	18,	2,	1,	80,	0x1B,	0x54, },
.
70a
	long	tsize;		/* track size in bytes */
.
48a

	DMAchan=	2,	/* floppy dma channel */
.
37,38d
34,35c
	/* digital input register */
	Pdir=		0x3F7,	/* disk changed port */
	Fchange=	0x80,	/* disk has changed */
.
26,32c
	/* data register */
	Pdata=		0x3f5,
	Frecal=		0x07,	/* recalibrate cmd */
	Fseek=		0x0f,	/* seek cmd */
	Fsense=		0x08,	/* sense cmd */
	Fread=		0x66,	/* read cmd */
	Freadid=	0x4a,	/* read track id */
	Fspec=		0x03,	/* set hold times */
	Fwrite=		0x45,	/* write cmd */
	Fmulti=		0x80,	/* or'd with Fread or Fwrite for multi-head */
	Fdumpreg=	0x0e,	/* dump internal registers */
.
21,24c
	/* main status register */
	Pmsr=		0x3f4,
	Fready=		0x80,	/* ready to be touched */
	Ffrom=		0x40,	/* data from controller */
	Fbusy=		0x10,	/* operation not over */
.
17,19c
	/* digital output register */
	Pdor=		0x3f2,
	Fintena=	0x8,	/* enable floppy interrupt */
	Fena=		0x4,	/* 0 == reset controller */
.
14a
/* bits in the registers */
.
9c
/* Intel 82077A (8272A compatible) floppy controller */
.
## diffname pc/devfloppy.c 1991/0925
## diff -e /n/bootesdump/1991/0924/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0925/sys/src/9/safari/devfloppy.c
816,817c
static void
floppyintr(Ureg *ur)
.
809,812d
803a
		print("	%d %d %d\n", fl.stat[3], fl.stat[4], fl.stat[5]);
.
786,793c
		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");
.
754c
	cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);
.
742c

.
726,735d
686d
673,674c
		outb(Pdsr, 0);
.
490a
	dp->vers++;
.
481a
	fl.selected = dp;
.
471a
	fl.selected = dp;
.
443c
		tsleep(&fl.kr, return0, 0, 1000);
.
440c
				qunlock(&fl);
.
437c
			&& canqlock(&fl)){
.
430,433d
424,425d
411a
		qunlock(&fl);
.
409a
			fl.confused = 1;
.
400,408d
397a
		qlock(&fl);
.
395a
		qunlock(&fl);
		poperror();
.
383,386c
		islegal(c, n, dp);
		qlock(&fl);
		if(waserror()){
			qunlock(&fl);
			nexterror();
		}
		floppyon(dp);
		changed(c, dp);
.
380d
358a
		qunlock(&fl);
		poperror();

.
330a

		qlock(&fl);
		if(waserror()){
			qunlock(&fl);
			nexterror();
		}
		floppyon(dp);
		changed(c, dp);
.
325,328c
		islegal(c, n, dp);
.
322d
306a
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");
	}
}

.
281c
	devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen);
.
237a
	setvec(Floppyvec, floppyintr);
.
231a
		dp->vers = 1;
.
212a
	fl.selected = fl.d;
.
164a
static void	floppyintr(Ureg*);
.
145a
	Drive	*selected;
.
124a
	int	vers;
.
117,118d
42c
	Pdir=		0x3F7,	/* disk changed port (read only) */
	Pdsr=		0x3F7,	/* data rate select port (write only) */
.
## diffname pc/devfloppy.c 1991/0927
## diff -e /n/bootesdump/1991/0925/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/0927/sys/src/9/safari/devfloppy.c
454a
		} else if(SNCMP(aa, "v") == 0){
			vgaset(aa+1);
.
422a
extern void vgaset(char*);
.
## diffname pc/devfloppy.c 1991/1001
## diff -e /n/bootesdump/1991/0927/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1001/sys/src/9/safari/devfloppy.c
795c
	fl.cmd[fl.ncmd++] = dp->t->sectors;
.
## diffname pc/devfloppy.c 1991/1003
## diff -e /n/bootesdump/1991/1001/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1003/sys/src/9/safari/devfloppy.c
343a
	old = c->qid.vers;
	c->qid.vers = dp->vers;
	if(old && old!=dp->vers)
		errors("disk changed");
.
342d
334,336d
332c
	if(inb(Pdir)&Fchange){
.
## diffname pc/devfloppy.c 1991/1005
## diff -e /n/bootesdump/1991/1003/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1005/sys/src/9/safari/devfloppy.c
636c
/*print("can't read sense response\n");/**/
.
## diffname pc/devfloppy.c 1991/1006
## diff -e /n/bootesdump/1991/1005/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1006/sys/src/9/safari/devfloppy.c
833,834d
758a
floppythrice(Drive *dp, int cmd, void *a, long off, long n)
{
	int tries;
	long rv;

	for(tries = 0; ; tries++){
		if(waserror()){
			if(strcmp(u->error, errstrtab[Eintr])==0 || tries > 3)
				nexterror();
		} else {
			rv = floppyxfer(dp, cmd, a, off, n);
			poperror();
			return rv;
		}
	}
}

static long
.
757a
/*
 *  since floppies are so flakey, try 3 times before giving up
 */
.
456,457d
444a
			if(i == 0)
				error(Eio);
.
443c
			if(i < 0)
.
441c
			i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv,
.
423d
390c
				i = floppythrice(dp, Fread, dp->cache,
.
177a
static long	floppythrice(Drive*, int, void*, long, long);
.
## diffname pc/devfloppy.c 1991/1029
## diff -e /n/bootesdump/1991/1006/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1029/sys/src/9/safari/devfloppy.c
457a
		} else if(SNCMP(aa, "fast") == 0){
			cpuspeed(1);
		} else if(SNCMP(aa, "slow") == 0){
			cpuspeed(0);
.
## diffname pc/devfloppy.c 1991/1112
## diff -e /n/bootesdump/1991/1029/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1112/sys/src/9/safari/devfloppy.c
183,190c
	"fd0disk",		{Qdata + 0},	0,	0666,
	"fd0ctl",		{Qctl + 0},	0,	0666,
	"fd1disk",		{Qdata + 1},	0,	0666,
	"fd1ctl",		{Qctl + 1},	0,	0666,
	"fd2disk",		{Qdata + 2},	0,	0666,
	"fd2ctl",		{Qctl + 2},	0,	0666,
	"fd3disk",		{Qdata + 3},	0,	0666,
	"fd3ctl",		{Qctl + 3},	0,	0666,
.
## diffname pc/devfloppy.c 1991/1203
## diff -e /n/bootesdump/1991/1112/sys/src/9/safari/devfloppy.c /n/bootesdump/1991/1203/sys/src/9/safari/devfloppy.c
287c
	return devopen(c, omode, floppydir, conf.nfloppy*NFDIR, devgen);
.
## diffname pc/devfloppy.c 1992/0111
## diff -e /n/bootesdump/1991/1203/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0111/sys/src/9/safari/devfloppy.c
773c
			if(strcmp(u->error, Eintr)==0 || tries > 3)
.
7c
#include	"../port/error.h"
.
## diffname pc/devfloppy.c 1992/0114
## diff -e /n/bootesdump/1992/0111/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0114/sys/src/9/safari/devfloppy.c
859c
		error(Eio);
.
848c
		error(Eio);
.
841c
		error(Eio);
.
826c
		error(Eio);
.
799c
		error(Eio);
.
396c
					error(Eio);
.
344c
		error(Eio);
.
319c
		error(Ebadarg);
.
317c
		error(Ebadarg);
.
## diffname pc/devfloppy.c 1992/0321
## diff -e /n/bootesdump/1992/0114/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0321/sys/src/9/safari/devfloppy.c
2c
#include	"../port/lib.h"
.
## diffname pc/devfloppy.c 1992/0625
## diff -e /n/bootesdump/1992/0321/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0625/sys/src/9/safari/devfloppy.c
234c
		dp->cache = (uchar*)xspanalloc(dp->t->tsize, BY2PG, 0);
.
215c
	fl.d = xalloc(conf.nfloppy*sizeof(Drive));
.
## diffname pc/devfloppy.c 1992/0711
## diff -e /n/bootesdump/1992/0625/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0711/sys/src/9/safari/devfloppy.c
868a
	USED(ur);
.
787d
668,669d
649a
	USED(a);
.
611,612d
476a
	USED(a);
.
423d
354d
309a
	USED(c, dp);
.
303a
	USED(c);
.
298a
	USED(c);
.
292a
	USED(c, name, omode, perm);
.
199,201d
## diffname pc/devfloppy.c 1992/0829
## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/devfloppy.c /n/bootesdump/1992/0829/sys/src/9/pc/devfloppy.c
835c
/*		print("xfer result failed %lux\n", inb(Pmsr));/**/
.
821c
/*		print("xfer cmd failed\n");/**/
.
## diffname pc/devfloppy.c 1992/0901
## diff -e /n/bootesdump/1992/0829/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/0901/sys/src/9/pc/devfloppy.c
842c
		DPRINT("offset %lud len %d\n", off, dp->len);
.
840c
		DPRINT("xfer failed %lux %lux %lux\n", fl.stat[0],
.
835c
		DPRINT("xfer result failed %lux\n", inb(Pmsr));
.
821c
		DPRINT("xfer cmd failed\n");
.
797,798c
	DPRINT("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
	dp->tcyl, dp->thead, dp->tsec, a, dp->len);
.
750c
		DPRINT("seek failed\n");
.
741c
		DPRINT("seek cmd failed\n");
.
735c
	DPRINT("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead);
.
685c
		DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl);
.
638c
		DPRINT("can't read sense response\n");
.
555c
			DPRINT("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, inb(Pmsr));
.
14a
#define DPRINT if(0)print

.
## diffname pc/devfloppy.c 1992/1002
## diff -e /n/bootesdump/1992/0901/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1002/sys/src/9/pc/devfloppy.c
762c
 *  since floppies are so flakey, automaticly retry failed attempts.
 *  every 3 tries switch to a different density
.
342c
			floppythrice(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize, dp->t->tsize);
.
340c
			floppythrice(dp, Fread, dp->cache, 0, dp->t->tsize);
.
326c
 *  check if the floppy has been replaced under foot.  cause a read error if it has.
.
86,91c
[0]	{ "MF2HD",	512,	18,	2,	1,	80,	0x1B,	0x54,	1, },
[1]	{ "MF1DD",	512,	9,	2,	1,	80,	0x1B,	0x54,	2, },
[2]	{ "MF4HD",	1024,	18,	2,	1,	80,	0x1B,	0x54,	0, },
[3]	{ "F2HD",	512,	15,	2,	1,	80,	0x2A,	0x50,	4, },
[4]	{ "F2DD",	512,	8,	2,	2,	40,	0x2A,	0x50,	5, },
[5]	{ "F1DD",	512,	8,	1,	2,	40,	0x2A,	0x50,	3, },
.
74a
	int	ring;		/* ring of compatible floppy types */
.
## diffname pc/devfloppy.c 1992/1003
## diff -e /n/bootesdump/1992/1002/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1003/sys/src/9/pc/devfloppy.c
857a
		DPRINT("xfer ends on wrong cyl\n");
.
854c
	offset = ((fl.stat[3]+dp->t->steps-1)/dp->t->steps) * dp->t->heads + fl.stat[4];
.
775a

			/* walk through the compatible types */
			if(tries == 3){
				if(++dp->t == &floppytype[NTYPES])
					dp->t = floppytype;
				floppydir[NFDIR*dp->dev].length = dp->t->cap;
				if(dp->t == start)
					nexterror();
				tries = 0;
				floppyon(dp);
			}
.
774c
			if(cmd != Fread || strcmp(u->error, Eintr)==0)
.
771a
	start = dp->t;
.
770a
	Type *start;
.
758,759c
	dp->arm = dp->tcyl*dp->t->steps;
	return dp->tcyl;
.
748a
		DPRINT("seek cmd confused\n");
.
735,736c
	if(dp->arm*dp->t->steps == dp->tcyl)
		return dp->tcyl;
.
722a
		fl.rate = 0;
.
686,688c
	dp->arm = fl.stat[1];
	if(dp->arm != 0){
		DPRINT("recalibrate went to wrong cylinder %d\n", dp->arm);
.
514a
	/* set transfer rate */
	if(fl.rate != dp->t->rate){
		fl.rate = dp->t->rate;
		outb(Pdsr, fl.rate);
	}

.
399c
					len = 0;
					continue;
.
387a
			nn = dp->t->tsize;
.
369d
348a
	}
.
347c
	if(old && old!=dp->vers){
.
343c
			floppythrice(dp, Fread, dp->cache, dp->t->heads*dp->t->tsize,
					dp->t->tsize);
.
340c
		if(dp->arm)
.
233c
		dp->arm = -1;		/* because we don't know */
.
149a
	int	rate;		/* current rate selected */
.
125c
	int	arm;		/* current arm position */
.
87,92c
 { "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, },
.
75c
	int	rate;		/* rate code */
.
63c
 *  floppy types (all MFM encoding)
.
## diffname pc/devfloppy.c 1992/1006
## diff -e /n/bootesdump/1992/1003/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1006/sys/src/9/pc/devfloppy.c
899,901c
	case Fformat:
.
891a
/*
 *  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;
}

.
879c
	offset = fl.stat[3] * dp->t->heads + fl.stat[4];
.
841c
	fl.cmd[fl.ncmd++] = dp->tcyl;
.
793,794c
				while(++dp->t){
					if(dp->t == &floppytype[NTYPES])
						dp->t = floppytype;
					if(dp->dt == Tnone)
						break;
					if(dp->dt == dp->t->dt)
						break;
				}
.
770c
	dp->cyl = dp->tcyl;
.
746c
	if(dp->cyl == dp->tcyl)
.
696,698c
	dp->cyl = fl.stat[1];
	if(dp->cyl != 0){
		DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl);
.
464,467c
		} else if(SNCMP(ctlmsg, "format") == 0){
			if(getfields(ctlmsg, f, 3, ' ') != 3)
				error(Ebadarg);
			rv = n*floppyformat(c, dp, atoi(f[1]), *f[2]);
.
461c
		} else if(SNCMP(ctlmsg, "reset") == 0){
.
459c
		if(n >= sizeof(ctlmsg))
			n = sizeof(ctlmsg) - 1;
		memmove(ctlmsg, aa, n);
		ctlmsg[n] = 0;
		if(SNCMP(ctlmsg, "eject") == 0){
.
447,448c
			i = floppythrice(dp, Fwrite, aa+rv, c->offset+rv, n-rv);
.
429a
	char *f[3];
	char ctlmsg[64];
.
340,341c
		dp->confused = 1;
		floppyon(dp);
		if(dp->cyl)
.
338a
		setdef(dp);
.
240a
	 *  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]);
	}

	/*
.
232,234c
		dp->dt = T1440kb;
		setdef(dp);
		dp->cyl = -1;			/* because we don't know */
.
202a
	uchar equip;
.
197a
/*
 *  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;
		}
}

.
181a
static int	floppyformat(Chan*, Drive*, int, char);
.
125c
	int	cyl;		/* current arm position */
.
121c
	Type	*t;		/* floppy type */
	int	dt;		/* drive type */
.
87,92c
 { "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, },
.
67a
	int	dt;		/* compatible drive type */
.
62a
 *  types of drive (from PC equipment byte)
 */
enum
{
	Tnone=		0,
	T360kb=		1,
	T1200kb=	2,
	T720kb=		3,
	T1440kb=	4,
};

/*
.
39a
	Fformat=	0x4d,	/* format cmd */
.
## diffname pc/devfloppy.c 1992/1007
## diff -e /n/bootesdump/1992/1006/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1007/sys/src/9/pc/devfloppy.c
1027a
	poperror();
.
1026d
974,977c
	if(!waserror()){
		floppyon(dp);
		poperror();
	}
	floppyseek(dp, track*t->tsize);
	dp->cyl = cyl;
	dp->confused = 0;
.
970d
967,968d
965a
	setdef(dp);
.
955c
floppyformat(Drive *dp, ulong track, ulong filler)
.
521a
		poperror();
.
520c
			rv = n*floppyformat(dp, strtoul(f[1], 0, 0), strtoul(f[2], 0, 0));
.
507a
		if(waserror()){
			qunlock(&fl);
			nexterror();
		}
.
463c
		return readstr(offset, a, n, dp->t->name);
.
197c
static int	floppyformat(Drive*, ulong, ulong);
.
## diffname pc/devfloppy.c 1992/1009
## diff -e /n/bootesdump/1992/1007/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1009/sys/src/9/pc/devfloppy.c
1034d
1026,1031d
1018,1024c
		/*
		 *  seek to track, ignore errors
		 */
		if(!waserror()){
			floppyon(dp);
			poperror();
		}
		floppyseek(dp, track*t->tsize);
		dp->cyl = cyl;
		dp->confused = 0;

		/*
		 *  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++] = 0x5a;
		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);
		}
.
1015,1016c
	for(track = 0; track < t->tracks*t->heads; track++){
		cyl = track/t->heads;
		h = track % t->heads;
.
1013c
	 *  format a track at time
.
1000,1009c
	buf = smalloc(t->sectors*4);
	if(waserror()){
		free(buf);
		nexterror();
.
998c
	 *  buffer for per track info
.
995d
988,993c
	if(getfields(params, f, 3, ' ') > 1){
		for(t = floppytype; t < &floppytype[NTYPES]; t++)
			if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){
				dp->t = t;
				floppydir[NFDIR*dp->dev].length = dp->t->cap;
				break;
			}
	} else {
		setdef(dp);
		t = dp->t;
.
986c
	 *  set the type
.
966,984d
964a
	char *f[3];
.
962a
	ulong track;
.
959,960c
static void
floppyformat(Drive *dp, char *params)
.
522,524c
			floppyformat(dp, ctlmsg);
.
506a
		rv = n;
.
497c
			i = floppythrice(dp, Fwrite, aa+rv, offset+rv, n-rv);
.
494c
			floppypos(dp, offset+rv);
.
485c
		islegal(offset, n, dp);
.
478d
473c
floppywrite(Chan *c, void *a, long n, ulong offset)
.
433c
			floppypos(dp, offset+rv);
.
418c
		islegal(offset, n, dp);
.
403c
floppyread(Chan *c, void *a, long n, ulong offset)
.
367c
	if(offset % dp->t->bytes)
.
365c
islegal(ulong offset, long n, Drive *dp)
.
197c
static void	floppyformat(Drive*, char*);
.
7a
#include	"devtab.h"
.
## diffname pc/devfloppy.c 1992/1013
## diff -e /n/bootesdump/1992/1009/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1013/sys/src/9/pc/devfloppy.c
1057a
	dp->confused = 1;
.
1040a
		poperror();
.
1018a
		if(waserror()){
			dmaend(DMAchan);
			nexterror();
		}
.
949a
	poperror();
.
921a
	poperror();
.
894a
	if(waserror()){
		dmaend(DMAchan);
		nexterror();
	}
.
882,884c
	/* retry on error 3 times */
	while(waserror())
		if(tries++ >= 3)
			nexterror();

.
875a
	int tries = 0;
.
836,872d
832,833c
 *  read or write to floppy.  try up to three times.
.
755a
		dp->cyl = -1;
.
497c
			i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv);
.
446c
				i = floppyxfer(dp, Fread, dp->cache,
.
400d
398c
	if(old && old != dp->vers)
.
395a

.
390,394c
		floppyseek(dp, dp->t->heads*dp->t->tsize);
		while(waserror()){
			while(++dp->t){
				if(dp->t == &floppytype[NTYPES])
					dp->t = floppytype;
				if(dp->dt == dp->t->dt)
					break;
			}
			floppydir[NFDIR*dp->dev].length = dp->t->cap;
			if(dp->t == start)
				nexterror();
			floppyon(dp);
		}
		floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize);
		poperror();
.
388c
		setdef(dp);
		start = dp->t;
		dp->confused = 1;	/* make floppyon recal */
.
385,386c
	/*
	 *  if floppy has changed or first time through
	 */
	if((inb(Pdir)&Fchange) || dp->vers == 0){
.
383a
	Type *start;
.
377,378c
 *  a seek and a read clears the condition.  this was determined
 *  experimentally, there has to be a better way.
 *
 *  if the read fails, cycle through the possible floppy
 *  density till one works or we've cycled through all
 *  possibilities.
.
375c
 *  check if the floppy has been replaced under foot.  cause
 *  an error if it has.
.
199d
## diffname pc/devfloppy.c 1992/1016
## diff -e /n/bootesdump/1992/1013/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1016/sys/src/9/pc/devfloppy.c
1047c
			DPRINT("format: failed %lux %lux %lux\n",
.
1042c
			DPRINT("format: confused\n");
.
1029d
1026,1027c
		if(floppycmd() < 0)
.
992,995d
981a
	/* force a recalibrate to cylinder 0 */
	dp->confused = 1;
	if(!waserror()){
		floppyon(dp);
		poperror();
	}

.
936c
		DPRINT("xfer: ends on wrong cyl\n");
.
922c
		DPRINT("xfer: failed %lux %lux %lux\n", fl.stat[0],
.
917c
		DPRINT("xfer: confused\n");
.
904d
900,902c
	if(floppycmd() < 0)
.
874c
	DPRINT("floppyxfer: tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
.
872a
	}
.
871c
	if(floppyseek(dp, off) < 0){
		DPRINT("xfer: seek failed\n");
		dp->confused = 1;
.
868a
	}
.
866c
	tries = 0;
	while(waserror()){
		DPRINT("floppyxfer: retrying\n");
.
858c
	int tries;
.
842c
		DPRINT("seek: failed\n");
.
837c
		DPRINT("seek: confused\n");
.
834d
831,832c
	if(floppycmd() < 0)
.
826c
	DPRINT("seek: tcyl %d, thead %d\n", dp->tcyl, dp->thead);
.
824a
	dp->cyl = -1;
.
774c
		DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl);
.
768a
		DPRINT("recalibrate: failed\n");
.
764a
		DPRINT("recalibrate: confused\n");
.
756a
	dp->cyl = -1;
.
644c
				DPRINT("cmd %ux can't be sent (%d %ux)\n",
					fl.cmd[0], i, inb(Pmsr));
.
640a
	fl.nstat = 0;
.
542a
		} else if(SNCMP(ctlmsg, "debug") == 0){
			floppydebug = 1;
.
410a
			DPRINT("changed: trying %s\n", dp->t->name);
.
16c
#define DPRINT if(floppydebug)print
int floppydebug;
.
## diffname pc/devfloppy.c 1992/1113
## diff -e /n/bootesdump/1992/1016/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1113/sys/src/9/pc/devfloppy.c
269c
		dp->cache = (uchar*)xspanalloc(dp->t->tsize, BY2PG, 64*1024);
.
## diffname pc/devfloppy.c 1992/1120
## diff -e /n/bootesdump/1992/1113/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1120/sys/src/9/pc/devfloppy.c
819c
		fl.rate = -1;
.
772c
		DPRINT("recalibrate: confused %ux\n", inb(Pmsr));
.
648c
			if(tries > 10000){
.
## diffname pc/devfloppy.c 1992/1216
## diff -e /n/bootesdump/1992/1120/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1216/sys/src/9/pc/devfloppy.c
819c
		fl.rate = 0;
DPRINT("floppyrevive: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
.
805a
DPRINT("floppyrevive: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
.
764a
DPRINT("floppyrecal: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
.
753a
	if(!cmddone(0))
		floppyintr(0);
.
411d
408a
			floppyon(dp);
.
394a
DPRINT("changed: msr %ux dir %ux\n", inb(Pmsr), inb(Pdir));
.
## diffname pc/devfloppy.c 1992/1217
## diff -e /n/bootesdump/1992/1216/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1217/sys/src/9/pc/devfloppy.c
893,895d
842d
825c

		DPRINT("floppyrevive out\n");
		fldump();
.
822a
		floppywait();

		/* mark all drives in an unknown state */
		for(dp = fl.d; dp < &fl.d[conf.nfloppy]; dp++)
			dp->confused = 1;

		/* set rate to a known value */
.
821d
818,819d
812a
		fl.ncmd = 1;
.
810c
		DPRINT("floppyrevive in\n");
		fldump();

.
768d
754c
	tsleep(&fl.r, cmddone, 0, 5000);
.
749c
 *  Wait for a floppy interrupt.  If none occurs in 5 seconds, we
 *  may have missed one.  This only happens on some portables which
 *  do power management behind our backs.  Call the interrupt
 *  routine to try to clear any conditions.
.
734a
		fldump();
.
692,693c
	fl.nstat = sizeof(fl.stat);
	return fl.nstat;
.
685c
				return fl.nstat;
.
678a
				DPRINT("floppyresult: %d stats\n", i);
				fldump();
.
676a
		/* wait for status byte */
.
675a
	/* get the result of the operation */
.
649,652c
			if(tries > 1000){
				DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i);
				fldump();

				/* empty fifo, might have been a bad command */
				floppyresult();
.
599a
		/* clear any pending interrupts */
		floppysense();
	}

.
597c
	if(!alreadyon){
		/* wait for drive to spin up */
.
413d
410a
			DPRINT("changed: trying %s\n", dp->t->name);
			fldump();
.
395c
		DPRINT("changed\n");
		fldump();
.
383c
 *  possibilities for this drive.
.
214a
static void
fldump(void)
{
	DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb),
		inb(Pdor), inb(Pmsr), inb(Pdir));
}

.
21a
	/* status registers a & b */
	Psra=		0x3f0,
	Psrb=		0x3f1,

.
16c
#define DPRINT if(floppydebug)kprint
.
## diffname pc/devfloppy.c 1992/1218
## diff -e /n/bootesdump/1992/1217/sys/src/9/pc/devfloppy.c /n/bootesdump/1992/1218/sys/src/9/pc/devfloppy.c
846a
		delay(10);
.
845c
		delay(10);
.
784a
		fl.confused = 1;
	}
.
783c
	if(!cmddone(0)){
.
614a
		setvec(Floppyvec, floppyintr);
.
280c
		dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024);
.
255a
		if(maxtsize < t->tsize)
			maxtsize = t->tsize;
.
251a
	maxtsize = 0;
.
247a
	ulong maxtsize;
.
## diffname pc/devfloppy.c 1993/0219
## diff -e /n/bootesdump/1992/1218/sys/src/9/pc/devfloppy.c /n/bootesdump/1993/0219/sys/src/9/pc/devfloppy.c
619d
## diffname pc/devfloppy.c 1993/0410
## diff -e /n/bootesdump/1993/0219/sys/src/9/pc/devfloppy.c /n/bootesdump/1993/0410/sys/src/9/pc/devfloppy.c
112a
 { "ATT3B1",	T360kb,	 512,  8, 2, 1, 48, 0x2A, 0x50, 2, },
.
## diffname pc/devfloppy.c 1993/0430
## diff -e /n/bootesdump/1993/0410/sys/src/9/pc/devfloppy.c /n/bootesdump/1993/0430/sys/src/9/pc/devfloppy.c
113d
111a
 { "ATT3B1",	T1200kb, 512,  8, 2, 2, 48, 0x2A, 0x50, 1, },
.
## diffname pc/devfloppy.c 1993/0915
## diff -e /n/bootesdump/1993/0430/sys/src/9/pc/devfloppy.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/devfloppy.c
479,496c
			if(readtrack(dp, cyl, head) < 0)
				break;
.
471c
			 *  all xfers come out of the track cache
.
447,448c
	long rv;
	int sec, head, cyl;
.
442a
static int
readtrack(Drive *dp, int cyl, int head)
{
	int i, nn, sofar;
	ulong pos;

	nn = dp->t->tsize;
	if(dp->ccyl==cyl && dp->chead==head)
		return nn;
	pos = (cyl*dp->t->heads+head) * nn;
	for(sofar = 0; sofar < nn; sofar += i){
		dp->ccyl = -1;
		i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar);
		if(i <= 0)
			return -1;
	}
	dp->ccyl = cyl;
	dp->chead = head;
	return nn;
}

.
## diffname pc/devfloppy.c 1993/1124
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/devfloppy.c
1124c
	USED(ur, arg);
.
1122c
floppyintr(Ureg *ur, void *arg)
.
794c
		floppyintr(0, 0);
.
307c
	setvec(Floppyvec, floppyintr, 0);
.
192c
static void	floppyintr(Ureg*, void*);
.
## diffname pc/devfloppy.c 1994/1017
## diff -e /n/fornaxdump/1993/1124/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1994/1017/sys/src/brazil/pc/devfloppy.c
377,378c
	Dirtab *dt;
	Dir d;

	if(!iseve())
		error(Eperm);
	if(CHDIR & c->qid.path)
		error(Eperm);

	convM2D(dp, &d);
	d.mode &= 0x666;
	dt = &floppydir[2 * (c->qid.path & ~Qmask)];
	dt[0].perm = dt[1].perm = d.mode;
.
209,216c
	"fd0disk",		{Qdata + 0},	0,	0660,
	"fd0ctl",		{Qctl + 0},	0,	0660,
	"fd1disk",		{Qdata + 1},	0,	0660,
	"fd1ctl",		{Qctl + 1},	0,	0660,
	"fd2disk",		{Qdata + 2},	0,	0660,
	"fd2ctl",		{Qctl + 2},	0,	0660,
	"fd3disk",		{Qdata + 3},	0,	0660,
	"fd3ctl",		{Qctl + 3},	0,	0660,
.
## diffname pc/devfloppy.c 1995/0105
## diff -e /n/fornaxdump/1994/1017/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0105/sys/src/brazil/pc/devfloppy.c
16c
#define DPRINT if(floppydebug)print
.
## diffname pc/devfloppy.c 1995/0108
## diff -e /n/fornaxdump/1995/0105/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devfloppy.c
589a
}

long
floppybwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
.
526a
Block*
floppybread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

.
## diffname pc/devfloppy.c 1995/0117
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0117/sys/src/brazil/pc/devfloppy.c
1045c
	if(getfields(params, f, 3, " ") > 1){
.
## diffname pc/devfloppy.c 1995/0218
## diff -e /n/fornaxdump/1995/0117/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0218/sys/src/brazil/pc/devfloppy.c
1051a
		}
		if(t >= &floppytype[NTYPES])
			error(Ebadarg);
.
1046c
		for(t = floppytype; t < &floppytype[NTYPES]; t++){
.
240a
	}
.
239c
			return;
.
235c
	for(t = floppytype; t < &floppytype[NTYPES]; t++){
.
## diffname pc/devfloppy.c 1995/0726
## diff -e /n/fornaxdump/1995/0218/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devfloppy.c
358d
356c
floppycreate(Chan*, char*, int, ulong)
.
## diffname pc/devfloppy.c 1995/0728
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0728/sys/src/brazil/pc/devfloppy.c
978c
	fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0);
.
976c
	cmd = cmd;
.
953c
		if(tries++ > 20)
.
949c
	/* retry on error */
.
## diffname pc/devfloppy.c 1995/0818
## diff -e /n/fornaxdump/1995/0728/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/0818/sys/src/brazil/pc/devfloppy.c
1009c
		if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun)
			DPRINT("DMA overrun: retry\n");
		else
			dp->confused = 1;
.
59a
	/* status 1 byte */
	Overrun=	0x10,

.
58a
	Cmdexec=	1<<6,
.
## diffname pc/devfloppy.c 1995/1121
## diff -e /n/fornaxdump/1995/0818/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1995/1121/sys/src/brazil/pc/devfloppy.c
866c
static void
.
## diffname pc/devfloppy.c 1996/0223
## diff -e /n/fornaxdump/1995/1121/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1996/0223/sys/src/brazil/pc/devfloppy.c
8d
## diffname pc/devfloppy.c 1996/0315
## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/pc/devfloppy.c /n/fornaxdump/1996/0315/sys/src/brazil/pc/devfloppy.c
1051c
	if(parsefields(params, f, 3, " ") > 1){
.
## diffname pc/devfloppy.c 1997/0327
## diff -e /n/fornaxdump/1996/0315/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0327/sys/src/brazil/pc/devfloppy.c
1170a

Dev floppydevtab = {
	floppyreset,
	devinit,
	floppyattach,
	devclone,
	floppywalk,
	floppystat,
	floppyopen,
	devcreate,
	floppyclose,
	floppyread,
	devbread,
	floppywrite,
	devbwrite,
	devremove,
	devwstat,
};
.
1159a
	case Fdumpreg: 
.
1155c
	USED(ur);
.
1153c
floppyintr(Ureg *ur)
.
1124a
		/* Poll ready bits and transfer data */
		floppyexec((char *)buf, bp-buf, 0);

.
1062c
		floppysetdef(dp);
.
1059c
		if(t >= &floppytype[nelem(floppytype)])
.
1052c
		for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
.
1045c
	FType *t;
.
1040c
floppyformat(FDrive *dp, char *params)
.
1014c
		} else
.
1012c
		if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){
.
992a
	/* Poll ready bits and transfer data */
	floppyexec((char*)a, dp->len, cmd==Fread);

.
979d
957a
		DPRINT("floppyxfer: retrying\n");
		/*floppyon(dp);*/
.
955d
952c
	/* retry on error (until it gets ridiculous) */
.
942c
floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
.
909c
floppyseek(FDrive *dp, long off)
.
891c
		for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++)
.
868c
	FDrive *dp;
.
828c
floppyrecal(FDrive *dp)
.
819c
		floppyintr(0);
.
761c
floppypos(FDrive *dp, long off)
.
749c
		fl.stat[i] = inb(Pfdata);
.
747a
			if(tries > 1000){
				DPRINT("floppyresult: %d stats\n", i);
				fldump();
				fl.confused = 1;
				return -1;
			}
			microdelay(8);	/* for machine independence */
.
735,740d
713c
		outb(Pfdata, fl.cmd[i]);
.
710,711c
			microdelay(8);	/* for machine independence */
.
701a
			if((inb(Pmsr)&(Ffrom|Fready)) == Fready)
				break;
.
680,690d
676d
672c
floppyoff(FDrive *dp)
.
633c
floppyon(FDrive *dp)
.
616c
		for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
.
610c
	FDrive *dp;
.
601,606d
590c
		} else
			error(Ebadctl);
.
540c
	FDrive *dp;
.
537c
static long
.
530,535d
487c
		return devdirread(c, a, n, floppydir, fl.ndrive*NFDIR, devgen);
.
480c
	FDrive *dp;
.
477c
static long
.
457c
readtrack(FDrive *dp, int cyl, int head)
.
434c
				if(dp->t == &floppytype[nelem(floppytype)])
.
427c
		floppysetdef(dp);
.
418c
	FType *start;
.
415c
changed(Chan *c, FDrive *dp)
.
395c
islegal(ulong offset, long n, FDrive *dp)
.
370,393d
358,364c
static void
.
355c
	return devopen(c, omode, floppydir, fl.ndrive*NFDIR, devgen);
.
352c
static Chan*
.
349c
	devstat(c, dp, floppydir, fl.ndrive*NFDIR, devgen);
.
346c
static void
.
343c
	return devwalk(c, name, floppydir, fl.ndrive*NFDIR, devgen);
.
334,340c
static int
.
319c
static Chan*
.
314,316c
	floppysetup1(&fl);
.
311,312d
295,307d
287c
		floppysetdef(dp);
.
284c
	for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){
.
270c
	fl.d = xalloc(fl.ndrive*sizeof(FDrive));
.
259c
	for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){
.
253a
	
	floppysetup0(&fl);
.
250,252c
	FDrive *dp;
	FType *t;
.
247c
static void
.
244d
242c
			break;
.
238c
	for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++)
.
236c
	FType *t;
.
234c
floppysetdef(FDrive *dp)
.
212,219c
	"fd0disk",		{Qdata + 0},	0,	0666,
	"fd0ctl",		{Qctl + 0},	0,	0666,
	"fd1disk",		{Qdata + 1},	0,	0666,
	"fd1ctl",		{Qctl + 1},	0,	0666,
	"fd2disk",		{Qdata + 2},	0,	0666,
	"fd2ctl",		{Qctl + 2},	0,	0666,
	"fd3disk",		{Qdata + 3},	0,	0666,
	"fd3ctl",		{Qctl + 3},	0,	0666,
.
206,209c
static long	floppyxfer(FDrive*, int, void*, long, long);
.
203c
static long	floppyseek(FDrive*, long);
.
197,200c
static void	floppypos(FDrive*,long);
static int	floppyrecal(FDrive*);
.
193,195c
static int	cmddone(void*);
static void	floppyformat(FDrive*, char*);
.
149,187d
140,147c
FController	fl;
.
118d
89,109d
84,87c
FType floppytype[] =
.
71a
#define DPRINT if(floppydebug)iprint
int floppydebug;

.
64c
	Qdir=		0, 
.
15,62c
enum {
.
11,13c
/* This module expects the following functions to be defined
 * elsewhere: 
 * 
 * inb()
 * outb()
 * floppyexec()
 * floppyeject() 
 * floppysetup0()
 * floppysetup1()
 * dmasetup()
 * dmaend()
 * 
 * On DMA systems, floppyexec() should be an empty function; 
 * on non-DMA systems, dmaend() should be an empty function; 
 * dmasetup() may enforce maximum transfer sizes. 
 */
.
8a
#include	"floppy.h"

.
## diffname pc/devfloppy.c 1997/0404
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0404/sys/src/brazil/pc/devfloppy.c
933c
		if(dmasetup(DMAchan, buf, bp-buf, 0) < 0)
			error(Eio);
.
795a
	if(dp->len < 0)
		error(Eio);
.
145a

	dmainit(DMAchan);
.
21a
 * dmainit()
.
## diffname pc/devfloppy.c 1997/0408
## diff -e /n/emeliedump/1997/0404/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0408/sys/src/brazil/pc/devfloppy.c
1005a
	'f',
	"floppy",

.
## diffname pc/devfloppy.c 1997/0910
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1997/0910/sys/src/brazil/pc/devfloppy.c
107,114c
	"fd0disk",		{Qdata + 0},	0,	0660,
	"fd0ctl",		{Qctl + 0},	0,	0660,
	"fd1disk",		{Qdata + 1},	0,	0660,
	"fd1ctl",		{Qctl + 1},	0,	0660,
	"fd2disk",		{Qdata + 2},	0,	0660,
	"fd2ctl",		{Qctl + 2},	0,	0660,
	"fd3disk",		{Qdata + 3},	0,	0660,
	"fd3ctl",		{Qctl + 3},	0,	0660,
.
## diffname pc/devfloppy.c 1998/0120
## diff -e /n/emeliedump/1997/0910/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0120/sys/src/brazil/pc/devfloppy.c
188c
		dp->vers = 0;
.
41,42c
#define DPRINT if(floppydebug)print
int floppydebug = 1;
.
## diffname pc/devfloppy.c 1998/0213
## diff -e /n/emeliedump/1998/0120/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0213/sys/src/brazil/pc/devfloppy.c
42c
int floppydebug = 0;
.
## diffname pc/devfloppy.c 1998/0319
## diff -e /n/emeliedump/1998/0213/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0319/sys/src/brazil/pc/devfloppy.c
987d
985c
floppyintr(Ureg *)
.
627d
625c
cmddone(void *)
.
445d
441c
floppykproc(void *)
.
381a
	ulong offset = off;
.
376c
floppywrite(Chan *c, void *a, long n, vlong off)
.
328a
	ulong offset = off;
.
322c
floppyread(Chan *c, void *a, long n, vlong off)
.
235d
233c
floppyclose(Chan *)
.
## diffname pc/devfloppy.c 1998/0825
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1998/0825/sys/src/brazil/pc/devfloppy.c
972c
			DPRINT("format: failed %ux %ux %ux\n",
.
838c
		DPRINT("offset %lud len %ld\n", off, dp->len);
.
836c
		DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0],
.
## diffname pc/devfloppy.c 1999/0403
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1999/0403/sys/src/brazil/pc/devfloppy.c
162a

	dmainit(DMAchan, maxtsize);
.
147,148d
## diffname pc/devfloppy.c 1999/0507
## diff -e /n/emeliedump/1999/0403/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1999/0507/sys/src/brazil/pc/devfloppy.c
685c
 *  reset it and get back to a known state
.
## diffname pc/devfloppy.c 1999/0714
## diff -e /n/emeliedump/1999/0507/sys/src/brazil/pc/devfloppy.c /n/emeliedump/1999/0714/sys/src/brazil/pc/devfloppy.c
202a

	if(fl.ndrive == 0)
		error(Enodev);
.
148a
	if(fl.ndrive == 0)
		return;
.
## diffname pc/devfloppy.c 2000/0308
## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/devfloppy.c /n/emeliedump/2000/0308/sys/src/9/pc/devfloppy.c
883c
	if(getfields(params, f, 3, 1, " ") > 1){
.
## diffname pc/devfloppy.c 2000/0813
## diff -e /n/emeliedump/2000/0308/sys/src/9/pc/devfloppy.c /n/emeliedump/2000/0813/sys/src/9/pc/devfloppy.c
964c
		floppywait(1);
.
828c
	floppywait(0);
.
785d
782c
		if(tries++ >= dp->maxtries)
.
749c
	floppywait(1);
.
715c
		floppywait(0);
.
665c
	floppywait(1);
.
644c
	tsleep(&fl.r, cmddone, 0, slow ? 5000 : 1000);
.
642c
floppywait(int slow)
.
503a

	/* return -1 if this didn't work */
	if(dp->confused)
		return -1;
	return 0;
.
470c
static int
.
295a
		dp->maxtries = 20;
.
293a

		/* if the read succeeds, we've got the density right */
.
288c

			/* floppyon will fail if there's a controller but no drive */
			if(floppyon(dp) < 0)
				error(Eio);

.
280a
			/*
			 *  if first attempt doesn't reset changed bit, there's
			 *  no floppy there
			 */
			if(inb(Pdir)&Fchange)
				nexterror();

.
278c
		if(floppyon(dp) < 0)
			error(Eio);

		/* seek to the first track */
.
276a
		dp->maxtries = 3;	/* limit it when we're probing */

		/* floppyon will fail if there's a controller but no drive */
.
275d
103c
static void	floppywait(int);
.
## diffname pc/devfloppy.c 2001/0527
## diff -e /n/emeliedump/2000/0813/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/0527/sys/src/9/pc/devfloppy.c
1038d
354c
	if(c->qid.type & QTDIR)
.
228c
	return devstat(c, dp, n, floppydir, fl.ndrive*NFDIR, devgen);
.
225,226c
static int
floppystat(Chan *c, uchar *dp, int n)
.
222c
	return devwalk(c, nc, name, nname, floppydir, fl.ndrive*NFDIR, devgen);
.
219,220c
static Walkqid*
floppywalk(Chan *c, Chan *nc, char **name, int nname)
.
106a
	".",		{Qdir, 0, QTDIR},	0,	0550,
.
## diffname pc/devfloppy.c 2001/0716
## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/0716/sys/src/9/pc/devfloppy.c
911c
				floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
.
356c
		return devdirread(c, a, n, floppydir, 1+fl.ndrive*NFDIR, devgen);
.
300c
			floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
.
235c
	return devopen(c, omode, floppydir, 1+fl.ndrive*NFDIR, devgen);
.
229c
	return devstat(c, dp, n, floppydir, 1+fl.ndrive*NFDIR, devgen);
.
223c
	return devwalk(c, nc, name, nname, floppydir, 1+fl.ndrive*NFDIR, devgen);
.
137c
			floppydir[1+NFDIR*dp->dev].length = dp->t->cap;
.
## diffname pc/devfloppy.c 2001/1117
## diff -e /n/emeliedump/2001/0716/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/1117/sys/src/9/pc/devfloppy.c
907c
	if(tokenize(params, f, 3) > 1){
.
## diffname pc/devfloppy.c 2001/1120
## diff -e /n/emeliedump/2001/1117/sys/src/9/pc/devfloppy.c /n/emeliedump/2001/1120/sys/src/9/pc/devfloppy.c
919a
	} else {
		cmderror(cb, "invalid floppy format command");
		SET(t);
.
917c
	} else if(cb->nf == 1){
.
909c
			if(strcmp(cb->f[1], t->name)==0 && t->dt==dp->dt){
.
907c
	if(cb->nf == 2){
.
902d
896c
floppyformat(FDrive *dp, Cmdbuf *cb)
.
457a
		poperror();
		free(cb);
.
454,455c
			break;
		}
.
450,452c
			break;
		case CMdebug:
.
447c
			break;
		case CMformat:
			floppyformat(dp, cb);
			break;
		case CMreset:
.
441,445c
		ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg));
		switch(ct->index){
		case CMeject:
.
435a
		cb = parsecmd(a, n);
		if(waserror()){
			free(cb);
			nexterror();
		}
.
406c
	Cmdbuf *cb;
	Cmdtab *ct;
.
399d
118a
enum
{
	CMdebug,
	CMeject,
	CMformat,
	CMreset,
};

static Cmdtab floppyctlmsg[] =
{
	CMdebug,	"debug",	1,
	CMeject,	"eject",	1,
	CMformat,	"format",	0,
	CMreset,	"reset",	1,
};

.
95c
static void	floppyformat(FDrive*, Cmdbuf*);
.
## diffname pc/devfloppy.c 2002/0109
## diff -e /n/emeliedump/2001/1120/sys/src/9/pc/devfloppy.c /n/emeliedump/2002/0109/sys/src/9/pc/devfloppy.c
1063a
	devshutdown,
.
## diffname pc/devfloppy.c 2003/0325
## diff -e /n/emeliedump/2002/0109/sys/src/9/pc/devfloppy.c /n/emeliedump/2003/0325/sys/src/9/pc/devfloppy.c
475a
			break;
		case CMnodebug:
			floppydebug = 0;
.
129a
	CMnodebug,	"nodebug", 1,
.
121a
	CMnodebug,
.
## diffname pc/devfloppy.c 2003/0407
## diff -e /n/emeliedump/2003/0325/sys/src/9/pc/devfloppy.c /n/emeliedump/2003/0407/sys/src/9/pc/devfloppy.c
534c
		tsleep(&up->sleep, return0, 0, 750);
.
512c
		tsleep(&up->sleep, return0, 0, 1000);
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.