Subject: Some more fd.c patches
To: None <amiga-dev@sun-lamp.cs.berkeley.edu>
From: Michael L. Hitch <osymh@gemini.oscs.montana.edu>
List: amiga-dev
Date: 04/21/1994 16:20:24
  Here are some more fd.c patches for anyone playing with the floppy driver.
These include the patches previously posted by Ty Sarna.

  Also included are changes to autoconf.c and swapgeneric.c that should
allow booting using the floppy drive as the root file system.  [The diffs
for autoconf.c doesn't have the correct line numbers, so you may have to
make these changes manually.]

  The patches to fd.c provides the following:

-  Working support for HD drives.

-  The delay() routine uses the DELAY() function instead of a counted
   loop, so delay timing should be CPU-independent.  It works on my
   25Mhz 68040 and 33Mhz 68040 systems.  [The DELAY() routine seems to
   be quite a bit off for large delays, so I have a "fudge-factor"
   multiplier that may need to be tweaked a bit.]

-  Writes seem to work reliably now.  I finally tracked down the problem
   I was having that resulted in bad tracks.  The Fdopen() routine called
   fd_probe every time, and fd_probe called get_drive_id().  Get_drive_id()
   deselects the drive - at times during the middle of the DMA write!  The
   crude fix I've got just skips calling fd_probe() if a drive is currently
   selected.

-  The drive type values are now "inverted" so they match the definitions
   in the AmigaDOS disk resource includes.

-  The driver will retry the track read if an error is detected.

-  When writing to the floppy, if the write begins on the first sector
   of the track and will be writing the entire track, the old data isn't
   read off the disk since it is just going to be overwritten anyway.  This
   allows a "poor man's format" to be done using dd:
	dd if=/dev/zero of=/dev/rfd0 bs=22b count=80
   [for DD disks; bs=44b for HD disks].

-  The side-delay and settle-delay value appear to have been reversed, so
   the entries in the drive_types table have been swapped.

-  The ADKF_MFMPREC flag wasn't being set, which I think is supposed
   to be set for MFM recorded disks.  [hackdisk.device and trackdisk.device
   also set this.]

-  The disk label should report 300rpm for DD drives and 150RPM for HD drives.

Michael


diff -cr /mnt/src/sys/arch/amiga/amiga/autoconf.c /opt/sys/arch/amiga/amiga/autoconf.c
*** /mnt/src/sys/arch/amiga/amiga/autoconf.c	Mon Apr 11 09:52:56 1994
--- /opt/sys/arch/amiga/amiga/autoconf.c	Sun Apr 10 19:10:55 1994
***************
*** 971,977 ****
  static	char devname[][2] = {
  	0,0,		/* 0 = ct */
  	0,0,		/* 1 = xx */
! 	'r','d',	/* 2 = rd */
  	0,0,		/* 3 = sw */
  	's','d',	/* 4 = sd */
  };
--- 1008,1014 ----
  static	char devname[][2] = {
  	0,0,		/* 0 = ct */
  	0,0,		/* 1 = xx */
! 	'f','d',	/* 2 = fd */
  	0,0,		/* 3 = sw */
  	's','d',	/* 4 = sd */
  };
diff -cr /mnt/src/sys/arch/amiga/amiga/swapgeneric.c /opt/sys/arch/amiga/amiga/swapgeneric.c
*** /mnt/src/sys/arch/amiga/amiga/swapgeneric.c	Mon Feb 28 10:55:35 1994
--- /opt/sys/arch/amiga/amiga/swapgeneric.c	Sun Apr 10 19:07:36 1994
***************
*** 58,64 ****
  };
  int	dmmin, dmmax, dmtext;
  
! /*extern	struct driver rddriver;*/
  extern	struct driver sddriver;
  extern struct amiga_ctlr amiga_cinit[];
  extern struct amiga_device amiga_dinit[];
--- 58,64 ----
  };
  int	dmmin, dmmax, dmtext;
  
