[comp.os.minix] Minix/ST Floppy disk blues

hcj@lzaz.ATT.COM (HC Johnson) (01/08/89)

I just made a major discovery.  My floppy drives (with a disk in them) are
spinning all the time I run Minix.  Properly, until I do a floppy disk
operation in Minix.  This can be days at a time.

The problem is that floppy_task starts by resetting the controller with
the line:
    dmawdat(FDC_CS, IRUPT, FDC_DELAY);		/* reset controller */
This turn ON the motor_on line, and spins all motors even if the drive is
not selected.  In the simplest case, this command is not needed as
the only way to boot Minix is via TOS or to boot a floppy.

I give you here my local version of stfloppy.c.  
It contains 3 changes:
1. a define to do away with the reset controller
2. a define to add a bit to the minor number to indicate 10 spt floppies.
   This is cruder than a previous posting but much simpler.
3. a define to do read after write.  (maybe I wouldn't have needed this if my 
   drives hadn't cooked for weeks).

Howard Johnson
ATT-BL
lzaz!hcj

=======cdiff of kernel/stfloppy=================
*** stfloppy.c	Thu Jan  7 21:53:55 1989
--- /mnt/kernel/stfloppy.c	Thu Oct 29 15:49:46 1988
***************
*** 27,40 ****
   * using DMA the interrupt is signalled to the floppy task.
   */
  
- /* HCJ: I have made three changes to this file.  They are separated
-  * with separate defines.  You may take all or part.
-  */
- 
- #define NO_FLOPPY_INIT	/* dont do init to floppy, it turns the motors on */
- #define RD_AFTER_WT	/* always read after write. off: you'll be sorry */
- #define TWISTER		/* inode specifies 9 and 10 spt */
- 
  #include "../h/const.h"
  #include "../h/type.h"
  #include "../h/callnr.h"
--- 27,32 ----
***************
*** 49,55 ****
  #include "stdma.h"
  #include "stsound.h"
  
- 
  #define	ASSERT(x)	if (!(x)) panic("fd: ASSERT(x) failed",NO_NUM);
  #define TRACE(x)	/* x */
  #define DEBUG(x)	x
--- 41,46 ----
***************
*** 64,73 ****
  #define NR_TYPES	2	/* number of diskette/drive combinations */
  #define MAX_ERRORS	10	/* how often to try rd/wt before quitting */
  
- #ifdef TWISTER
- #define NR_ALT_SECTS	10	/* 10 spt on twisted format */
- #endif
- 
  /* return values of xfer_ok(): */
  #define X_OK		0
  #define X_AGAIN		1
--- 55,60 ----
***************
*** 94,112 ****
  	int	x_count;	/* bytes still to transfer */
  	int	x_errors;	/* errors on current sector */
  	int	x_cmd;		/* controller command */
- #ifdef TWISTER
- 	int	x_spt;		/* sectors per track */
- #endif
  } xfer;
  
  #define	DRIVE(d)	((d) & 0x07)
! #define	DTYPE(d)	(((d) >> 3) & 0x1)
! #ifdef TWISTER
! #define TWIST(d)	(((d) >> 4) & 0x1)
! /*
!  * minor: twisted<<4 | dtype<<3 | partition
!  */
! #endif
  
  FORWARD int	fdcint();
  
--- 81,90 ----
  	int	x_count;	/* bytes still to transfer */
  	int	x_errors;	/* errors on current sector */
  	int	x_cmd;		/* controller command */
  } xfer;
  
  #define	DRIVE(d)	((d) & 0x07)
! #define	DTYPE(d)	(((d) >> 3) & 0x1F)
  
  FORWARD int	fdcint();
  
***************
*** 122,137 ****
     * It waits for a message, carries it out, and sends a reply.
     */
    TRACE(printf("fd: task started\n"));
- #ifndef NO_FLOPPY_INIT
    dmagrab(FLOPPY, fdcint);
    dmawdat(FDC_CS, IRUPT, FDC_DELAY);		/* reset controller */
    dmafree(FLOPPY);
- #endif
- 
- #ifndef RD_AFTER_WT
- #define do_wtrd(x) do_rdwt(x)
- #endif
- 
    for (drive = 0; drive < NR_DRIVES; drive++)
  	curcyl[drive] = -1;	/* uncalibrated */
    while (TRUE) {
--- 100,108 ----
***************
*** 143,150 ****
  
  	/* Now carry out the work. */
  	switch (mess.m_type) {
! 	    case DISK_READ:	r = do_rdwt(&mess);	break;
! 	    case DISK_WRITE:	r = do_wtrd(&mess);	break;
  	    default:		r = EINVAL;		break;
  	}
  
--- 114,121 ----
  
  	/* Now carry out the work. */
  	switch (mess.m_type) {
! 	    case DISK_READ:
! 	    case DISK_WRITE:	r = do_rdwt(&mess);	break;
  	    default:		r = EINVAL;		break;
  	}
  
***************
*** 157,237 ****
  }
  
  
