[comp.os.minix] Patches for floppy disk handling

hyc@math.lsa.umich.edu (Howard Chu) (11/27/88)

Enclosed are diffs to allow ST-Minix to use (just about) any floppy disk
format. (82 tracks, 11 sectors, what have you. As long as it uses 512 byte
sectors it's OK. I was going to allow arbitrary sector size at first, but
it didn't seem worthwhile...) The patches should be applied thus:

In
  /usr/src/commands: mkfs.dif - Patched up to create a semi-legal bootblock,
	instead of all zeros. The info I consider necessary, number of
	sectors per disk, and number of sectors per track, are preserved,
	while a couple other fields are twiddled for the benefit of TOS and
	the tos program. (Set sectors per cluster to 0x80, -128, and TOS
	will show 0 bytes available. Set reserved field so tos program will
	recognize it as a minix diskette...)

  /usr/src/kernel: stfloppy.dif - Allocate arrays, with one entry per drive,
	to record number of tracks and sectors per track on the disk in that
	drive. Initialized to 80/9, these values are updated by a new procedure
	do_open (with corresponding new message type DISK_OPEN) which is
	called whenever a floppy disk special device file is opened.

  /usr/src/fs: device.dif, mount.dif, table.dif - Change device dispatch
	table to include flop_open call, which sends a DISK_OPEN message
	to the floppy task. Also make the mount system call open the special
	file  before reading a superblock, so the flop_open will be invoked
	when mounting floppy filesystems.

One other change, which I just now remembered and forgot to include in these
diffs - in /usr/src/h/com.h, add an entry to the disk message types named
DISK_OPEN - I stuck it in as message number 2, just before DISK_READ...

I'm using this system now, and haven't had any troubles yet, so I think
it's pretty stable. Your kernel will be about 1K larger when it boots. Try
it and send me any comments...
  -- Howard

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r--  1 hyc          1094 Nov 26 19:20 device.dif
# -rw-r--r--  1 hyc          2620 Nov 26 19:21 mkfs.dif
# -rw-r--r--  1 hyc           493 Nov 26 19:23 mount.dif
# -rw-r--r--  1 hyc          6705 Nov 26 19:23 stfloppy.dif
# -rw-r--r--  1 hyc          1660 Nov 26 19:23 table.dif
#
echo 'x - device.dif'
if test -f device.dif; then echo 'shar: not overwriting device.dif'; else
sed 's/^X//' << '________This_Is_The_END________' > device.dif
X*** device.c~	Thu Nov 10 21:16:04 1988
X--- device.c	Fri Nov 25 06:10:58 1988
X***************
X*** 11,16 ****
X--- 11,17 ----
X   *   no_call:	 dummy procedure (e.g., used when device need not be opened)
X   *   tty_open:   a tty has been opened
X   *   tty_exit:   a process with pid=pgrp has exited.
X+  *   flop_open:  a floppy disk has been opened
X   */
X  
X  #include "../h/const.h"
X***************
X*** 262,265 ****
X--- 263,281 ----
X    dev_mess.TTY_PGRP = 0;
X    (*dmap[major].dmap_rw)(task, &dev_mess);
X    return(OK);
X+ }
X+ 
X+ /*===========================================================================
X+  *				flop_open
X+  *===========================================================================*/
X+ PUBLIC flop_open(task_nr, mess_ptr)
X+ int task_nr;
X+ message *mess_ptr;
X+ {
X+ /* Tell floppy task to read block 0 of the diskette and configure itself...*/
X+   mess_ptr->m_type = DISK_OPEN;
X+   mess_ptr->DEVICE = (mess_ptr->DEVICE >> MINOR) & BYTE;
X+   mess_ptr->PROC_NR = task_nr;
X+   (*dmap[major].dmap_rw)(task_nr, mess_ptr);
X+   if(mess_ptr->m_type == SUSPEND) suspend(task_nr);
X  }
________This_Is_The_END________
if test `wc -c < device.dif` -ne     1094; then
	echo 'shar: device.dif was damaged during transit (should have been     1094 bytes)'