! extern	struct driver fddriver;
  extern	struct driver sddriver;
  extern struct amiga_ctlr amiga_cinit[];
  extern struct amiga_device amiga_dinit[];
***************
*** 68,74 ****
  	char	*gc_name;
  	dev_t	gc_root;
  } genericconf[] = {
! /*	{ (caddr_t)&rddriver,	"rd",	makedev(2, 0),	},*/
  	{ (caddr_t)&sddriver,	"sd",	makedev(4, 0),	},
  	{ 0 },
  };
--- 68,74 ----
  	char	*gc_name;
  	dev_t	gc_root;
  } genericconf[] = {
! 	{ (caddr_t)&fddriver,	"fd",	makedev(2, 0),	},
  	{ (caddr_t)&sddriver,	"sd",	makedev(4, 0),	},
  	{ 0 },
  };
diff -cr /mnt/src/sys/arch/amiga/dev/fd.c /opt/sys/arch/amiga/dev/fd.c
*** /mnt/src/sys/arch/amiga/dev/fd.c	Fri Apr  8 10:12:49 1994
--- /opt/sys/arch/amiga/dev/fd.c	Wed Apr 20 22:45:56 1994
***************
*** 109,117 ****
  #define DSKLEN_WRITE    (1<<14)
  
  /* drive type values */
! #define FD_NONE		0x00000000
! #define FD_DD_3		0xffffffff	/* double-density 3.5" (880K) */
! #define FD_HD_3		0x55555555	/* high-density 3.5" (1760K) */
  
  struct fd_type {
  	int id;
--- 109,118 ----
  #define DSKLEN_WRITE    (1<<14)
  
  /* drive type values */
! #define FD_NONE		0xffffffff
! #define FD_DD_3		0x00000000	/* double-density 3.5" (880K) */
! #define FD_HD_3		0xaaaaaaaa	/* high-density 3.5" (1760K) */
! #define	FD_DD_5		0x55555555	/* double-density 5.25" (440K) */
  
  struct fd_type {
  	int id;
***************
*** 120,125 ****
--- 121,127 ----
  	int heads;
  	int read_size;
  	int write_size;
+ 	int gap_size;
  	int sect_mult;
  	int precomp1;
  	int precomp2;
***************
*** 129,137 ****
  };
  
  struct fd_type drive_types[] = {
! /*	    id       name      tr he  rdsz   wrsz  sm pc1  pc2 sd  st st  */
! 	{ FD_DD_3, "DD 3.5", 80, 2, 14716, 13630, 1, 80, 161, 3, 18, 1 },
! 	{ FD_HD_3, "HD 3.5", 80, 2, 29432, 27260, 2, 80, 161, 3, 18, 1 },
  	{ FD_NONE, "No Drive", 0, }
  };
  int num_dr_types = sizeof(drive_types) / sizeof(drive_types[0]);
--- 131,140 ----
  };
  
  struct fd_type drive_types[] = {
! /*	    id       name      tr he  rdsz   wrsz   gap sm pc1  pc2 sd  st st  */
! 	{ FD_DD_3, "DD 3.5\"", 80, 2, 14716, 13630, 414, 1, 80, 161, 3, 2, 18 },
! 	{ FD_HD_3, "HD 3.5\"", 80, 2, 29432, 27260, 828, 2, 80, 161, 3, 2, 18 },
! 	{ FD_DD_5, "DD 5.25\"",40, 2, 14716, 13630, 414, 1, 40,  80, 3, 2, 18 },
  	{ FD_NONE, "No Drive", 0, }
  };
  int num_dr_types = sizeof(drive_types) / sizeof(drive_types[0]);
***************
*** 313,321 ****
  	long cnt, inner;
  	int val;
  
! 	for (cnt = 0; cnt < delay_ms; cnt++)
! 		for (inner = 0; inner < 500; inner++)
! 			val += inner * cnt;
  	return(val);
  }
  
--- 316,322 ----
  	long cnt, inner;
  	int val;
  
! 	DELAY (delay_ms * 1000 * 25);	/* NOTE:  DELAY seems to run too fast */
  	return(val);
  }
  
