[comp.os.minix] dosdir/dosread/doswrite for 720K and 1.44MB floppies; floppy.c for 1.44MB

crew@pitt.UUCP (Al Crew) (01/13/89)

The following shar output contains two cdiff files.  

The first is used to patch dosread/dosdir/doswrite to support 720K and 1.44MB
floppies.  

The second is used to patch floppy.c to support 1.44MB floppies.  It was
tested on an IBM PS/2 Model 30-286.  Read the file header comments
for details on defining "DEFAULT_CLASS".

Hopefully, the changes should be transparent other users.


PS: As others modify floppy.c to support the PS/2 computers that
	have microchannels and 3.5 inch drives, remember the following:

	1) Not all PS/2 computers have microchannels.

	2) Some PS/2 computers have 5.25 inch drives attached.

	3) Some non-PS/2 computers have 3.5 inch drives.

	4) Some computers have both 5.25 and 3.5 inch drives.

    Please define seperate flags for independent configuration options.

    Perhaps instead of the model flags, we should have more specific flags
    like "floppy_3_5", "microchannel", "pcr", etc. 

--------------------------------cut-----------------------------------------
echo x - dosread.c.cdif
sed '/^X/s///' > dosread.c.cdif << '/'
X*** dosread.c	Thu Jan 12 22:12:26 1989
X--- dosread.c.v1.3	Thu Jan 12 22:12:35 1989
X***************
X*** 25,38 ****
X   *			properly then all the rest should be okay.
X   *		If there are any problems there is debugging information
X   *		  in fdinit() -- please let me know of any problems
X-  *
X-  * 	Modified by Al Crew 1-5-88
X-  *		allow 720K (and when the kernel does 1.44M) diskettes
X-  *			(for 1.44M the size of /dev/at[01] will have to
X-  *			 be changed or a new device name added)
X-  *		adjusted MAX_FAT_SIZE and MAX_CLUSTER_SIZE to better
X-  *			match my fixed disk (you may want to change them)
X-  *              fixed bug in read_cluster (sbrk failures were not reported)
X   */
X  
X  #include <sys/stat.h>
X--- 25,30 ----
X***************
X*** 45,52 ****
X  #define DDHD	0xF9
X  #define DDFD	0xF8
X  
X! #define	MAX_CLUSTER_SIZE	2048
X! #define MAX_FAT_SIZE		25600	/* 50 sectoren */
X  #define HMASK		0xFF00
X  #define LMASK		0x00FF
X  
X--- 37,44 ----
X  #define DDHD	0xF9
X  #define DDFD	0xF8
X  
X! #define	MAX_CLUSTER_SIZE	4096
X! #define MAX_FAT_SIZE		23552	/* 46 sectoren */
X  #define HMASK		0xFF00
X  #define LMASK		0x00FF
X  
X***************
X*** 207,214 ****
X  		exit(1);
X  	}
X  
X! 	fdinit(dev_nr);
X! 	disk_read(f_start, &fat_type, sizeof(fat_type));
X  	disk_read(f_start + (long) fat_size, &fat_check, sizeof(fat_check));
X  	if (fat_check != fat_type) {
X  		print_string(TRUE, "Disk type in FAT copy differs from disk type in FAT original.\n");
X--- 199,237 ----
X  		exit(1);
X  	}
X  
X! 	if (fdisk) {		/* fixed disk */
X! 		fdinit(dev_nr);
X! 		disk_read(f_start, &fat_type, sizeof(fat_type));
X! 		if (fat_type != DDFD) {
X! 			print_string(TRUE, "Fixed disk is not DOS\n");
X! 			leave(1);
X! 		}
X! 	}
X! 	else {		/* use standard start for floppies */
X! 		f_start = FAT_START;
X! 		disk_read(f_start, &fat_type, sizeof(fat_type));
X! 		if (fat_type == DDDD) {		/* Double-sided double-density 9 s/t */
X! 			total_clusters = 355;	/* 720 - 7 - 2 - 2 - 1 */
X! 			cluster_size = 1024;	/* 2 sectors per cluster */
X! 			fat_size = 1024;	/* 2 sectors */
X! 			data_start = 6144L;	/* Starts on sector #12 */
X! 			root_entries = 112;	
X! 			sub_entries = 32;	/* 1024 / 32 */
X! 		}
X! 		else if (fat_type == DDHD) {	/* Double-sided high-density 15 s/t */
X! 			total_clusters = 2372;	/* 2400 - 14 - 7 - 7 - 1 */
X! 			cluster_size = 512;	/* 1 sector per cluster */
X! 			fat_size = 3584;	/* 7 sectors */
X! 			data_start = 14848L;	/* Starts on sector #29 */
X! 			root_entries = 224;	
X! 			sub_entries = 16;	/* 512 / 32 */
X! 		}
X! 		else {
X!         		print_string(TRUE, "Diskette is not DOS 2.0 360K or 1.2M\n");
X! 			leave(1);
X! 		}
X! 	}
X! 
X  	disk_read(f_start + (long) fat_size, &fat_check, sizeof(fat_check));
X  	if (fat_check != fat_type) {
X  		print_string(TRUE, "Disk type in FAT copy differs from disk type in FAT original.\n");
X***************
X*** 305,311 ****
X  	leave(0);
X  }
X  
X! fdinit(part_nr)		/* Initializations */
X  char part_nr;
X  {
X  
X--- 328,334 ----
X  	leave(0);
X  }
X  
X! fdinit(part_nr)		/* Fixed Disk Initializations */
X  char part_nr;
X  {
X  
X***************
X*** 356,365 ****
X  	pe = (struct part_entry *)&secbuf[TABLEOFFSET];
X  		/* get the proper partition */
X  	switch(part_nr) {
X- 		case '0':
X- 		case 'a':
X- 		case '1':
X- 		case 'b': boot_loc=0; break;
X  		case 'f': pe++;
X  		case 'e': pe++;
X  		case 'd': pe++;
X--- 379,384 ----
X***************
X*** 393,400 ****
X  		(boot.hidden_sectors[1]  << 8 & HMASK) + (boot.hidden_sectors[0] & LMASK));
X  	leave(1);
X  /**************/
X! 	if (((boot.media_type & 0xf0) != 0xf0)
X!             || (boot.jump[0] != 0xeb) || (boot.jump[2] != 0x90) ) {
X  		printf("DISK is not DOS Format.\n");
X  		leave(1);
X  	}
X--- 412,418 ----
X  		(boot.hidden_sectors[1]  << 8 & HMASK) + (boot.hidden_sectors[0] & LMASK));
X  	leave(1);
X  /**************/
X! 	if (boot.media_type != DDFD) {
X  		printf("DISK is not DOS Format.\n");
X  		leave(1);
X  	}
X***************
X*** 1032,1039 ****
X  	register DIRECTORY *sub_dir;
X  	extern char *sbrk();
X  
X! 	if ((sub_dir = (DIRECTORY *) sbrk(cluster_size)) 
X!             == ((DIRECTORY *)-1)) {
X  		print_string(TRUE, "Cannot set break!\n");
X  		leave(1);
X  	}
X--- 1050,1056 ----
X  	register DIRECTORY *sub_dir;
X  	extern char *sbrk();
X  
X! 	if ((sub_dir = (DIRECTORY *) sbrk(cluster_size)) < 0) {
X  		print_string(TRUE, "Cannot set break!\n");
X  		leave(1);
X  	}
/
echo x - floppy.c.cdiff
sed '/^X/s///' > floppy.c.cdiff << '/'
X*** floppy.c	Thu Jan 12 22:00:10 1989
X--- floppy.c.v1.3	Fri Jan  6 22:11:04 1989
X***************
X*** 15,48 ****
X   *   floppy_task:	main entry when system is brought up
X   *
X   *  Changes:
X!  *
X!  *	27 october 1986 by Jakob Schripsema: fdc_results fixed for 8 MHz
X!  *
X!  *      06 january 1988 by Al Crew:          Added 1.44MB drive support.
X!  *      Changes are provided on an "As Is" basis.  The responsibility for
X!  *      their use is yours.  The original driver supported 6 diskette/drive 
X!  *	combinations and depended on getting an error if the wrong type was
X!  *      used.  In reality, the driver was often using the wrong combination
X!  * 	(a close combination works for quite a while).  This was no
X!  * 	problem because all of the close combinations had the same
X!  *	geometry (9 sectors per track).  Thus, the mapping between
X!  * 	logical and physical sectors was still correct.  The
X!  *	only "odd ball" was the 1.2M diskette with 15 sectors per track,
X!  *	but its parameters were not close enough to the others to work 
X!  *	at all.  When I added the 1.44M diskette, a problem arose.
X!  *	The parameters for the 1.2M and the 1.44M are quite close, but
X!  *	they have different geometries.  If the driver ever guessed
X!  *	wrong, the logical structure of the disk would surely be damaged.
X!  *
X!  *	The array "drive_class" now defines which combinations are
X!  * 	allowed for each minor device.
X!  *	
X!  *		AUTOMATIC	Normal Minix V1.3
X!  *		THREEINCH	Only 3.5 inch drive combinations
X!  *		FIVEINCH	Only 5.25 inch drive combinations
X!  *
X!  *	12 january 1989 by Al Crew:
X!  *	Changed settling time criteria from computer type to drive type.
X   */
X  
X  #include "../h/const.h"
X--- 15,21 ----
X   *   floppy_task:	main entry when system is brought up
X   *
X   *  Changes:
X!  *	27 october 1986 by Jakob Schripsema: fdc_results fixed for 8 MHz
X   */
X  
X  #include "../h/const.h"
X***************
X*** 109,117 ****
X  
X  /* Parameters for the disk drive. */
X  #define SECTOR_SIZE      512	/* physical sector size in bytes */
X! #define HC_SIZE         2880	/* # sectors on a high-capacity (1.44M) disk */
X! #define NR_HEADS        0x02	/* two heads (i.e., two tracks/cylinder) */
X! #define DTL             0xFF	/* determines data length (sector size) */
X  #define SPEC2           0x02	/* second parameter to SPECIFY */
X  
X  #define MOTOR_OFF       3*HZ	/* how long to wait before stopping motor */
X--- 82,91 ----
X  
X  /* Parameters for the disk drive. */
X  #define SECTOR_SIZE      512	/* physical sector size in bytes */
X! #define HC_SIZE         2400	/* # sectors on a high-capacity (1.2M) disk */
X! #define NR_HEADS        0x02	/* two heads (i.e., two tracks/cylinder) */
X! #define DTL             0xFF	/* determines data length (sector size) */
X! #define SPEC1           0xDF	/* first parameter to SPECIFY */
X  #define SPEC2           0x02	/* second parameter to SPECIFY */
X  
X  #define MOTOR_OFF       3*HZ	/* how long to wait before stopping motor */
X***************
X*** 131,140 ****
X  #define NR_DRIVES          2	/* maximum number of drives */
X  #define DIVISOR          128	/* used for sector size encoding */
X  #define MAX_FDC_RETRY    100	/* max # times to try to output to FDC */
X! #define NT                 7	/* number of diskette/drive combinations */
X! #define AUTOMATIC	0x3F	/* automatic selection as in std Minix 1.3 */
X! #define THREEINCH	0x48	/* allow only valid 3.5 inch drive */
X! #define FIVEINCH	0x37	/* allow only valid 5.25 inch drive */
X  
X  /* Variables. */
X  PRIVATE struct floppy {		/* main drive struct, one entry per drive */
X--- 105,111 ----
X  #define NR_DRIVES          2	/* maximum number of drives */
X  #define DIVISOR          128	/* used for sector size encoding */
X  #define MAX_FDC_RETRY    100	/* max # times to try to output to FDC */
X! #define NT                 6	/* number of diskette/drive combinations */
X  
X  /* Variables. */
X  PRIVATE struct floppy {		/* main drive struct, one entry per drive */
X***************
X*** 149,155 ****
X    vir_bytes fl_address;		/* user virtual address */
X    char fl_results[MAX_RESULTS];	/* the controller can give lots of output */
X    char fl_calibration;		/* CALIBRATED or UNCALIBRATED */
X!   char fl_density;		/* 0 = 360K/360K; 1 = 360K/1.2M; etc. */
X  } floppy[NR_DRIVES];
X  
X  #define UNCALIBRATED       0	/* drive needs to be calibrated at next use */
X--- 120,126 ----
X    vir_bytes fl_address;		/* user virtual address */
X    char fl_results[MAX_RESULTS];	/* the controller can give lots of output */
X    char fl_calibration;		/* CALIBRATED or UNCALIBRATED */
X!   char fl_density;		/* 0 = 360K/360K; 1 = 360K/1.2M; 2= 1.2M/1.2M*/
X  } floppy[NR_DRIVES];
X  
X  #define UNCALIBRATED       0	/* drive needs to be calibrated at next use */
X***************
X*** 161,172 ****
X  PRIVATE int need_reset;		/* set to 1 when controller must be reset */
X  PRIVATE int initialized;	/* set to 1 after first successful transfer */
X  PRIVATE int d;			/* diskette/drive combination */
X- PRIVATE int current_spec1;	/* latest spec1 sent to the controller */
X  
X  PRIVATE message mess;		/* message buffer for in and out */
X  
X  PRIVATE char len[] = {-1,0,1,-1,2,-1,-1,3,-1,-1,-1,-1,-1,-1,-1,4};
X! PRIVATE char interleave[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18};
X  
X  /* Six combinations of diskette/drive are supported:
X   * # Drive  diskette  Sectors  Tracks  Rotation Data-rate  Comment
X--- 132,142 ----
X  PRIVATE int need_reset;		/* set to 1 when controller must be reset */
X  PRIVATE int initialized;	/* set to 1 after first successful transfer */
X  PRIVATE int d;			/* diskette/drive combination */
X  
X  PRIVATE message mess;		/* message buffer for in and out */
X  
X  PRIVATE char len[] = {-1,0,1,-1,2,-1,-1,3,-1,-1,-1,-1,-1,-1,-1,4};
X! PRIVATE char interleave[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
X  
X  /* Six combinations of diskette/drive are supported:
X   * # Drive  diskette  Sectors  Tracks  Rotation Data-rate  Comment
X***************
X*** 174,211 ****
X   * 1  1.2M    1.2M     15       80     360 RPM  500 kbps   AT disk in AT drive
X   * 2  720K    360K      9       40     300 RPM  250 kbps   Quad density PC
X   * 3  720K    720K      9       80     300 RPM  250 kbps   Toshiba, et al.
X!  * or 1.44M   720K	9	80     300 RPM  250 kbps   PS/2, et al.
X!  * 4  1.2M    360K      9       40     360 RPM  300 kbps   PC disk in AT drive
X!  * 5  1.2M    720K      9       80     360 RPM  300 kbps   Toshiba in AT drive
X!  * 6  1.44M   1.44M    18	80     300 RPM  500 kbps   PS/2, et al.
X!  */
X! PRIVATE int gap[NT] =
X! 	{0x2A, 0x1B, 0x2A, 0x2A, 0x23, 0x23, 0x1B}; /* gap size */
X! PRIVATE int rate[NT] = 
X! 	{0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x00}; /* 2=250,1=300,0=500 kbps*/
X! PRIVATE int nr_sectors[NT] = 
X! 	{9,    15,   9,    9,    9,    9,    18};   /* sectors/track */
X! PRIVATE int nr_blocks[NT] = 
X! 	{720,  2400, 720,  1440, 720,  1440, 2880}; /* sectors/diskette*/
X! PRIVATE int steps_per_cyl[NT] = 
X! 	{1,    1,    2,    1,    2,    1,     1};   /* 2 = dbl step */
X! PRIVATE int mtr_setup[NT] = 
X! 	{HZ/4,3*HZ/4,HZ/4,HZ,3*HZ/4,3*HZ/4,HZ};     /* in ticks */
X! PRIVATE char spec1[NT] =
X! 	{0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xAF}; /* step rate, etc. */
X! 
X! PRIVATE char drive_class[NR_DRIVES] = {
X! #ifndef DEFAULT_CLASS
X! 	AUTOMATIC, AUTOMATIC
X! #else
X! #if	(DEFAULT_CLASS==3)
X! 	THREEINCH, THREEINCH
X! #endif
X! #if	(DEFAULT_CLASS==5)
X! 	FIVEINCH, FIVEINCH
X! #endif
X! #endif
X! };
X  
X  /*===========================================================================*
X   *				floppy_task				     * 
X--- 144,164 ----
X   * 1  1.2M    1.2M     15       80     360 RPM  500 kbps   AT disk in AT drive
X   * 2  720K    360K      9       40     300 RPM  250 kbps   Quad density PC
X   * 3  720K    720K      9       80     300 RPM  250 kbps   Toshiba, et al.
X!  * 4  1.2M    360K      9       40     360 RPM  300 kbps   PC disk in AT drive
X!  * 5  1.2M    720K      9       80     360 RPM  300 kbps   Toshiba in AT drive
X!  */
X! PRIVATE int gap[NT] =
X! 	{0x2A, 0x1B, 0x2A, 0x2A, 0x23, 0x23}; /* gap size */
X! PRIVATE int rate[NT] = 
X! 	{0x02, 0x00, 0x02, 0x02, 0x01, 0x01}; /* 250,300,500 kbps*/
X! PRIVATE int nr_sectors[NT] = 
X! 	{9,    15,   9,    9,    9,    9};   /* sectors/track */
X! PRIVATE int nr_blocks[NT] = 
X! 	{720,  2400, 720,  1440, 720,  1440}; /* sectors/diskette*/
X! PRIVATE int steps_per_cyl[NT] = 
X! 	{1,    1,    2,    1,    2,    1};   /* 2 = dbl step */
X! PRIVATE int mtr_setup[NT] = 
X! 	{HZ/4,3*HZ/4,HZ/4,2*HZ/4,3*HZ/4,3*HZ/4};/* in ticks */
X  
X  /*===========================================================================*
X   *				floppy_task				     * 
X***************
X*** 257,271 ****
X    /* Decode the message parameters. */
X    drive = m_ptr->DEVICE;
X    if (drive < 0 || drive >= NR_DRIVES) return(EIO);
X!   fp = &floppy[drive];		/* 'fp' points to entry for this drive */  
X    fp->fl_drive = drive;		/* save drive number explicitly */
X    fp->fl_opcode = m_ptr->m_type;	/* DISK_READ or DISK_WRITE */
X    if (m_ptr->POSITION % BLOCK_SIZE != 0) return(EINVAL);
X    block = m_ptr->POSITION/SECTOR_SIZE;
X!   if (block >= HC_SIZE) return(EOF); /* sector is beyond end of 1.44M disk */
X!   d = fp->fl_density;		/* diskette/drive combination */
X!   while ((drive_class[drive] & (1 << d)) == 0) d = (d + 1) % NT;
X!   fp->fl_density=d;
X    fp->fl_cylinder = (int) (block / (NR_HEADS * nr_sectors[d]));
X    fp->fl_sector = (int) interleave[(int)(block % nr_sectors[d])];
X    fp->fl_head = (int) (block % (NR_HEADS*nr_sectors[d]) )/nr_sectors[d];
X--- 210,222 ----
X    /* Decode the message parameters. */
X    drive = m_ptr->DEVICE;
X    if (drive < 0 || drive >= NR_DRIVES) return(EIO);
X!   fp = &floppy[drive];		/* 'fp' points to entry for this drive */
X    fp->fl_drive = drive;		/* save drive number explicitly */
X    fp->fl_opcode = m_ptr->m_type;	/* DISK_READ or DISK_WRITE */
X    if (m_ptr->POSITION % BLOCK_SIZE != 0) return(EINVAL);
X    block = m_ptr->POSITION/SECTOR_SIZE;
X!   if (block >= HC_SIZE) return(EOF);	/* sector is beyond end of 1.2M disk */
X!   d = fp->fl_density;		/* diskette/drive combination */
X    fp->fl_cylinder = (int) (block / (NR_HEADS * nr_sectors[d]));
X    fp->fl_sector = (int) interleave[(int)(block % nr_sectors[d])];
X    fp->fl_head = (int) (block % (NR_HEADS*nr_sectors[d]) )/nr_sectors[d];
X***************
X*** 285,293 ****
X  	 */
X  	errors++;		/* increment count once per loop cycle */
X   	if (errors % (MAX_ERRORS/NT) == 0) {
X!                 d++;
X! 		while ((drive_class[drive] & (1 << d)) == 0)
X! 			d = (d + 1) % NT;	/* try next density */
X   		fp->fl_density = d;
X  		sectors = nr_sectors[d];
X  		fp->fl_cylinder = (int) (block / (NR_HEADS * sectors));
X--- 236,242 ----
X  	 */
X  	errors++;		/* increment count once per loop cycle */
X   	if (errors % (MAX_ERRORS/NT) == 0) {
X!  		d = (d + 1) % NT;	/* try next density */
X   		fp->fl_density = d;
X  		sectors = nr_sectors[d];
X  		fp->fl_cylinder = (int) (block / (NR_HEADS * sectors));
X***************
X*** 300,315 ****
X  	/* First check to see if a reset is needed. */
X  	if (need_reset) reset();
X  
X- 	/* Set the stepping rate */
X- 	if (current_spec1 != spec1[d]) {
X- 		fdc_out(FDC_SPECIFY);
X- 		fdc_out(current_spec1=spec1[d]);
X- 		fdc_out(SPEC2);
X- 	}
X- 
X-  	/* Set the data rate */
X- 	if (pc_at) port_out(FDC_RATE, rate[d]);
X- 
X  	/* Now set up the DMA chip. */
X  	dma_setup(fp);
X  
X--- 249,254 ----
X***************
X*** 471,477 ****
X    if (r != OK) 
X  	if (recalibrate(fp) != OK) return(ERR_SEEK);
X    fp->fl_curcyl = (r == OK ? fp->fl_cylinder : -1);
X!   if (r == OK && ((d == 6) || (d == 3))) {/* give head time to settle on 3.5 */
X  	clock_mess(2, send_mess);
X  	receive(CLOCK, &mess);
X    }
X--- 410,416 ----
X    if (r != OK) 
X  	if (recalibrate(fp) != OK) return(ERR_SEEK);
X    fp->fl_curcyl = (r == OK ? fp->fl_cylinder : -1);
X!   if (r == OK && ps) {		/* give head time to settle on PS/2 */
X  	clock_mess(2, send_mess);
X  	receive(CLOCK, &mess);
X    }
X***************
X*** 635,641 ****
X    } else {
X  	/* Recalibration succeeded. */
X  	fp->fl_calibration = CALIBRATED;
X! 	if (ps||((d == 6) || (d == 3))) {/* give head time to settle on 3.5 */
X  		clock_mess(2, send_mess);
X  		receive(CLOCK, &mess);
X  	}
X--- 574,580 ----
X    } else {
X  	/* Recalibration succeeded. */
X  	fp->fl_calibration = CALIBRATED;
X! 	if (ps) {		/* give head time to settle on PS/2 */
X  		clock_mess(2, send_mess);
X  		receive(CLOCK, &mess);
X  	}
X***************
X*** 675,681 ****
X  
X    /* Tell FDC drive parameters. */
X    fdc_out(FDC_SPECIFY);		/* specify some timing parameters */
X!   fdc_out(current_spec1=spec1[d]); /* step-rate and head-unload-time */
X    fdc_out(SPEC2);		/* head-load-time and non-dma */
X  
X    for (i = 0; i < NR_DRIVES; i++) floppy[i].fl_calibration = UNCALIBRATED;
X--- 614,620 ----
X  
X    /* Tell FDC drive parameters. */
X    fdc_out(FDC_SPECIFY);		/* specify some timing parameters */
X!   fdc_out(SPEC1);		/* step-rate and head-unload-time */
X    fdc_out(SPEC2);		/* head-load-time and non-dma */
X  
X    for (i = 0; i < NR_DRIVES; i++) floppy[i].fl_calibration = UNCALIBRATED;
/