fi
fi		; : end of overwriting check
echo 'x - mkfs.dif'
if test -f mkfs.dif; then echo 'shar: not overwriting mkfs.dif'; else
sed 's/^X//' << '________This_Is_The_END________' > mkfs.dif
X*** mkfs.c~	Thu Nov 10 21:35:38 1988
X--- mkfs.c	Sat Nov 26 17:44:04 1988
X***************
X*** 69,75 ****
X--- 69,100 ----
X  long lseek();
X  char gwarning[] = {65,46,83,46,84,97,110,101,110,98,97,117,109,10};
X  
X+ /*
X+  * Block 0 of a TOS media	-- from tos.c
X+  *	(media : floppy diskette or hard disk partion)
X+  * Contains media description and boot code
X+  */
X+ struct block0 {
X+ 	char	b0_res0[8];
X+ 	char	b0_serial[3];
X+ 	char	b0_bps[2];
X+ 	char	b0_spc;
X+ 	char	b0_res[2];
X+ 	char	b0_nfats;
X+ 	char	b0_ndirs[2];
X+ 	char	b0_nsects[2];
X+ 	char	b0_media;
X+ 	char	b0_spf[2];
X+ 	char	b0_spt[2];
X+ 	char	b0_nsides[2];
X+ 	char	b0_nhid[2];
X+ 	char	b0_code[0x1e2];
X+ };
X+ struct	block0	block0;
X+ char	buf[BLOCK_SIZE - sizeof(block0)];
X  
X+ /* convert an 88-format short into a 68-format short */
X+ #define	sh88tosh68(ch)	((short)(((ch)[1]<<8)|(ch)[0]))
X  
X  /*================================================================
X   *                    mkfs  -  make filesystem
X***************
X*** 165,176 ****
X      } /* end switch */
X    } /* end while */
X  
X  
X- 
X  #ifdef UNIX
X    if (!donttest) {
X    static short testb[BLOCK_SIZE/sizeof(short)];
X  
X    /* Try writing the last block of partition or diskette. */
X    ls = lseek(fd,  ((long)blocks - 1L) * BLOCK_SIZE, 0);
X    testb[0] = 0x3245;
X--- 190,207 ----
X      } /* end switch */
X    } /* end while */
X  
X+   cache_init();
X+   get_block (0, &block0);		/* get_block routine cheats... */
X+   get_block (0, &block0);
X  
X  #ifdef UNIX
X    if (!donttest) {
X    static short testb[BLOCK_SIZE/sizeof(short)];
X  
X+   i = sh88tosh68(block0.b0_nsects) / 2;
X+   if (blocks > i)
X+ 	pexit("File system is too big for minor device");
X+ 
X    /* Try writing the last block of partition or diskette. */
X    ls = lseek(fd,  ((long)blocks - 1L) * BLOCK_SIZE, 0);
X    testb[0] = 0x3245;
X***************
X*** 192,201 ****
X    }
X  #endif
X  
X    /* make the file-system */
X  
X!   cache_init();
X!   put_block (0, zero);		/* Write a null boot block. */
X  
X    zone_shift = 0;		/* for future use */
X    zones = blocks >> zone_shift;
X--- 223,241 ----
X    }
X  #endif
X  
X+   /* Fix the boot block up.... */
X+ 
X+   block0.b0_res0[0] = block0.b0_res0[1] = 0;
X+   for (i=0; i<6; i++) block0.b0_res0[i+2] = "MINIX "[i];
X+   block0.b0_spc = 0x80;
X+   block0.b0_nfats = 0;
X+   block0.b0_ndirs[0] = block0.b0_ndirs[1] = 0;
X+   block0.b0_spf[0] = block0.b0_spf[1] = 0;
X+   bzero(block0.b0_code, sizeof(block0.b0_code) + sizeof(buf));
X+ 
X    /* make the file-system */
X  
X!   put_block (0, &block0);		/* Write a new boot block. */
X  
X    zone_shift = 0;		/* for future use */
X    zones = blocks >> zone_shift;
________This_Is_The_END________
if test `wc -c < mkfs.dif` -ne     2620; then
	echo 'shar: mkfs.dif was damaged during transit (should have been     2620 bytes)'