***************
*** 336,345 ****
  	fdu_t fdu;
  {
  	int i;
- 	int cnt;		/* XXXX not used? */
  
- 	cnt = 0;		/* XXXX not used? */
- 
  	/* deselect all drives */
  	for (i = 0; i < DRVS_PER_CTLR; i++)
  		DESELECT(SELMASK(i));
--- 337,343 ----
***************
*** 459,464 ****
--- 457,464 ----
  
  	/* set known values */
  	fd->cyl = 0;
+ 
+ 	delay (fd->ft->settle_time);
  }
  
  /*
***************
*** 472,478 ****
  {
  	int cyl, side;
  	int dir, cnt;
- 	int delay_time;
  
  	cyl = track >> 1;
  	side = (track % 2) ^ 1;
--- 472,477 ----
***************
*** 494,504 ****
  
  	if (cnt) {
  		while (cnt) {
- 			delay_time = fd->ft->step_delay;
- 			if (dir != fd->dir)
- 				delay_time += fd->ft->settle_time;
  			fd_step();
! 			delay(delay_time);
  			--cnt;
  		}
  		delay(fd->ft->settle_time);
--- 493,500 ----
  
  	if (cnt) {
  		while (cnt) {
  			fd_step();
! 			delay(fd->ft->step_delay);
  			--cnt;
  		}
  		delay(fd->ft->settle_time);
***************
*** 605,615 ****
  	track = fd->buf_track;
  
  	/* gap space */
! 	for (cnt = 0; cnt < 414; cnt++)
  		*raw++ = 0xaaaaaaaa;
  
  	/* sectors */
! 	for (cnt = 0; cnt < 11; cnt++) {
  		*raw = 0xaaaaaaaa;
  		correct(raw);
  		++raw;
--- 601,611 ----
  	track = fd->buf_track;
  
  	/* gap space */
! 	for (cnt = fd->ft->gap_size; cnt; cnt--)
  		*raw++ = 0xaaaaaaaa;
  
  	/* sectors */
! 	for (cnt = 0; cnt < fd->sects; cnt++) {
  		*raw = 0xaaaaaaaa;
  		correct(raw);
  		++raw;
***************
*** 616,622 ****
  
  		*raw++ = 0x44894489;
  
! 		format = 0xff000000 | (track << 16) | (cnt << 8) | (11 - cnt);
  		csum = encode_long(format,raw);
  		raw += 2;
  
--- 612,618 ----
  
  		*raw++ = 0x44894489;
  
! 		format = 0xff000000 | (track << 16) | (cnt << 8) | (fd->sects - cnt);
  		csum = encode_long(format,raw);
  		raw += 2;
  
***************
*** 628,635 ****
--- 624,635 ----
  		csum = 0;
  		encode_block(raw+2, data + cnt * 512, 512, &csum);
  		csum = encode_long(csum, raw);
+ 		correct (raw+2);
  		raw += 256 + 2;
  	}
+ 	*raw = 0xaaa80000;
+ 	correct(raw);
+ 
  }
  
  #define get_word(raw) (*(u_short *)(raw))
***************
*** 646,652 ****
  
  /*
   * scan_sync - looks for the next start of sector marked by a sync. When
!  *	sector = 10, can't be certain of a starting sync.
   */
  u_long
  scan_sync(raw, end, sect)
--- 646,652 ----
  
  /*
   * scan_sync - looks for the next start of sector marked by a sync. When
!  *	sect != 0, can't be certain of a starting sync.
   */
  u_long
  scan_sync(raw, end, sect)
