From: heiko@kaa.informatik.rwth-aachen.de (Heiko Schroeder)
Newsgroups: comp.os.linux
Subject: nonstandard floppy formats for linux
Date: 8 Jan 93 10:02:48 GMT
Organization: Rechnerbetrieb Informatik - RWTH Aachen
NNTP-Posting-Host: kaa.informatik.rwth-aachen.de

Hi,

for all of you who are not satisfied with 1.44MB on 3.5" floppy disk:

I patched the linux kernel so that I can use the formats known from the
MS-DOS program fdformat. The formats are established with new device numbers,
so that you can create dev-entries for them. Autodetection works, but there's
one (minor) problem: some of the formats use more than 80 tracks, this is
not detectable with reasonable effort (one would have to try to read the tracks
81,82,83 to find out if they exist, but I think, that's to much to slow).
So I used a new variable in the main Makefile to decide which number of 
tracks the autodetection routine should assume. You have to edit the Makefile
to change this (I use FD_detect_83).

The new formats supported are:
3,5": 21 sectors, 80 tracks, 1.68MB, device 11
      21 sectors, 82 tracks, 1.72MB, device 15
      21 sectors, 83 tracks, 1.74MB, device 19
      10 sectors, 80 tracks, 800k, device 9
      10 sectors, 82 tracks, 820k, device 13
      10 sectors, 83 tracks, 830k, device 17
5,25" HD:
      18 sectors, 80 tracks, 1.44MB, device 10
      18 sectors, 82 tracks, 1.48MB, device 14
      18 sectors, 83 tracks, 1.59MB, device 18
      10 sectors, 40 tracks, 400k, device 8
      10 sectors, 41 tracks, 410k, device 12
      10 sectors, 42 tracks, 420k, device 16

Minor device numbers are calculated as ususal:
   device * 4 + drive number
So a 1.74MB format for drive 0 would be set with
  mknod /dev/fd0h1743 b 2 76

It works fine on my system and on a few other system, too, but I can't
guarantee that it will work on other systems (but I think it should).

The files Makefile, boot/head.S and kernel/blk_drv/floppy.c are affected
by the patch, so it should work with earlier versions of linux, but some
editing may be needed.
Here is the patch (for linux 0.99pl2):
-------------------------------------------------------------------------
*** Makefile.old	Fri Jan  1 21:45:57 1993
--- Makefile	Thu Jan  7 18:00:38 1993
***************
*** 71,80 ****
  SOUND_SUPPORT = -DKERNEL_SOUNDCARD -DDSP_BUFFSIZE=16384 -DSBC_IRQ=7 -DPAS_IRQ=5
  
  #
  # standard CFLAGS
  #
  
! CFLAGS = -Wall -O6 -fomit-frame-pointer
  
  ifdef CONFIG_M486
  CFLAGS := $(CFLAGS) -m486
--- 71,92 ----
  SOUND_SUPPORT = -DKERNEL_SOUNDCARD -DDSP_BUFFSIZE=16384 -DSBC_IRQ=7 -DPAS_IRQ=5
  
  #
+ # As we can't detect the number of tracks on a floppy disk with in
+ # reasonable time, there is variable, which tells the autodetect routine
+ # how many tracks it should assume. This aplies only to the nonstandard
+ # formats!
+ #     FD_detect_82     assume 82 tracks
+ #     FD_detect_83     assume 83 tracks
+ #     (none)           assume 80 tracks, default
+ #
+ 
+ FD_DETECT=-DFD_detect_83
+ 
+ #
  # standard CFLAGS
  #
  
! CFLAGS = -Wall -O6 -fomit-frame-pointer $(FD_DETECT) 
  
  ifdef CONFIG_M486
  CFLAGS := $(CFLAGS) -m486
*** boot/head.S.old	Fri Jan  1 21:45:58 1993
--- boot/head.S	Thu Jan  7 14:37:31 1993
***************
*** 215,224 ****
   * floppy_track_buffer is used to buffer one track of floppy data: it
   * has to be separate from the tmp_floppy area, as otherwise a single-
   * sector read/write can mess it up. It can contain one full track of
!  * data (18*2*512 bytes).
   */
  _floppy_track_buffer:
! 	.fill 512*2*18,1,0
  
  /* This is the default interrupt "handler" :-) */
  int_msg:
--- 215,224 ----
   * floppy_track_buffer is used to buffer one track of floppy data: it
   * has to be separate from the tmp_floppy area, as otherwise a single-
   * sector read/write can mess it up. It can contain one full track of
!  * data (21*2*512 bytes).
   */
  _floppy_track_buffer:
! 	.fill 512*2*21,1,0
  
  /* This is the default interrupt "handler" :-) */
  int_msg:
*** kernel/blk_drv/floppy.c.old	Fri Dec 11 11:15:23 1992
--- kernel/blk_drv/floppy.c	Thu Jan  7 14:37:45 1993
***************
*** 103,115 ****
   * Maximum disk size (in kilobytes). This default is used whenever the
   * current disk size is unknown.
   */
! #define MAX_DISK_SIZE 1440
  
  /*
   * Maximum number of sectors in a track buffer. Track buffering is disabled
   * if tracks are bigger.
   */
! #define MAX_BUFFER_SECTORS 18
  
  /*
   * The DMA channel used by the floppy controller cannot access data at
--- 103,115 ----
   * Maximum disk size (in kilobytes). This default is used whenever the
   * current disk size is unknown.
   */
! #define MAX_DISK_SIZE 1743
  
  /*
   * Maximum number of sectors in a track buffer. Track buffering is disabled
   * if tracks are bigger.
   */
! #define MAX_BUFFER_SECTORS 21
  
  /*
   * The DMA channel used by the floppy controller cannot access data at
***************
*** 135,171 ****
   * be self-explanatory.
   */
  static struct floppy_struct floppy_type[] = {
! 	{    0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL },	/* no testing */
! 	{  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,NULL },	/* 360kB PC diskettes */
! 	{ 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,NULL },	/* 1.2 MB AT-diskettes */
! 	{  720, 9,2,40,1,0x2A,0x02,0xDF,0x50,NULL },	/* 360kB in 720kB drive */
! 	{ 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,NULL },	/* 3.5" 720kB diskette */
! 	{  720, 9,2,40,1,0x23,0x01,0xDF,0x50,NULL },	/* 360kB in 1.2MB drive */
! 	{ 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,NULL },	/* 720kB in 1.2MB drive */
! 	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL },	/* 1.44MB diskette */
  };
  
  /*
!  * Auto-detection. Each drive type has a pair of formats which are
   * used in succession to try to read the disk. If the FDC cannot lock onto
   * the disk, the next format is tried. This uses the variable 'probing'.
   */