! #ifdef RD_AFTER_WT
! PRIVATE char lbuffer[SECTOR_SIZE * 2];	/* used for read after write */
! 
! /*===========================================================================*
!  *				do_wtrd					     *
!  *===========================================================================*/
! PRIVATE int do_wtrd(mp)
  register message *mp;
  {
    register struct proc *rp;
    register struct xfer *xp;
    register nbytes;
- 
- 	int Device;
- 	int lbytes;
- 	int r,rw;
- 	char * address;
- 	long position;
- 	int xfer_size;
- 	int retry = 5;
- 
- 	lbytes = mp->COUNT;
- 	if ((mp->POSITION % SECTOR_SIZE) != 0)
- 		return(EINVAL);
- 	if ((lbytes % SECTOR_SIZE) != 0)
- 		return(EINVAL);
- 
- 	Device = mp->DEVICE;
- 	position = mp->POSITION;
- 	address = mp->ADDRESS;
- 
- 	xfer_size = (lbytes > SECTOR_SIZE)?sizeof(lbuffer):SECTOR_SIZE;
- 	while(lbytes)  {
- 		if(lbytes < xfer_size)
- 			xfer_size = lbytes;
- 		mp->COUNT = xfer_size;
- /* first time ADDRESS, POSITION, m_type are correct */
- 		if((rw=do_rdwt(mp)) < 0)
- 			return(rw);	/* it failed */
- 		mp->COUNT = xfer_size;
- 		mp->ADDRESS = lbuffer;
- 		mp->POSITION = position;
- 		mp->m_type = DISK_READ;
- 		mp->DEVICE = Device;
- 		if((r=do_rdwt(mp)) < 0) {
- printf("Read after write failed device=%x err cod=%d  sz=%d pos=%ld\n",
-  mp->DEVICE,r,position);
- 			mp->ADDRESS = address;
- 			mp->m_type = DISK_WRITE;
- 			if(--retry)
- 				continue;	/* try again */
- 			return(r);	/* it failed */
- 		}
- 		address += xfer_size;
- 		position += xfer_size;
- 		lbytes -= xfer_size;
- 
- 		mp->ADDRESS = address;
- 		mp->POSITION = position;
- 		mp->m_type = DISK_WRITE;
- 		mp->DEVICE = Device;
- 	}
- 	return(rw);
- }
- #endif
- 
- /*===========================================================================*
-  *				do_rdwt					     *
-  *===========================================================================*/
- PRIVATE int do_rdwt(mp)
- register message *mp;
- {
-   register struct proc *rp;
-   register struct xfer *xp;
-   register nbytes;
    extern phys_bytes umap();
  
    xp = &xfer;
--- 128,142 ----
  }
  
  
! /*===========================================================================*
!  *				do_rdwt					     *
!  *===========================================================================*/
! PRIVATE int do_rdwt(mp)
  register message *mp;
  {
    register struct proc *rp;
    register struct xfer *xp;
    register nbytes;
    extern phys_bytes umap();
  
    xp = &xfer;
***************
*** 241,249 ****
  	return(EIO);
    if (DTYPE(xp->x_drive) >= NR_TYPES)
  	return(EIO);
- #ifdef TWISTER
-   xp->x_spt = TWIST(xp->x_drive)==1?NR_ALT_SECTS:NR_SECTORS;
- #endif
    nbytes = mp->COUNT;
    xp->x_count = nbytes;
    if ((mp->POSITION % SECTOR_SIZE) != 0)
--- 146,151 ----
***************
*** 284,292 ****
    xp = &xfer;
  
    d = DTYPE(xp->x_drive);
! #ifdef TWISTER
!   cylinder = xp->x_secnum / xp->x_spt;
! #endif
    head = cylinder % nr_heads[d];
    cylinder = cylinder / nr_heads[d];
    if (cylinder >= NR_CYLINDERS)
--- 186,192 ----
    xp = &xfer;
  
    d = DTYPE(xp->x_drive);
!   cylinder = xp->x_secnum / NR_SECTORS;
    head = cylinder % nr_heads[d];
    cylinder = cylinder / nr_heads[d];
    if (cylinder >= NR_CYLINDERS)
***************
*** 330,352 ****
  	return(1);
    }
  
- 
- #ifndef TWISTER
    TRACE(printf("fd%d: %s: secnum=%d,cylinder=%d,sector=%d,head=%d\n",
  	xp->x_drive, xp->x_rw == DISK_READ ? "read" : "write",
  	xp->x_secnum, cylinder, sector, head));
    sector = xp->x_secnum % NR_SECTORS;
    sector++;	/* start numbering at 1 */
  
-   /* The drive is now on the proper cylinder.  Read or write 1 block. */
- #else  /* TWISTER */
-   sector = xp->x_secnum % xp->x_spt;
-   sector++;	/* start numbering at 1 */
- 
-   TRACE(printf("fd%d: %s: secnum=%d,cylinder=%d,spt=%d,sector=%d,head=%d\n",
- 	xp->x_drive, xp->x_rw == DISK_READ ? "read" : "write",
- 	xp->x_secnum, cylinder, xp->x_spt, sector, head));
- #endif
    dmawdat(FDC_SR, sector, FDC_DELAY);
    dmaaddr(xp->x_address);	/* DMA address setup */
  
--- 230,243 ----
  	return(1);
    }
  
    TRACE(printf("fd%d: %s: secnum=%d,cylinder=%d,sector=%d,head=%d\n",
  	xp->x_drive, xp->x_rw == DISK_READ ? "read" : "write",
  	xp->x_secnum, cylinder, sector, head));
+ 
+   /* The drive is now on the proper cylinder.  Read or write 1 block. */
    sector = xp->x_secnum % NR_SECTORS;
    sector++;	/* start numbering at 1 */
  
    dmawdat(FDC_SR, sector, FDC_DELAY);
    dmaaddr(xp->x_address);	/* DMA address setup */
  

ast@cs.vu.nl (Andy Tanenbaum) (01/09/89)

In article <357@lzaz.ATT.COM> hcj@lzaz.ATT.COM (HC Johnson) writes:
>I just made a major discovery.  My floppy drives (with a disk in them) are
>spinning all the time I run Minix.  Properly, until I do a floppy disk
>operation in Minix.  This can be days at a time.

Is this also true on the PC?  My machine has a fan that makes so much noise
that I can't tell when the drives are on or off.  The light certainly goes
out, but that doesn't mean anything.

Andy Tanenbaum (ast@cs.vu.nl)