[comp.os.minix] a solution to the xt_wini RRL disk drive problem

hall@nosc.NOSC.MIL (Robert R. Hall) (11/08/88)

I now have the MINIX xt_wini driver working with my RRL disk drive.
I am using the seagate ST2238 disk with Western WD-27x controller.
The previous problem which the xt_xini.c version 1.3c+ was giving
was error message the the hard drive won't reset status: $C0
and error message cant read partition parameters.
Then after overcomming these message it then would refuse to
mount any file system built on the hard drive.

I dissasembled the BIOS ROM at location C800:0000 for examples
where correction may be need.  The following patch is what I ended
up with.  You MFM owner check it out for your drives to see if
any of my patches cause trouble with you.  It would be nice to
have only one xt_wini version.

---------------------   xt_wini.cdif   -----------------------------
*** xt_wini.v3c	Thu Oct 13 08:14:22 1988
--- xt_wini.c	Mon Nov  7 07:07:40 1988
***************
*** 32,38
  #include "type.h"
  #include "proc.h"
  
! /*#define AUTO_BIOS       TRUE	/* TRUE: use Western's autoconfig BIOS */
  #define DEBUG	       FALSE	/* TRUE: enable debug messages */
  #define MONITOR		TRUE	/* TRUE: monitor performance of busy loops */
  #define MAX_DRIVES         1

--- 32,38 -----
  #include "type.h"
  #include "proc.h"
  
! #define AUTO_BIOS      FALSE	/* TRUE: use Western's autoconfig BIOS */
  #define DEBUG	       FALSE	/* TRUE: enable debug messages */
  #define MONITOR	       FALSE	/* TRUE: monitor performance of busy loops */
  #define RRL		TRUE	/* MFM owners need to set this false */
***************
*** 34,40
  
  /*#define AUTO_BIOS       TRUE	/* TRUE: use Western's autoconfig BIOS */
  #define DEBUG	       FALSE	/* TRUE: enable debug messages */
! #define MONITOR		TRUE	/* TRUE: monitor performance of busy loops */
  #define MAX_DRIVES         1
  
  /* I/O Ports used by winchester disk task. */

--- 34,41 -----
  
  #define AUTO_BIOS      FALSE	/* TRUE: use Western's autoconfig BIOS */
  #define DEBUG	       FALSE	/* TRUE: enable debug messages */
! #define MONITOR	       FALSE	/* TRUE: monitor performance of busy loops */
! #define RRL		TRUE	/* MFM owners need to set this false */
  #define MAX_DRIVES         1
  
  /* I/O Ports used by winchester disk task. */
***************
*** 72,78
  
  /* Parameters for the disk drive. */
  #define SECTOR_SIZE	 512	/* physical sector size in bytes */
! #define NR_SECTORS	0x11	/* number of sectors per track */
  
  /* Error codes */
  #define ERR		  -1	/* general error */

--- 73,79 -----
  
  /* Parameters for the disk drive. */
  #define SECTOR_SIZE	 512	/* physical sector size in bytes */
! #define NR_SECTORS	  26	/* number of sectors per track */
  
  /* Error codes */
  #define ERR		  -1	/* general error */
***************
*** 87,92
  #if AUTO_BIOS
  #define AUTO_PARAM     0x1AD	/* drive parameter table starts here in sect 0	*/
  #define AUTO_ENABLE	0x10	/* auto bios enabled bit from status reg */
  /* some start up parameters in order to extract the drive parameter table */
  /* from the winchester. these should not need changed. */
  #define AUTO_CYLS	 306	/* default number of cylinders */

--- 88,94 -----
  #if AUTO_BIOS
  #define AUTO_PARAM     0x1AD	/* drive parameter table starts here in sect 0	*/
  #define AUTO_ENABLE	0x10	/* auto bios enabled bit from status reg */