***************
*** 655,661 ****
  {
  	u_short data;
  
! 	if (sect != 10) {
  		while (raw < end) {
  			data = get_word(raw);
  			if (data == 0x4489)
--- 655,661 ----
  {
  	u_short data;
  
! 	if (sect == 0) {
  		while (raw < end) {
  			data = get_word(raw);
  			if (data == 0x4489)
***************
*** 696,702 ****
  	end = raw + fd->ft->read_size;
  
  	for (scnt = fd->sects-1; scnt >= 0; scnt--) {
! 		if ((raw = scan_sync(raw, end, scnt)) == 0) {
  			/* XXXX */
  			printf("can't find sync for sector %d\n", scnt);
  			return(1);
--- 696,702 ----
  	end = raw + fd->ft->read_size;
  
  	for (scnt = fd->sects-1; scnt >= 0; scnt--) {
! 		if ((raw = scan_sync(raw, end, scnt == fd->sects-1)) == 0) {
  			/* XXXX */
  			printf("can't find sync for sector %d\n", scnt);
  			return(1);
***************
*** 774,780 ****
  
  		if (data_csum != csum) {
  			printf(
! 			    "MFM_DATA: f=%d t=%d s=%d sn=%d sc=%d %ld, %ld\n", 
  			    format, tnum, sect, snext, scnt, data_csum, csum);
  			return(MFM_DATA);
  		}
--- 774,780 ----
  
  		if (data_csum != csum) {
  			printf(
! 			    "MFM_DATA: f=%d t=%d s=%d sn=%d sc=%d %lx, %lx\n", 
  			    format, tnum, sect, snext, scnt, data_csum, csum);
  			return(MFM_DATA);
  		}
***************
*** 791,807 ****
  	int unit;
  {
  	u_long id;
! 	int i;
  
  	id = 0;
  
  	/* loop and read disk ID */
! 	for (i = 0; i < 32; i++) {
  		SELECT(SELMASK(unit));
  
  		/* read and store value of DSKRDY */
! 		id <<= 1;		/* XXXX 0 << 1? */
! 		id |= (ciaa.pra & CIAA_PRA_RDY) ? 0 : 1;
  
  		DESELECT(SELMASK(unit));
  	}
--- 791,807 ----
  	int unit;
  {
  	u_long id;
! 	u_long id_bit;
  
  	id = 0;
  
  	/* loop and read disk ID */
! 	for (id_bit = 0x80000000; id_bit; id_bit >>= 1) {
  		SELECT(SELMASK(unit));
  
  		/* read and store value of DSKRDY */
! 		if (ciaa.pra & CIAA_PRA_RDY)
! 			id |= id_bit;
  
  		DESELECT(SELMASK(unit));
  	}
***************
*** 811,818 ****
  get_drive_id(unit)
  	int unit;
  {
! 	int i, t;
! 	u_long id;
  	u_char mask1, mask2;
  	volatile u_char *a_ptr;
  	volatile u_char *b_ptr;
--- 811,818 ----
  get_drive_id(unit)
  	int unit;
  {
! 	int t;
! 	u_long id, id_bit;
  	u_char mask1, mask2;
  	volatile u_char *a_ptr;
  	volatile u_char *b_ptr;
***************
*** 830,839 ****
  	*b_ptr &= mask1;
  	*b_ptr |= mask2;
  
! 	for (i = 0; i < 32; i++) {
  		*b_ptr &= mask1;
! 		t = (*a_ptr) & CIAA_PRA_RDY;
! 		id = (id << 1) | (t ? 0 : 1);
  		*b_ptr |= mask2;
  	}
  
--- 830,839 ----
  	*b_ptr &= mask1;
  	*b_ptr |= mask2;
  
! 	for (id_bit = 0x80000000; id_bit;  id_bit >>= 1) {
  		*b_ptr &= mask1;
! 		if ((*a_ptr) & CIAA_PRA_RDY)
! 			id |= id_bit;
  		*b_ptr |= mask2;
  	}
  
***************
*** 877,882 ****
--- 877,887 ----
  	id = get_drive_id(fd->fdu);
  	type = get_drive_type(id);
  
+ 	/* get_drive_id shuts off the motor */
+ 	/* XXXX fdc_data[0] only as long as there is one controller */
+ 	if (fd->fdu == fdc_data[0].motor_fdu)
+ 		fdc_data[0].motor_fdu = -1;
+ 
  	if (type == -1) {
  		/* XXXX */
  		printf("fd_probe: unsupported drive type %08x found\n", id);
***************
*** 910,916 ****
  
  	fd->buf_track = track;
  	fdc->state = WAIT_READ;
- 	timeout((timeout_t)fd_timeout, (caddr_t)fdc, 2 * hz);
  
  	fd_seek(fd, track);
  
--- 915,920 ----
***************
*** 924,929 ****
--- 928,934 ----
  
  	custom.dsklen = 0;
  	delay(fd->ft->side_time);
+ 	timeout((timeout_t)fd_timeout, (caddr_t)fdc, 2 * hz);
  
  	custom.dskpt = (u_char *)kvtop(raw_buf);
  	custom.dsklen = len | DSKLEN_DMAEN;
***************
*** 946,952 ****
  
  	fdc->saved = fdc->state;
  	fdc->state = WAIT_WRITE;
- 	timeout((timeout_t)fd_timeout, (caddr_t)fdc, 2 * hz);
  
  	fd_seek(fd, track);
  
--- 951,956 ----
***************
*** 960,966 ****
  	    ADKF_MSBSYNC;
  
  	/* set appropriate adkcon bits */
! 	adk = ADKF_SETCLR | ADKF_FAST;
  	if (track >= fd->ft->precomp2)
  		adk |= ADKF_PRECOMP1;
  	else if (track >= fd->ft->precomp1)
--- 964,970 ----
  	    ADKF_MSBSYNC;
  
  	/* set appropriate adkcon bits */
! 	adk = ADKF_SETCLR | ADKF_FAST | ADKF_MFMPREC;
  	if (track >= fd->ft->precomp2)
  		adk |= ADKF_PRECOMP1;
  	else if (track >= fd->ft->precomp1)
***************
*** 969,974 ****
--- 973,979 ----
  
  	custom.dsklen = DSKLEN_WRITE;
  	delay(fd->ft->side_time);
+ 	timeout((timeout_t)fd_timeout, (caddr_t)fdc, 2 * hz);
  
  	custom.dskpt = (u_char *)kvtop(raw_buf);	/* XXXX again raw */
  	custom.dsklen = len | DSKLEN_DMAEN | DSKLEN_WRITE;
***************
*** 1057,1063 ****
  	if (fdu >= DRVS_PER_CTLR) 
  		return(ENXIO);
  
! 	fd_probe(fd);
  	if (fd->ft == NULL || fd->ft->tracks == 0)
  		return(ENXIO);
  
--- 1062,1080 ----
  	if (fdu >= DRVS_PER_CTLR) 
  		return(ENXIO);
  
! 	/*
! 	 * XXXX don't probe if device is currently selected
! 	 * it may be in the middle of a DMA transfer and fd_probe
! 	 * will deselect all drives
! 	 */
! 	if (fdc->motor_fdu < 0)
! 		fd_probe(fd);
! #if 0
! 	else
! 		printf ("fd: Fdopen called with a drive selected\n");
! #endif
! 
! 
  	if (fd->ft == NULL || fd->ft->tracks == 0)
  		return(ENXIO);
  
***************
*** 1130,1141 ****
  	fd_label->d_magic = DISKMAGIC;
  	fd_label->d_type = DTYPE_FLOPPY;
  	strncpy(fd_label->d_typename, "fd", sizeof(fd_label->d_typename) - 1);
! 	strcpy(fd_label->d_packname, "some pack");
  
  	fd_label->d_secsize = 512;
! 	fd_label->d_nsectors = 11;
! 	fd_label->d_ntracks = 2;
! 	fd_label->d_ncylinders = 80;
  	fd_label->d_secpercyl = fd_label->d_nsectors * fd_label->d_ntracks;
  	fd_label->d_secperunit= fd_label->d_ncylinders * fd_label->d_secpercyl;
  
--- 1147,1159 ----
  	fd_label->d_magic = DISKMAGIC;
  	fd_label->d_type = DTYPE_FLOPPY;
  	strncpy(fd_label->d_typename, "fd", sizeof(fd_label->d_typename) - 1);
! 	strcpy(fd_label->d_packname, fd->ft->name);
  
+ 	fd_label->d_rpm = 300 / fd->ft->sect_mult;
  	fd_label->d_secsize = 512;
! 	fd_label->d_nsectors = fd->sects;
! 	fd_label->d_ntracks = fd->ft->heads;
! 	fd_label->d_ncylinders = fd->ft->tracks;
  	fd_label->d_secpercyl = fd_label->d_nsectors * fd_label->d_ntracks;
  	fd_label->d_secperunit= fd_label->d_ncylinders * fd_label->d_secpercyl;
  
***************
*** 1192,1203 ****
  	blknum = (unsigned long) bp->b_blkno * DEV_BSIZE / FDBLK;
  	nblocks = fd->sects * fd->ft->tracks * fd->ft->heads;
  	if (blknum + (bp->b_bcount / FDBLK) > nblocks) {
! 		/* XXXX */
! 		printf("at end of disk\n");
! 		bp->b_error = ENOSPC;
! 		bp->b_flags |= B_ERROR;
! 		biodone(bp);
! 		return;
  	}
  
  	bp->b_cylin = blknum;	/* set here for disksort */
--- 1210,1228 ----
  	blknum = (unsigned long) bp->b_blkno * DEV_BSIZE / FDBLK;
  	nblocks = fd->sects * fd->ft->tracks * fd->ft->heads;
  	if (blknum + (bp->b_bcount / FDBLK) > nblocks) {
! 		nblocks -= blknum;
! 		if (nblocks == 0) {
! 			bp->b_resid = bp->b_bcount;
! 			goto done;
! 		}
! 		if (nblocks < 0) {
! 			bp->b_error = EINVAL;
! 			bp->b_flags |= B_ERROR;
! done:
! 			biodone(bp);
! 			return;
! 		}
! 		bp->b_bcount = dbtob(nblocks);
  	}
  
  	bp->b_cylin = blknum;	/* set here for disksort */
***************
*** 1255,1265 ****
  	dp = &fd->head;
  	bp = dp->b_actf;
  
  	/* XXXX */
! 	printf("fd%d: Operation timeout\n", fd->fdu);
  	if (bp) {
  		retrier(fdc);
  		fdc->state = DONE_IO;
  		if (fdc->retry < 6)
  			fdc->retry = 6;
  	} else {
--- 1280,1297 ----
  	dp = &fd->head;
  	bp = dp->b_actf;
  
+ 	if (fd == NULL) {
+ 		printf ("fd_timeout called with no active drive?\n");
+ 		return;
+ 	}
+ 
  	/* XXXX */
! 	printf("fd%d: Operation timeout; state %d\n", fd->fdu, fdc->state);
  	if (bp) {
  		retrier(fdc);
+ #if 0	/* XXX retrier already set fdc->state? */
  		fdc->state = DONE_IO;
+ #endif
  		if (fdc->retry < 6)
  			fdc->retry = 6;
  	} else {
***************
*** 1368,1378 ****
  		if (fd->buf_track != track) {
  			TRACE1("do track %d\n", track);
  
! 			if (fd->buf_dirty)
  				track_write(fdc, fd);
! 			else
! 				track_read(fdc, fd, track);
! 			return(0);
  		}
  
  		fdc->state = DO_IO;
--- 1400,1424 ----
  		if (fd->buf_track != track) {
  			TRACE1("do track %d\n", track);
  
! 			if (fd->buf_dirty) {
  				track_write(fdc, fd);
! 				return (0);
! 			} else {
! 				if (read || sec != 0 ||
! 				    ((bp->b_bcount - fd->skip)/FDBLK) % fd->sects) {
! 					track_read(fdc, fd, track);
! 					return(0);
! 				}
! 				/*
! 				 * if writing a full track, don't bother reading
! 				 * in the old track - we're just going to overwrite
! 				 * it all anyway.
! 				 */
! 				fd_seek (fd, track);
! 				fd->buf_track = track;
! 				/* clear sector labels */
! 				bzero(fd->buf_labels, MAX_SECTS * 16);
! 			}
  		}
  
  		fdc->state = DO_IO;
***************
*** 1397,1405 ****
  			fdc->state = DOSEEK;
  		else {
  			fd->skip = 0;
! 			bp->b_resid = 0;
! 			dp->b_actf = bp->b_actf;
! 			biodone(bp);
  			fdc->state = FINDWORK;
  		}
  		return(1);
--- 1443,1455 ----
  			fdc->state = DOSEEK;
  		else {
  			fd->skip = 0;
! 			if (bp == NULL)
! 				printf ("fd: fdstate DONE_IO bp == NULL\n");
! 			else {
! 				bp->b_resid = 0;
! 				dp->b_actf = bp->b_actf;
! 				biodone(bp);
! 			}
  			fdc->state = FINDWORK;
  		}
  		return(1);
***************
*** 1406,1419 ****
  	case WAIT_READ:
  		untimeout((timeout_t)fd_timeout, (caddr_t)fdc);
  		custom.dsklen = 0;
! 		amiga_read(fd);
! 		fdc->state = DO_IO;
! 		return(1);
  	case WAIT_WRITE:
  		untimeout((timeout_t)fd_timeout, (caddr_t)fdc);
  		custom.dsklen = 0;
  		fdc->state = fdc->saved;
  		fd->buf_dirty = 0;
  		return(1);
  	default:
  		/* XXXX */
--- 1456,1490 ----
  	case WAIT_READ:
  		untimeout((timeout_t)fd_timeout, (caddr_t)fdc);
  		custom.dsklen = 0;
! 		if (amiga_read(fd) == 0) {
! 			fdc->retry = 0;
! 			fdc->state = DO_IO;
! 			return(1);
! 		}
! 		if (fdc->retry++ < 6) {
! 			track_read(fdc, fd, track);
! 			return(0);
! 		}
! 		if (bp) {
! 			bp->b_flags |= B_ERROR;
! 			bp->b_error = EIO;
! 			bp->b_resid = bp->b_bcount - fd->skip;
! 			dp->b_actf = bp->b_actf;
! 			fd->skip = 0;
! 			biodone(bp);
! 		}
! 		fdc->state = FINDWORK;
! 		return (1);
  	case WAIT_WRITE:
  		untimeout((timeout_t)fd_timeout, (caddr_t)fdc);
  		custom.dsklen = 0;
  		fdc->state = fdc->saved;
  		fd->buf_dirty = 0;
+ 		/*
+ 		 * post-write delay - should delay only if changing sides
+ 		 * after a write?
+ 		 */
+ 		delay (4);
  		return(1);
  	default:
  		/* XXXX */
***************
*** 1458,1469 ****
  	/* XXXX */
  	printf("fd%d: hard error\n", fd->fdu);
  
! 	bp->b_flags |= B_ERROR;
! 	bp->b_error = EIO;
! 	bp->b_resid = bp->b_bcount - fd->skip;
! 	dp->b_actf = bp->b_actf;
! 	fd->skip = 0;
! 	biodone(bp);
  	fdc->state = FINDWORK;
  	return(1);
  #if 0
--- 1529,1544 ----
  	/* XXXX */
  	printf("fd%d: hard error\n", fd->fdu);
  
! 	if (bp == NULL)
! 		printf ("fd: retrier bp == NULL\n");
! 	else {
! 		bp->b_flags |= B_ERROR;
! 		bp->b_error = EIO;
! 		bp->b_resid = bp->b_bcount - fd->skip;
! 		dp->b_actf = bp->b_actf;
! 		fd->skip = 0;
! 		biodone(bp);
! 	}
  	fdc->state = FINDWORK;
  	return(1);
  #if 0

-- 
Michael L. Hitch			INTERNET:  osymh@montana.edu
Computer Consultant			BITNET:  OSYMH@MTSUNIX1.BITNET
Office of Systems and Computing Services
Montana State University	Bozeman, MT	USA

------------------------------------------------------------------------------