! static struct floppy_struct floppy_types[] = {
! 	{  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k/PC" }, /* 360kB PC diskettes */
! 	{  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k/PC" }, /* 360kB PC diskettes */
! 	{ 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"1.2M" },	  /* 1.2 MB AT-diskettes */
! 	{  720, 9,2,40,1,0x23,0x01,0xDF,0x50,"360k/AT" }, /* 360kB in 1.2MB drive */
! 	{ 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k" },	  /* 3.5" 720kB diskette */
! 	{ 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k" },	  /* 3.5" 720kB diskette */
! 	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"1.44M" },	  /* 1.44MB diskette */
! 	{ 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k/AT" }, /* 3.5" 720kB diskette */
! };
  
  /* Auto-detection: Disk type used until the next media change occurs. */
  struct floppy_struct *current_type[4] = { NULL, NULL, NULL, NULL };
  
  /* This type is tried first. */
! struct floppy_struct *base_type[4];
  
  /*
   * User-provided type information. current_type points to
--- 135,193 ----
   * be self-explanatory.
   */
  static struct floppy_struct floppy_type[] = {
! 	{    0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL },	/*  0 no testing */
! 	{  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"360k PC" },	/*  1 360kB PC diskettes */
! 	{ 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"1.2M" },	/*  2 1.2 MB AT-diskettes */
! 	{  720, 9,2,40,1,0x2A,0x02,0xDF,0x50,"D360" },	/*  3 360kB in 720kB drive */
! 	{ 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"720k"},	/*  4 3.5" 720kB diskette */
! 	{  720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360" },	/*  5 360kB in 1.2MB drive */
! 	{ 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" },	/*  6 720kB in 1.2MB drive */
! 	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"1.44M" },	/*  7 1.44MB diskette */
! 	{  800,10,2,40,1,0x25,0x02,0xDF,0x2E,"h400" },	/*  8 400k 5.25" */
! 	{ 1600,10,2,80,0,0x25,0x01,0xDF,0x2E,"H800" },	/*  9 800k 3.5" */
! 	{ 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */
! 	{ 3360,21,2,80,0,0x25,0x00,0xDF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */
! 	{  820,10,2,41,1,0x25,0x02,0xDF,0x2E,"h410" },	/* 12 410k 5.25" */
! 	{ 1640,10,2,82,0,0x25,0x01,0xDF,0x2E,"H820" },	/* 13 820k 3.5" */
! 	{ 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" },	/* 14 1.48MB 5.25" */
! 	{ 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" },	/* 15 1.72MB 3.5" */
! 	{  840,10,2,42,1,0x25,0x02,0xDF,0x2E,"h420" },	/* 16 420k 5.25" */
! 	{ 1660,10,2,83,0,0x25,0x01,0xDF,0x2E,"H830" },	/* 17 830k 3.5" */
! 	{ 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" },	/* 18 1.49MB 5.25" */
! 	{ 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" },	/* 19 1.74MB 3.5" */
  };
  
  /*
!  * Auto-detection. Each drive type has four formats which are
   * used in succession to try to read the disk. If the FDC cannot lock onto
   * the disk, the next format is tried. This uses the variable 'probing'.
   */
! static int floppy_types[] = {
! #ifdef FD_detect_82
! 	 1,  1,  1,  1,  /* 5.25" DD drive */
! 	14,  2, 12,  5,  /* 5.25" HD drive */
! 	13,  4, 13,  4,  /* 3.5" DD drive */
! 	15,  7, 13,  4   /* 3.5" HD drive */
! #else
! #ifdef FD_detect_83
! 	 1,  1,  1,  1,
! 	18,  2, 16,  5,
! 	17,  4, 17,  4,
! 	19,  7, 17,  4
! #else   /* 80 tracks */
! 	 1,  1,  1,  1,
! 	10,  2,  8,  5,
! 	 9,  4,  9,  4,
! 	11,  7,  9,  4
! #endif
! #endif
! 	};
  
  /* Auto-detection: Disk type used until the next media change occurs. */
  struct floppy_struct *current_type[4] = { NULL, NULL, NULL, NULL };
  
  /* This type is tried first. */
! int *base_type[4];
  
  /*
   * User-provided type information. current_type points to
***************
*** 181,187 ****
  	 720, 720, 720, 720,
  	 360, 360, 360, 360,
  	 720, 720, 720, 720,
! 	1440,1440,1440,1440
  };
  
  /*
--- 203,221 ----
  	 720, 720, 720, 720,
  	 360, 360, 360, 360,
  	 720, 720, 720, 720,
! 	1440,1440,1440,1440,
! 	 400, 400, 400, 400,
! 	 800, 800, 800, 800,
! 	1440,1440,1440,1440,
! 	1680,1680,1680,1680,
! 	 410, 410, 410, 410,
! 	 820, 820, 820, 820,
! 	1476,1476,1476,1476,
! 	1722,1722,1722,1722,
! 	 420, 420, 420, 420,
! 	 830, 830, 830, 830,
! 	1494,1494,1494,1494,
! 	1743,1743,1743,1743
  };
  
  /*
***************
*** 899,921 ****
  
  static void setup_format_params(void)
  {
!     unsigned char *here = (unsigned char *) tmp_floppy_area;
!     int count,head_shift,track_shift,total_shift;
  
      /* allow for about 30ms for data transport per track */
      head_shift  = floppy->sect / 6;
      /* a ``cylinder'' is two tracks plus a little stepping time */
      track_shift = 2 * head_shift + 1; 
!     /* count backwards */
!     total_shift = floppy->sect - 
! 	((track_shift * track + head_shift * head) % floppy->sect);
! 
!     /* XXX: should do a check to see this fits in tmp_floppy_area!! */
!     for (count = 0; count < floppy->sect; count++) {
! 	*here++ = track;
! 	*here++ = head;
! 	*here++ = 1 + (( count + total_shift ) % floppy->sect);
! 	*here++ = 2; /* 512 bytes */
      }
  }
  
--- 933,970 ----
  
  static void setup_format_params(void)
  {
!     struct fparm {
!         unsigned char track,head,sect,size;
!         } *here = (void *)tmp_floppy_area;
!     int il,n,count,head_shift,track_shift;
  
      /* allow for about 30ms for data transport per track */
      head_shift  = floppy->sect / 6;
      /* a ``cylinder'' is two tracks plus a little stepping time */
      track_shift = 2 * head_shift + 1; 
!     /* position of logical sector 1 on this track */
!     n = (track_shift * track + head_shift * head) % floppy->sect;
!     /* determine interleave */
!     il = (floppy->sect-
!         floppy_type[base_type[format_req.device & 3][1]].sect)>2?2:1;
!     /* initialize field */ 
!     for (count = 0; count < floppy->sect; ++count) {
!        here[count].track = track;
!        here[count].head = head;
!        here[count].sect = 0;
!        here[count].size = 2;
!        }
!     /* place logical sectors */
!     for (count = 1; count <= floppy->sect; ++count) {
!         here[n].sect = count;
!         n = (n+il) % floppy->sect;
!         if (here[n].sect) { /* sector busy, find next free sector */
!            ++n;
!            if (n>=floppy->sect) {
!              n-=floppy->sect;
!              while (here[n].sect) ++n;
!              }
!         }
      }
  }
  
***************
*** 954,965 ****
  	else { /* Auto-detection */
  		if ((floppy = current_type[device & 3]) == NULL) {
  			probing = 1;
! 			if ((floppy = base_type[device & 3]) ==
! 			    NULL) {
  				request_done(0);
  				goto repeat;
  			}
! 			floppy += CURRENT_ERRORS & 1;
  		}
  	}
  	if (format_status != FORMAT_BUSY) {
--- 1003,1014 ----
  	else { /* Auto-detection */
  		if ((floppy = current_type[device & 3]) == NULL) {
  			probing = 1;
! 			if (base_type[device & 3] == NULL) {
! 				floppy = NULL;
  				request_done(0);
  				goto repeat;
  			}
! 			floppy = &floppy_type[base_type[device & 3][CURRENT_ERRORS & 3]];
  		}
  	}
  	if (format_status != FORMAT_BUSY) {
***************
*** 1144,1156 ****
  inb_p(0x71); \
  })
  
! static struct floppy_struct *find_base(int drive,int code)
  {
! 	struct floppy_struct *base;
  
  	if (code > 0 && code < 5) {
! 		base = &floppy_types[(code-1)*2];
! 		printk("fd%d is %s",drive,base->name);
  		return base;
  	}
  	printk("fd%d is unknown type %d",drive,code);
--- 1193,1205 ----
  inb_p(0x71); \
  })
  
! static int *find_base(int drive,int code)
  {
! 	int *base;
  
  	if (code > 0 && code < 5) {
! 		base = &floppy_types[(code-1)*4];
! 		printk("fd%d is %s",drive,floppy_type[base[1]].name);
  		return base;
  	}
  	printk("fd%d is unknown type %d",drive,code);
------------------------------------------------------------------------
That`s ist. I hobe it is usefull for some of you.

CU
   Heiko
--
PS: Please excuse my english as it is not my native language.
(heiko@pool.informatik.rwth-aachen.de)

Newsgroups: comp.os.linux