fi
fi		; : end of overwriting check
echo 'x - mount.dif'
if test -f mount.dif; then echo 'shar: not overwriting mount.dif'; else
sed 's/^X//' << '________This_Is_The_END________' > mount.dif
X*** mount.c~	Thu Nov 10 21:16:10 1988
X--- mount.c	Fri Nov 25 07:21:42 1988
X***************
X*** 50,55 ****
X--- 50,58 ----
X    if (found) return(EBUSY);	/* already mounted */
X    if (sp == NIL_SUPER) return(ENFILE);	/* no super block available */
X  
X+   /* Touch the device. Updates floppy tables in the kernel... */
X+   if ( (r = dev_open(dev, 0)) != OK)	return(r);
X+ 
X    /* Fill in the super block. */
X    sp->s_dev = dev;		/* rw_super() needs to know which dev */
X    rw_super(sp, READING);
________This_Is_The_END________
if test `wc -c < mount.dif` -ne      493; then
	echo 'shar: mount.dif was damaged during transit (should have been      493 bytes)'
fi
fi		; : end of overwriting check
echo 'x - stfloppy.dif'
if test -f stfloppy.dif; then echo 'shar: not overwriting stfloppy.dif'; else
sed 's/^X//' << '________This_Is_The_END________' > stfloppy.dif
X*** stfloppy.c~	Thu Nov 10 21:19:46 1988
X--- stfloppy.c	Sat Nov 26 18:02:44 1988
X***************
X*** 11,17 ****
X   * |  DISK_READ | device  | proc nr |  bytes  |  offset | buf ptr |
X   * |------------+---------+---------+---------+---------+---------|
X   * | DISK_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
X!  * ----------------------------------------------------------------
X   *
X   * The file contains two entry points:
X   *
X--- 11,19 ----
X   * |  DISK_READ | device  | proc nr |  bytes  |  offset | buf ptr |
X   * |------------+---------+---------+---------+---------+---------|
X   * | DISK_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
X!  * |------------+----------------------------------------------------
X!  * |  DISK_OPEN | device  | proc nr |  <-- this is new
X!  * ----------------------------------
X   *
X   * The file contains two entry points:
X   *
X***************
X*** 54,59 ****
X--- 56,64 ----
X  #define NR_DRIVES	2	/* maximum number of drives */
X  #define NR_TYPES	2	/* number of diskette/drive combinations */
X  #define MAX_ERRORS	10	/* how often to try rd/wt before quitting */
X+ PRIVATE int nr_sec[NR_DRIVES];
X+ PRIVATE int nr_cyl[NR_DRIVES];
X+ PRIVATE int Nr_sec;		/* convenience copy */
X  
X  /* return values of xfer_ok(): */
X  #define X_OK		0
X***************
X*** 103,110 ****
X    dmagrab(FLOPPY, fdcint);
X    dmawdat(FDC_CS, IRUPT, FDC_DELAY);		/* reset controller */
X    dmafree(FLOPPY);
X!   for (drive = 0; drive < NR_DRIVES; drive++)
X  	curcyl[drive] = -1;	/* uncalibrated */
X    while (TRUE) {
X  	receive(ANY, &mess);
X  	ASSERT(mess.m_source >= 0);
X--- 108,118 ----
X    dmagrab(FLOPPY, fdcint);
X    dmawdat(FDC_CS, IRUPT, FDC_DELAY);		/* reset controller */
X    dmafree(FLOPPY);
X!   for (drive = 0; drive < NR_DRIVES; drive++) {
X  	curcyl[drive] = -1;	/* uncalibrated */
X+ 	nr_sec[drive] = NR_SECTORS;
X+ 	nr_cyl[drive] = NR_CYLINDERS;
X+   }
X    while (TRUE) {
X  	receive(ANY, &mess);
X  	ASSERT(mess.m_source >= 0);
X***************
X*** 114,119 ****
X--- 122,128 ----
X  
X  	/* Now carry out the work. */
X  	switch (mess.m_type) {
X+ 	    case DISK_OPEN:	r = do_open(&mess);	break;
X  	    case DISK_READ:
X  	    case DISK_WRITE:	r = do_rdwt(&mess);	break;
X  	    default:		r = EINVAL;		break;
X***************
X*** 128,133 ****
X--- 137,196 ----
X  }
X  
X  
X+ /*===========================================================================
X+  *				do_open
X+  *===========================================================================*/
X+ PRIVATE int do_open(mp)
X+ register message *mp;
X+ {
X+   register d, ret;
X+   register short temp;
X+ /*
X+  * Block 0 of a TOS media	-- from tos.c
X+  *	(media : floppy diskette or hard disk partion)
X+  * Contains media description and boot code
X+  */
X+ struct block0 {
X+ 	unsigned char	b0_res0[8];
X+ 	unsigned char	b0_serial[3];
X+ 	unsigned char	b0_bps[2];
X+ 	unsigned char	b0_spc;
X+ 	unsigned char	b0_res[2];
X+ 	unsigned char	b0_nfats;
X+ 	unsigned char	b0_ndirs[2];
X+ 	unsigned char	b0_nsects[2];
X+ 	unsigned char	b0_media;
X+ 	unsigned char	b0_spf[2];
X+ 	unsigned char	b0_spt[2];
X+ 	unsigned char	b0_nsides[2];
X+ 	unsigned char	b0_nhid[2];
X+ 	unsigned char	b0_code[0x1e2];
X+ };
X+ struct	block0	block0;
X+ 
X+ /* convert an 88-format short into a 68-format short */
X+ #define	sh88tosh68(ch)	((short)(((ch)[1]<<8)|(ch)[0]))
X+ 
X+   mp->m_type = DISK_READ;
X+   mp->COUNT = SECTOR_SIZE;
X+   mp->POSITION = 0L;
X+   mp->ADDRESS = (char *) &block0;
X+ 
X+   ret = do_rdwt(mp);
X+   if (ret != SECTOR_SIZE)
X+ 	return(ret);
X+   d = DRIVE(mp->DEVICE);
X+   temp = sh88tosh68(block0.b0_spt);
X+   if (!temp) {			/* Probably a zeroed bootblok. Should only */
X+ 	nr_sec[d] = NR_SECTORS;	/* happen with older Minix filesystems... */
X+ 	nr_cyl[d] = NR_CYLINDERS;
X+ 	return(0);
X+   }
X+   nr_sec[d] = temp;
X+   nr_cyl[d] = sh88tosh68(block0.b0_nsects) / nr_sec[d];
X+   return(0);
X+ }
X+ 
X  /*===========================================================================*
X   *				do_rdwt					     *
X   *===========================================================================*/
X***************
X*** 137,148 ****
X    register struct proc *rp;
X    register struct xfer *xp;
X    register nbytes;
X    extern phys_bytes umap();
X  
X    xp = &xfer;
X    xp->x_rw = mp->m_type;
X    xp->x_drive = mp->DEVICE;
X!   if (DRIVE(xp->x_drive) >= NR_DRIVES)
X  	return(EIO);
X    if (DTYPE(xp->x_drive) >= NR_TYPES)
X  	return(EIO);
X--- 200,213 ----
X    register struct proc *rp;
X    register struct xfer *xp;
X    register nbytes;
X+   register d;
X    extern phys_bytes umap();
X  
X    xp = &xfer;
X    xp->x_rw = mp->m_type;
X    xp->x_drive = mp->DEVICE;
X!   d = DRIVE(xp->x_drive);
X!   if (d >= NR_DRIVES)
X  	return(EIO);
X    if (DTYPE(xp->x_drive) >= NR_TYPES)
X  	return(EIO);
X***************
X*** 152,157 ****
X--- 217,223 ----
X  	return(EINVAL);
X    if ((nbytes % SECTOR_SIZE) != 0)
X  	return(EINVAL);
X+   Nr_sec = nr_sec[d];
X    xp->x_secnum = (int)(mp->POSITION/SECTOR_SIZE);
X    rp = proc_addr(mp->PROC_NR);
X    xp->x_address = umap(rp, D, (vir_bytes) mp->ADDRESS, (vir_bytes) nbytes);
X***************
X*** 186,199 ****
X    xp = &xfer;
X  
X    d = DTYPE(xp->x_drive);
X!   cylinder = xp->x_secnum / NR_SECTORS;
X    head = cylinder % nr_heads[d];
X    cylinder = cylinder / nr_heads[d];
X-   if (cylinder >= NR_CYLINDERS)
X- 	return(0);
X  
X    d = DRIVE(xp->x_drive);
X  
X    hbit = 0;
X    if (select(d, head) != 0)
X  	hbit = HBIT;	/* motor on, suppress spin up sequence */
X--- 252,266 ----
X    xp = &xfer;
X  
X    d = DTYPE(xp->x_drive);
X!   cylinder = xp->x_secnum / Nr_sec;
X    head = cylinder % nr_heads[d];
X    cylinder = cylinder / nr_heads[d];
X  
X    d = DRIVE(xp->x_drive);
X  
X+   if (cylinder >= nr_cyl[d])
X+ 	return(0);
X+ 
X    hbit = 0;
X    if (select(d, head) != 0)
X  	hbit = HBIT;	/* motor on, suppress spin up sequence */
X***************
X*** 230,242 ****
X  	return(1);
X    }
X  
X    TRACE(printf("fd%d: %s: secnum=%d,cylinder=%d,sector=%d,head=%d\n",
X  	xp->x_drive, xp->x_rw == DISK_READ ? "read" : "write",
X  	xp->x_secnum, cylinder, sector, head));
X- 
X-   /* The drive is now on the proper cylinder.  Read or write 1 block. */
X-   sector = xp->x_secnum % NR_SECTORS;
X-   sector++;	/* start numbering at 1 */
X  
X    dmawdat(FDC_SR, sector, FDC_DELAY);
X    dmaaddr(xp->x_address);	/* DMA address setup */
X--- 297,309 ----
X  	return(1);
X    }
X  
X+   /* The drive is now on the proper cylinder.  Read or write 1 block. */
X+   sector = xp->x_secnum % Nr_sec;
X+   sector++;	/* start numbering at 1 */
X+ 
X    TRACE(printf("fd%d: %s: secnum=%d,cylinder=%d,sector=%d,head=%d\n",
X  	xp->x_drive, xp->x_rw == DISK_READ ? "read" : "write",
X  	xp->x_secnum, cylinder, sector, head));
X  
X    dmawdat(FDC_SR, sector, FDC_DELAY);
X    dmaaddr(xp->x_address);	/* DMA address setup */
________This_Is_The_END________
if test `wc -c < stfloppy.dif` -ne     6705; then
	echo 'shar: stfloppy.dif was damaged during transit (should have been     6705 bytes)'