+ #endif
  /* some start up parameters in order to extract the drive parameter table */
  /* from the winchester. these should not need changed. */
  #define AUTO_CYLS	 613	/* default number of cylinders */
***************
*** 89,95
  #define AUTO_ENABLE	0x10	/* auto bios enabled bit from status reg */
  /* some start up parameters in order to extract the drive parameter table */
  /* from the winchester. these should not need changed. */
! #define AUTO_CYLS	 306	/* default number of cylinders */
  #define AUTO_HEADS	   4	/* default number of heads */
  #define AUTO_RWC	 307	/* default reduced write cylinder */
  #define AUTO_WPC	 307	/* default write precomp cylinder */

--- 91,97 -----
  #endif
  /* some start up parameters in order to extract the drive parameter table */
  /* from the winchester. these should not need changed. */
! #define AUTO_CYLS	 613	/* default number of cylinders */
  #define AUTO_HEADS	   4	/* default number of heads */
  #define AUTO_RWC	 616	/* default reduced write cylinder */
  #define AUTO_WPC	 616	/* default write precomp cylinder */
***************
*** 91,98
  /* from the winchester. these should not need changed. */
  #define AUTO_CYLS	 306	/* default number of cylinders */
  #define AUTO_HEADS	   4	/* default number of heads */
! #define AUTO_RWC	 307	/* default reduced write cylinder */
! #define AUTO_WPC	 307	/* default write precomp cylinder */
  #define AUTO_ECC	  11	/* default ecc burst */
  #define AUTO_CTRL	   5	/* default winchester stepping speed byte */
  #endif

--- 93,100 -----
  /* from the winchester. these should not need changed. */
  #define AUTO_CYLS	 613	/* default number of cylinders */
  #define AUTO_HEADS	   4	/* default number of heads */
! #define AUTO_RWC	 616	/* default reduced write cylinder */
! #define AUTO_WPC	 616	/* default write precomp cylinder */
  #define AUTO_ECC	  11	/* default ecc burst */
  #define AUTO_CTRL	   7	/* default winchester stepping speed byte */
  
***************
*** 94,101
  #define AUTO_RWC	 307	/* default reduced write cylinder */
  #define AUTO_WPC	 307	/* default write precomp cylinder */
  #define AUTO_ECC	  11	/* default ecc burst */