fi
fi		; : end of overwriting check
echo 'x - table.dif'
if test -f table.dif; then echo 'shar: not overwriting table.dif'; else
sed 's/^X//' << '________This_Is_The_END________' > table.dif
X*** table.c~	Thu Nov 10 21:16:20 1988
X--- table.c	Sun Nov 20 21:15:28 1988
X***************
X*** 107,113 ****
X  };
X  
X  
X! extern rw_dev(), rw_dev2(), tty_open();
X  
X  /* The order of the entries here determines the mapping between major device
X   * numbers and tasks.  The first entry (major device 0) is not used.  The
X--- 107,113 ----
X  };
X  
X  
X! extern rw_dev(), rw_dev2(), tty_open(), flop_open();
X  
X  /* The order of the entries here determines the mapping between major device
X   * numbers and tasks.  The first entry (major device 0) is not used.  The
X***************
X*** 120,126 ****
X      ----       ----------   -----       -------     ------  ----      */
X      0,         0,           0,          0,           /* 0 = not used  */
X      no_call,   rw_dev,      no_call,    MEM,         /* 1 = /dev/mem  */
X!     no_call,   rw_dev,      no_call,    FLOPPY,      /* 2 = /dev/fd0  */
X      no_call,   rw_dev,      no_call,    WINCHESTER,  /* 3 = /dev/hd0  */
X      tty_open,  rw_dev,      no_call,    TTY,         /* 4 = /dev/tty0 */
X      no_call,   rw_dev2,     no_call,    TTY,         /* 5 = /dev/tty  */
X--- 120,126 ----
X      ----       ----------   -----       -------     ------  ----      */
X      0,         0,           0,          0,           /* 0 = not used  */
X      no_call,   rw_dev,      no_call,    MEM,         /* 1 = /dev/mem  */
X!     flop_open, rw_dev,      no_call,    FLOPPY,      /* 2 = /dev/fd0  */
X      no_call,   rw_dev,      no_call,    WINCHESTER,  /* 3 = /dev/hd0  */
X      tty_open,  rw_dev,      no_call,    TTY,         /* 4 = /dev/tty0 */
X      no_call,   rw_dev2,     no_call,    TTY,         /* 5 = /dev/tty  */
________This_Is_The_END________
if test `wc -c < table.dif` -ne     1660; then
	echo 'shar: table.dif was damaged during transit (should have been     1660 bytes)'
fi
fi		; : end of overwriting check
exit 0
--
  /
 /_ , ,_.                      Howard Chu
/ /(_/(__                University of Michigan
    /           Computing Center          College of LS&A
   '              Unix Project          Information Systems