! #define AUTO_CTRL	   5	/* default winchester stepping speed byte */
! #endif
  
  /* Variables. */
  PRIVATE struct wini {		/* main drive struct, one entry per drive */

--- 96,102 -----
  #define AUTO_RWC	 616	/* default reduced write cylinder */
  #define AUTO_WPC	 616	/* default write precomp cylinder */
  #define AUTO_ECC	  11	/* default ecc burst */
! #define AUTO_CTRL	   7	/* default winchester stepping speed byte */
  
  /* Variables. */
  PRIVATE struct wini {		/* main drive struct, one entry per drive */
***************
*** 390,396
    /* Strobe reset bit low. */
    port_out(WIN_STATUS, 0);
  
!   for(i = MAX_WIN_RETRY/10; i; --i)
  	;	/* Spin loop for a while */
  
    port_out(WIN_SELECT, 0);	/* Issue select pulse */

--- 391,397 -----
    /* Strobe reset bit low. */
    port_out(WIN_STATUS, 0);
  
!   for(i = 0x0584; i; i--)
  	;	/* Spin loop for a while */
  
    for (i = 500; i; i--) {
***************
*** 393,400
    for(i = MAX_WIN_RETRY/10; i; --i)
  	;	/* Spin loop for a while */
  
!   port_out(WIN_SELECT, 0);	/* Issue select pulse */
!   for (i = 0; i < MAX_WIN_RETRY; i++) {
  	port_in(WIN_STATUS, &r);
  	if(r & 0x30)		/* What is 10? 20 = INTERRUPT */
  		return (ERR);

--- 394,401 -----
    for(i = 0x0584; i; i--)
  	;	/* Spin loop for a while */
  
!   for (i = 500; i; i--) {
!   	port_out(WIN_SELECT, 0);	/* Issue select pulse */
  	port_in(WIN_STATUS, &r);
  	if(r & 0x30)		/* What is 10? 20 = INTERRUPT */
  		return (ERR);
***************
*** 404,410
  		break;
    }
  
!   if (i == MAX_WIN_RETRY) {
  	printf("Hard disk won't reset, status = %x\n", r);
  	return(ERR);
    }

--- 405,411 -----
  		break;
    }
  
!   if (!i) {
  	printf("Hard disk won't reset, status = %x\n", r);
  	return(ERR);
    }
***************
*** 447,453
  {
     /*DEBUG: loop looking for 0x20 in status (I don't know what that is!!) */
     /*		 10-Apr-87. G. Oliver					  */
!    int r, i; /* Some local storage */
  
     receive(HARDWARE, &w_mess);
  

--- 448,455 -----
  {
     /*DEBUG: loop looking for 0x20 in status (I don't know what that is!!) */
     /*		 10-Apr-87. G. Oliver					  */
!    int r; /* Some local storage */
!    long i;
  
     receive(HARDWARE, &w_mess);
  
***************
*** 453,459
  
     port_out(DMA_INIT, 0x07);	/* Disable int from DMA */
  
!    for(i=0; i<MAX_WIN_RETRY; ++i) {
  	port_in(WIN_STATUS, &r);
  	if(r & WST_INTERRUPT)
  		break;		/* Exit if end of int */

--- 455,461 -----
  
     port_out(DMA_INIT, 0x07);	/* Disable int from DMA */
  
!    for(i=64000 * 75; i; i--) {
  	port_in(WIN_STATUS, &r);
  	if(r & WST_INTERRUPT)
  		break;		/* Exit if end of int */
***************
*** 460,467
    }
  
  #if	 MONITOR
!    if(i > 10) {		/* Some arbitrary limit below which we don't really care */
! 	if(i == MAX_WIN_RETRY)
  		printf("wini: timeout waiting for INTERRUPT status\n");
  	else
  		printf("wini: %d loops waiting for INTERRUPT status\n", i);

--- 462,469 -----
    }
  
  #if	 MONITOR
!    if(i < 64000 * 70) {		/* Some arbitrary limit below which we don't really care */
! 	if(!i)
  		printf("wini: timeout waiting for INTERRUPT status\n");
  	else
  		printf("wini: %ld loops waiting for INTERRUPT status\n",
***************
*** 464,470
  	if(i == MAX_WIN_RETRY)
  		printf("wini: timeout waiting for INTERRUPT status\n");
  	else
! 		printf("wini: %d loops waiting for INTERRUPT status\n", i);
     }
  #endif	/* MONITOR */
  }

--- 466,473 -----
  	if(!i)
  		printf("wini: timeout waiting for INTERRUPT status\n");
  	else
! 		printf("wini: %ld loops waiting for INTERRUPT status\n",
! 		       64000 * 75 - i);
     }
  #endif	/* MONITOR */
  }
***************
*** 660,671
    /* Read the switches from the controller */
    port_in(WIN_SELECT, &i);
  
- #if AUTO_BIOS
-   /* Get the drive parameters from sector zero of the drive if the */
-   /* autoconfig mode of the controller has been selected */
- 
-   if(i & AUTO_ENABLE) {
- 
  	/* set up some phoney parameters so that we can read the first sector */
  	/* from the winchester. all drives will have one cylinder and one head */
  	/* but set up initially to the mini scribe drives from ibm */

--- 663,668 -----
    /* Read the switches from the controller */
    port_in(WIN_SELECT, &i);
  
  	/* set up some phoney parameters so that we can read the first sector */
  	/* from the winchester. all drives will have one cylinder and one head */
  	/* but set up initially to the mini scribe drives from ibm */
***************
*** 679,684
  	wini[DEV_PER_DRIVE].wn_low = wini[0].wn_low = 0L;
  	wini[DEV_PER_DRIVE].wn_size = wini[0].wn_size
  		   = (long)AUTO_CYLS * (long)AUTO_HEADS * (long)NR_SECTORS;
  	if(w_reset() != OK)
  	  panic("cannot setup for reading winchester parameter tables",0);
  

--- 676,687 -----
  	wini[DEV_PER_DRIVE].wn_low = wini[0].wn_low = 0L;
  	wini[DEV_PER_DRIVE].wn_size = wini[0].wn_size
  		   = (long)AUTO_CYLS * (long)AUTO_HEADS * (long)NR_SECTORS;
+ #if AUTO_BIOS
+   /* Get the drive parameters from sector zero of the drive if the */
+   /* autoconfig mode of the controller has been selected */
+ 
+   if(i & AUTO_ENABLE) {
+ 
  	if(w_reset() != OK)
  	  panic("cannot setup for reading winchester parameter tables",0);
  
***************
*** 695,701
  		panic("cannot read drive parameters from winchester",DEV_PER_DRIVE);
  
  	  /* copy the parameter tables into the structures for later use */
! 	  copy_param(&buf[AUTO_PARAM], &param1);
  
  	}
  

--- 698,704 -----
  		panic("cannot read drive parameters from winchester",DEV_PER_DRIVE);
  
  	  /* copy the parameter tables into the structures for later use */
! 	  copy_params(&buf[AUTO_PARAM], &param1);
  
  	}
  
***************
*** 710,716
  	  panic("cannot read drive parameters from winchester", 0);
  
  	/* copy the parameter tables into the structures for later use */
! 	copy_param(&buf[AUTO_PARAM], &param0);
  
  	   
     /* whoever compiled the kernel wanted the auto bios code included. if it

--- 713,719 -----
  	  panic("cannot read drive parameters from winchester", 0);
  
  	/* copy the parameter tables into the structures for later use */
! 	copy_params(&buf[AUTO_PARAM], &param0);
  
  	   
     /* whoever compiled the kernel wanted the auto bios code included. if it
***************
*** 720,725
  #endif
  
    /* Calculate the drive types */
    type_0 = i & 3;
    type_1 = (i >> 2) & 3;
  

--- 723,732 -----
  #endif
  
    /* Calculate the drive types */
+ #if RRL
+   type_0 = ((~i) >> 4) & 3;
+   type_1 = type_0;
+ #else
    type_0 = i & 3;
    type_1 = (i >> 2) & 3;
  #endif
***************
*** 722,727
    /* Calculate the drive types */
    type_0 = i & 3;
    type_1 = (i >> 2) & 3;
  
    /* Copy the parameter vector from the saved vector table */
    offset = vec_table[2 * 0x41];

--- 729,735 -----
  #else
    type_0 = i & 3;
    type_1 = (i >> 2) & 3;
+ #endif
  
    /* Copy the parameter vector from the saved vector table */
    offset = vec_table[2 * 0x41];
---------------------------  xt_wini.cdif END ----------------------
						Robert R. Hall
						hall@nosc.mil

ncoverby@ndsuvax.UUCP (Glen Overby) (11/09/88)

In article <803@nosc.NOSC.MIL> hall@nosc.NOSC.MIL (Robert R. Hall) writes:
>I now have the MINIX xt_wini driver working with my RRL disk drive.
>I am using the seagate ST2238 disk with Western WD-27x controller.

>--- 73,79 -----
>
>  /* Parameters for the disk drive. */
>  #define SECTOR_SIZE   512    /* physical sector size in bytes */
>! #define NR_SECTORS     26    /* number of sectors per track */

Caveat:

If you have an Adaptec RLL controler, this should be 25 because the
controler apparently uses one sector per track for bad-block mapping
(yes, one sector per track does seem a bit excessive, but that appears
to be the way they're doing it!)