[comp.os.minix] WD1002-WX2 Controller Diffs for xt_wini.c

myxm@beta.UUCP (04/30/87)

Enclosed you will find a copy of the context diffs between the xt_wini.c
module and those submitted by Gary Oliver (go@orstcs.uucp). This file
should be suitable enough to run through patch if you have it running
on your BSD machine.

I have also hard coded a couple of the drive tables for a machine which
has the AutoConfig Western Digital BIOS. It turns out that Minix stomps
on the tables which are stored in lower ram. Hopefully a cleaner way to
read the drive tables is in the works. I have a couple of ideas...

Mike Mitchell
myxm@lanl.gov

---//---//---//---//---// TEAR HERE //---//---//---//---//---
*** xt_wini.c	Wed Apr 29 20:40:56 1987
--- wd_wini.c	Wed Apr 29 20:43:48 1987
***************
*** 27,37 ****
--- 27,46 ----
  #include "type.h"
  #include "proc.h"
  
+ #define	DEBUG	FALSE		/* TRUE: enable debugging messages */
+ #define	MONITOR	TRUE		/* TRUE: moniter performance */
+ #define NOBIOS	FALSE		/* TRUE: bios tables incorrect */
+ 				   
  /* I/O Ports used by winchester disk task. */
  #define WIN_DATA       0x320	/* winchester disk controller data register */
  #define WIN_STATUS     0x321	/* winchester disk controller status register */
  #define WIN_SELECT     0x322	/* winchester disk controller select port */
  #define WIN_DMA	       0x323	/* winchester disk controller dma register */
+ #define WST_REQ        0x001	/* request bit */
+ #define WST_INPUT      0x002	/* controller writing to cpu */
+ #define WST_BUS        0x004	/* command/status bit */
+ #define WST_BUSY       0x008	/* busy status */
+ #define WST_INTERRUPT  0x020	/* interrupt generated */
  #define DMA_ADDR       0x006	/* port for low 16 bits of DMA address */
  #define DMA_TOP        0x082	/* port for top 4 bits of 20-bit DMA addr */
  #define DMA_COUNT      0x007	/* port for DMA count (count =  bytes - 1) */
***************
*** 50,56 ****
  #define DMA_INT		   3 /* Command with dma and interrupt */
  #define INT		   2	/* Command with interrupt, no dma */
  #define NO_DMA_INT	   0	/* Command without dma and interrupt */
- #define CTRL_BYTE	   5 /* Control byte for controller */
  
  /* DMA channel commands. */
  #define DMA_READ        0x47	/* DMA read opcode */
--- 59,64 ----
***************
*** 75,85 ****
  PRIVATE struct wini {		/* main drive struct, one entry per drive */
    int wn_opcode;		/* DISK_READ or DISK_WRITE */
    int wn_procnr;		/* which proc wanted this operation? */
!   int wn_drive;			/* drive number addressed */
    int wn_cylinder;		/* cylinder number addressed */
    int wn_sector;		/* sector addressed */
    int wn_head;			/* head number addressed */
    int wn_heads;			/* maximum number of heads */
    long wn_low;			/* lowest cylinder of partition */
    long wn_size;			/* size of partition in blocks */
    int wn_count;			/* byte count */
--- 83,94 ----
  PRIVATE struct wini {		/* main drive struct, one entry per drive */
    int wn_opcode;		/* DISK_READ or DISK_WRITE */
    int wn_procnr;		/* which proc wanted this operation? */
!   int wn_drive;			/* drive number addressed (<< 5) */
    int wn_cylinder;		/* cylinder number addressed */
    int wn_sector;		/* sector addressed */
    int wn_head;			/* head number addressed */
    int wn_heads;			/* maximum number of heads */
+   int wn_ctrl_byte;		/* command control byte */
    long wn_low;			/* lowest cylinder of partition */
    long wn_size;			/* size of partition in blocks */
    int wn_count;			/* byte count */
***************
*** 102,109 ****
--- 111,123 ----
  	int reduced_wr;		/* First cylinder with reduced write current */
  	int wr_precomp;		/* First cylinder with write precompensation */
  	int max_ecc;		/* Maximum ECC burst length */
+ 	int ctrl_byte;		/* control code byte */
  } param0, param1;
  
+ #if DEBUG
+ #define port_out(port,val) xport_out(port,val)
+ #endif
+ 
  /*===========================================================================*
   *				winchester_task				     * 
   *===========================================================================*/
***************
*** 114,120 ****
    int r, caller, proc_nr;
  
    /* First initialize the controller */
!   init_param();
  
    /* Here is the main loop of the disk task.  It waits for a message, carries
     * it out, and sends a reply.
--- 128,134 ----
    int r, caller, proc_nr;
  
    /* First initialize the controller */
!   init_params();
  
    /* Here is the main loop of the disk task.  It waits for a message, carries
     * it out, and sends a reply.
***************
*** 165,173 ****
    if (m_ptr->COUNT != BLOCK_SIZE)
  	return(EINVAL);
    wn = &wini[device];		/* 'wn' points to entry for this drive */
!   wn->wn_drive = device/DEV_PER_DRIVE;	/* save drive number */
!   if (wn->wn_drive >= nr_drives)
! 	return(EIO);
    wn->wn_opcode = m_ptr->m_type;	/* DISK_READ or DISK_WRITE */
    if (m_ptr->POSITION % BLOCK_SIZE != 0)
  	return(EINVAL);
--- 179,185 ----
    if (m_ptr->COUNT != BLOCK_SIZE)
  	return(EINVAL);
    wn = &wini[device];		/* 'wn' points to entry for this drive */
! 
    wn->wn_opcode = m_ptr->m_type;	/* DISK_READ or DISK_WRITE */
    if (m_ptr->POSITION % BLOCK_SIZE != 0)
  	return(EINVAL);
***************
*** 264,280 ****
  
    /* The command is issued by outputing 6 bytes to the controller chip. */
    command[0] = (wn->wn_opcode == DISK_READ ? WIN_READ : WIN_WRITE);
!   command[1] = (wn->wn_head | (wn->wn_drive << 5));
    command[2] = (((wn->wn_cylinder & 0x0300) >> 2) | wn->wn_sector);
    command[3] = (wn->wn_cylinder & 0xFF);
    command[4] = BLOCK_SIZE/SECTOR_SIZE;
!   command[5] = CTRL_BYTE;
    if (com_out(DMA_INT) != OK)
  	return(ERR);
  
    port_out(DMA_INIT, 3);	/* initialize DMA */
    /* Block, waiting for disk interrupt. */
!   receive(HARDWARE, &w_mess);
  
    /* Get controller status and check for errors. */
    if (win_results(wn) == OK)
--- 276,292 ----
  
    /* The command is issued by outputing 6 bytes to the controller chip. */
    command[0] = (wn->wn_opcode == DISK_READ ? WIN_READ : WIN_WRITE);
!   command[1] = wn->wn_head | wn->wn_drive;
    command[2] = (((wn->wn_cylinder & 0x0300) >> 2) | wn->wn_sector);
    command[3] = (wn->wn_cylinder & 0xFF);
    command[4] = BLOCK_SIZE/SECTOR_SIZE;
!   command[5] = wn->wn_ctrl_byte;
    if (com_out(DMA_INT) != OK)
  	return(ERR);
  
    port_out(DMA_INIT, 3);	/* initialize DMA */
    /* Block, waiting for disk interrupt. */
!   w_wait_int();
  
    /* Get controller status and check for errors. */
    if (win_results(wn) == OK)
***************
*** 300,322 ****
  
    port_in(WIN_DATA, &status);
    port_out(WIN_DMA, 0);
!   if (!(status & 2))
  	return(OK);
    command[0] = WIN_SENSE;
!   command[1] = (wn->wn_drive << 5);
    if (com_out(NO_DMA_INT) != OK)
  	return(ERR);
  
    /* Loop, extracting bytes from WIN */
    for (i = 0; i < MAX_RESULTS; i++) {
! 	if (hd_wait(1) != OK)
  		return(ERR);
  	port_in(WIN_DATA, &status);
  	wn->wn_results[i] = status & BYTE;
    }
!   if (wn->wn_results[0] & 63)
  	return(ERR);
!   else
  	return(OK);
  }
  
--- 312,342 ----
  
    port_in(WIN_DATA, &status);
    port_out(WIN_DMA, 0);
!   if (!(status & 2))		/* test "error" bit from last command */
  	return(OK);
    command[0] = WIN_SENSE;
!   command[1] = wn->wn_drive;
    if (com_out(NO_DMA_INT) != OK)
  	return(ERR);
  
    /* Loop, extracting bytes from WIN */
    for (i = 0; i < MAX_RESULTS; i++) {
! 	if (hd_wait(WST_REQ) != OK)
  		return(ERR);
  	port_in(WIN_DATA, &status);
  	wn->wn_results[i] = status & BYTE;
    }
!   if(hd_wait(WST_REQ) != OK)
!   	return(ERR);
!   
!   port_in(WIN_DATA,&status);
!   
!   if(((status & 2) != 0) || (wn->wn_results[0] & 0x3f)) {
! #if DEBUG
! 	printf("\nwin_results: results[0] = %x", wn->wn_results[0]);
! #endif
  	return(ERR);
!   } else
  	return(OK);
  }
  
***************
*** 331,340 ****
   * can only write to it when it is listening, and it decides when to listen.
   * If the controller refuses to listen, the WIN chip is given a hard reset.
   */
  
    if (w_need_reset) return;	/* if controller is not listening, return */
!   if (hd_wait(1) == OK)
! 	port_out(WIN_DATA, val);
  }
  
  /*===========================================================================*
--- 351,364 ----
   * can only write to it when it is listening, and it decides when to listen.
   * If the controller refuses to listen, the WIN chip is given a hard reset.
   */
+   int r;
  
    if (w_need_reset) return;	/* if controller is not listening, return */
!   do {
!   	port_in(WIN_STATUS,&r);
!   } while ((r & (WST_REQ | WST_BUSY)) == WST_BUSY);
! 
!   port_out(WIN_DATA,val);
  }
  
  /*===========================================================================*
***************
*** 346,408 ****
   * like the controller refusing to respond.
   */
  
!   int r = 1, i;
  
    /* Strobe reset bit low. */
!   port_out(WIN_STATUS, r);
!   for (i = 0; i < 10000; i++) {
! 	port_in(WIN_STATUS, &r);
! 	if ( (r&01) == 0)break;
    }
-   if (r & 2) {
- 	printf("Hard disk won't reset\n");
- 	return(ERR);
-   }
  
    /* Reset succeeded.  Tell WIN drive parameters. */
    w_need_reset = FALSE;
  
!   return(win_init());
  }
  
! /*===========================================================================*
!  *				win_init				     * 
!  *===========================================================================*/
! PRIVATE win_init()
! {
! /* Routine to initialize the drive parameters after boot or reset */
  
!   register int i;
  
!   command[0] = WIN_SPECIFY;		/* Specify some parameters */
!   command[1] = 0;			/* Drive 0 */
    if (com_out(NO_DMA_INT) != OK)	/* Output command block */
  	return(ERR);
    lock();
  
    /* No. of cylinders (high byte) */
!   win_out(param0.nr_cyl >> 8);
  
    /* No. of cylinders (low byte) */
!   win_out(param0.nr_cyl & 0xFF);
  
    /* No. of heads */
!   win_out(param0.nr_heads);
  
    /* Start reduced write (high byte) */
!   win_out(param0.reduced_wr >> 8);
  
    /* Start reduced write (low byte) */
!   win_out(param0.reduced_wr & 0xFF);
  
    /* Start write precompensation (high byte) */
!   win_out(param0.wr_precomp >> 8);
  
    /* Start write precompensation (low byte) */
!   win_out(param0.wr_precomp & 0xFF);
  
    /* Ecc burst length */
!   win_out(param0.max_ecc);
    unlock();
  
    if (check_init() != OK) {	/* See if controller accepted parameters */
--- 370,504 ----
   * like the controller refusing to respond.
   */
  
!   int r, i;
  
    /* Strobe reset bit low. */
!   port_out(WIN_STATUS,0);
!   
!    for (i = 1000; i; --i)
!    	;	/* allow drive to spin for a bit */
! 
!   for (i = 0; i < MAX_WIN_RETRY; i++) {
!   	port_out(WIN_SELECT,0);
!   	port_in(WIN_STATUS,&r);
!   	if (r & 0x30)
!   		return(ERR);
!   	
!   	if ((r & (WST_BUSY | WST_BUS | WST_REQ)) ==
!   		(WST_BUSY | WST_BUS | WST_REQ))
!   		break;
    }
  
+   if (i == MAX_WIN_RETRY) {
+   	printf("Hard disk won't reset\n");
+   	return(ERR);
+   }
+   
    /* Reset succeeded.  Tell WIN drive parameters. */
    w_need_reset = FALSE;
  
!   if (win_specify(0,&param0) != OK)
!   	return(ERR);
!   	
! #if DEBUG
!   printf("\nw_reset: drive 0 specified");
! #endif
! 
!   if ((nr_drives > 1) && (win_specify(1,&param1) != OK))
!   	return(ERR);
!   	
! #if DEBUG
!   printf("\nw_reset: drive 1 specified");
! #endif
! 
!   for (i = 0; i < nr_drives; i++) {
!   	command[0] = WIN_RECALIBRATE;
!   	command[1] = i << 5;
!   	command[5] = wini[i * DEV_PER_DRIVE].wn_ctrl_byte;
! #if DEBUG
!  	printf("\nw_reset: recal %d, ccb = %x", i, command[5]);
! #endif
! 	if (com_out(INT) != OK)
! 		return(ERR);
! 		
! 	w_wait_int();
! 	
! 	if (win_results(&wini[i * DEV_PER_DRIVE]) != OK) {
! 		w_need_reset = TRUE;
! #if DEBUG
! 		printf("\nw_reset: recal error");
! #endif
! 		return(ERR);
! 	}
!   }
!   return(OK);
  }
  
! /*============================================================================*
!  *                             w_wait_int                                     *
!  *============================================================================*/
!  PRIVATE w_wait_int()
!  {
!  	int r, i;
!  	
!  	receive(HARDWARE, &w_mess);
!  	
!  	port_out(DMA_INIT, 0x07);
!  	
!  	for (i = 0; i < MAX_WIN_RETRY; ++i) {
!  		port_in(WIN_STATUS, &r);
!  		if (r & WST_INTERRUPT)
!  			break;
! 	}
! 	
! #if MONITOR
! 	if (i > 10) {
! 		if (i == MAX_WIN_RETRY)
! 			printf("wini: timeout waiting for interrupt\n");
! 		else
! 			printf("wini: %d loops waiting for interrupt\n", i);
! 	}
! #endif
! }
  
! /*============================================================================*
!  *                            win_specify                                     *
!  *============================================================================*/
!  PRIVATE win_specify(drive, paramp)
!   int drive;
!   struct param *paramp;
!   {
  
!   command[0] = WIN_SPECIFY;
!   command[1] = drive << 5;
! 
    if (com_out(NO_DMA_INT) != OK)	/* Output command block */
  	return(ERR);
    lock();
  
    /* No. of cylinders (high byte) */
!   win_out(paramp->nr_cyl >> 8);
  
    /* No. of cylinders (low byte) */
!   win_out(paramp->nr_cyl);
  
    /* No. of heads */
!   win_out(paramp->nr_heads);
  
    /* Start reduced write (high byte) */
!   win_out(paramp->reduced_wr >> 8);
  
    /* Start reduced write (low byte) */
!   win_out(paramp->reduced_wr);
  
    /* Start write precompensation (high byte) */
!   win_out(paramp->wr_precomp >> 8);
  
    /* Start write precompensation (low byte) */
!   win_out(paramp->wr_precomp);
  
    /* Ecc burst length */
!   win_out(paramp->max_ecc);
    unlock();
  
    if (check_init() != OK) {	/* See if controller accepted parameters */
***************
*** 409,463 ****
  	w_need_reset = TRUE;
  	return(ERR);
    }
! 
!   if (nr_drives > 1) {
! 	command[1] = (1 << 5);			/* Drive 1 */
! 	if (com_out(NO_DMA_INT) != OK)		/* Output command block */
! 		return(ERR);
! 	lock();
! 
! 	/* No. of cylinders (high byte) */
! 	win_out(param1.nr_cyl >> 8);
! 
! 	/* No. of cylinders (low byte) */
! 	win_out(param1.nr_cyl & 0xFF);
! 
! 	/* No. of heads */
! 	win_out(param1.nr_heads);
! 
! 	/* Start reduced write (high byte) */
! 	win_out(param1.reduced_wr >> 8);
! 
! 	/* Start reduced write (low byte) */
! 	win_out(param1.reduced_wr & 0xFF);
! 
! 	/* Start write precompensation (high byte) */
! 	win_out(param1.wr_precomp >> 8);
! 
! 	/* Start write precompensation (low byte) */
! 	win_out(param1.wr_precomp & 0xFF);
! 
! 	/* Ecc burst length */
! 	win_out(param1.max_ecc);
! 	unlock();
! 	if (check_init() != OK) {  /* See if controller accepted parameters */
! 		w_need_reset = TRUE;
! 		return(ERR);
! 	}
!   }
!   for (i=0; i<nr_drives; i++) {
! 	command[0] = WIN_RECALIBRATE;
! 	command[1] = i << 5;
! 	command[5] = CTRL_BYTE;
! 	if (com_out(INT) != OK)
! 		return(ERR);
! 	receive(HARDWARE, &w_mess);
! 	if (win_results() != OK) {
! 		w_need_reset = TRUE;
! 		return(ERR);
! 	}
!   }
!   return(OK);
  }
  
  /*============================================================================*
--- 505,512 ----
  	w_need_reset = TRUE;
  	return(ERR);
    }
!   else
! 	return(OK);
  }
  
  /*============================================================================*
***************
*** 466,479 ****
  PRIVATE check_init()
  {
  /* Routine to check if controller accepted the parameters */
!   int r;
! 
!   if (hd_wait(2) == OK) {
! 	  port_in(WIN_DATA, &r);
! 	  if (r & 2)
! 		return(ERR);
  	  else
  		return(OK);
    }
  }
  
--- 515,540 ----
  PRIVATE check_init()
  {
  /* Routine to check if controller accepted the parameters */
!   int r, s;
!   
!   if (hd_wait(WST_REQ | WST_INPUT) == OK) {
!   	port_in(WIN_DATA,&r);
!   	do {
!   		port_in(WIN_STATUS,&s);
!   	} while (s & WST_BUSY);
!   	if (r & 2) {
! #if DEBUG
!   		printf("\ncheck_init: error bit set in %x", r);
! #endif
!   		return(ERR);
!   	}
  	  else
  		return(OK);
+   } else {
+ #if DEBUG
+   	printf("\ncheck_init: INPUT not active");
+ #endif
+   	return(ERR);
    }
  }
  
***************
*** 487,495 ****
    int r;
  
    command[0] = WIN_ECC_READ;
!   if (com_out(NO_DMA_INT) == OK && hd_wait(1) == OK) {
  	port_in(WIN_DATA, &r);
! 	if (hd_wait(1) == OK) {
  		port_in(WIN_DATA, &r);
  		if (r & 1)
  			w_need_reset = TRUE;
--- 548,556 ----
    int r;
  
    command[0] = WIN_ECC_READ;
!   if (com_out(NO_DMA_INT) == OK && hd_wait(WST_REQ) == OK) {
  	port_in(WIN_DATA, &r);
! 	if (hd_wait(WST_REQ) == OK) {
  		port_in(WIN_DATA, &r);
  		if (r & 1)
  			w_need_reset = TRUE;
***************
*** 501,508 ****
  /*============================================================================*
   *				hd_wait					      *
   *============================================================================*/
! PRIVATE hd_wait(bit)
! register int bit;
  {
  /* Wait until the controller is ready to receive a command or send status */
  
--- 562,569 ----
  /*============================================================================*
   *				hd_wait					      *
   *============================================================================*/
! PRIVATE hd_wait(bits)
! register int bits;
  {
  /* Wait until the controller is ready to receive a command or send status */
  
***************
*** 511,521 ****
  
    do {
  	port_in(WIN_STATUS, &r);
! 	r &= bit;
!   } while ((i++ < MAX_WIN_RETRY) && !r);
  
    if (i >= MAX_WIN_RETRY) {
  	w_need_reset = TRUE;
  	return(ERR);
    } else
  	return(OK);
--- 572,585 ----
  
    do {
  	port_in(WIN_STATUS, &r);
! 	r &= bits;
!   } while ((i++ < MAX_WIN_RETRY) && r != bits);
  
    if (i >= MAX_WIN_RETRY) {
  	w_need_reset = TRUE;
+ #if DEBUG
+ 	printf("\nhd_wait: timout waiting for %x (%x)", bits, r);
+ #endif
  	return(ERR);
    } else
  	return(OK);
***************
*** 529,555 ****
  {
  /* Output the command block to the winchester controller and return status */
  
! 	register int i = 0;
  	int r;
  
- 	port_out(WIN_SELECT, mode);
  	port_out(WIN_DMA, mode);
  	for (i=0; i<MAX_WIN_RETRY; i++) {
  		port_in(WIN_STATUS, &r);
! 		if ((r & 0x0F) == 0x0D)
  			break;
  	}
  	if (i == MAX_WIN_RETRY) {
  		w_need_reset = TRUE;
  		return(ERR);
  	}
  	lock();
! 	for (i=0; i<6; i++)
! 		port_out(WIN_DATA, command[i]);
  	unlock();
! 	port_in(WIN_STATUS, &r);
! 	if (r & 1) {
! 		w_need_reset = TRUE;
  		return(ERR);
  	} else
  		return(OK);
--- 593,633 ----
  {
  /* Output the command block to the winchester controller and return status */
  
! 	register int i;
  	int r;
  
  	port_out(WIN_DMA, mode);
+ 	port_out(WIN_SELECT, mode);
  	for (i=0; i<MAX_WIN_RETRY; i++) {
  		port_in(WIN_STATUS, &r);
! 		if (r & WST_BUSY)
  			break;
  	}
  	if (i == MAX_WIN_RETRY) {
  		w_need_reset = TRUE;
+ #if DEBUG
+ 		printf("\ncom_out: retry exceeded, status = %x", r);
+ #endif
  		return(ERR);
  	}
  	lock();
! 	for (i = 0; i < 6; i++) {
! 		if (hd_wait(WST_REQ) != OK)
! 			break;
! 		port_in(WIN_STATUS, &r);
! #if DEBUG
! 		printf("\nWIN_STATUS = %x", r);
! #endif
! 		if((r & (WST_BUSY|WST_BUS|WST_REQ)) !=
! 			(WST_BUSY|WST_BUS|WST_REQ))
! 			break;
! 		port_out(WIN_DATA,command[i]);
! 	}
  	unlock();
! 	if (i != 6) {
! #if DEBUG
! 		printf("\ncom_out: packet write aborted, byte %d status %x", i, r);
! #endif
  		return(ERR);
  	} else
  		return(OK);
***************
*** 562,568 ****
  {
  /* This routine is called at startup to initialize the partition table,
   * the number of drives and the controller
! */
    unsigned int i, segment, offset;
    int type_0, type_1;
    phys_bytes address;
--- 640,646 ----
  {
  /* This routine is called at startup to initialize the partition table,
   * the number of drives and the controller
!  */
    unsigned int i, segment, offset;
    int type_0, type_1;
    phys_bytes address;
***************
*** 581,592 ****
    segment = vec_table[2 * 0x41 + 1];
  
    /* Calculate the address off the parameters and copy them to buf */
!   address = ((long)segment << 4) + offset;
    phys_copy(address, umap(proc_addr(WINCHESTER), D, buf, 64), 64L);
  
    /* Copy the parameters to the structures */
!   copy_param((&buf[type_0 * 16]), &param0);
!   copy_param((&buf[type_1 * 16]), &param1);
  
    /* Get the nummer of drives from the bios */
    phys_copy(0x475L, umap(proc_addr(WINCHESTER), D, buf, 1), 1L);
--- 659,690 ----
    segment = vec_table[2 * 0x41 + 1];
  
    /* Calculate the address off the parameters and copy them to buf */
!   address = ((phys_bytes)segment << 4) + offset;
    phys_copy(address, umap(proc_addr(WINCHESTER), D, buf, 64), 64L);
  
    /* Copy the parameters to the structures */
!   /* Those with WD AutoConfig BIOS will have to hardcode the drive
!    * parameters here. Working on a patch which should sense the
!    * AutoConfig BIOS and read the tables from the magic locations
!    * on the hard disk itself (head 0, cyl 0, sector 1) and pop
!    * the information in here */
! #if NOBIOS
!   param0.nr_cyl = 733;
!   param0.nr_heads = 5;
!   param0.reduced_wr = 734;
!   param0.wr_precomp = 300;
!   param0.max_ecc = 5;
!   param0.ctrl_byte = 6;
!   param1.nr_cyl = 612;
!   param1.nr_heads = 4;
!   param1.reduced_wr = 300;
!   param1.wr_precomp = 300;
!   param1.max_ecc = 5;
!   param1.ctrl_byte = 5;
! #else
!   copy_param(&buf[type_0 * 16], &param0);
!   copy_param(&buf[type_1 * 16], &param1);
! #endif
  
    /* Get the nummer of drives from the bios */
    phys_copy(0x475L, umap(proc_addr(WINCHESTER), D, buf, 1), 1L);
***************
*** 593,614 ****
    nr_drives = (int) *buf;
  
    /* Set the parameters in the drive structure */
!   for (i=0; i<5; i++)
! 	wini[i].wn_heads = param0.nr_heads;
!   wini[0].wn_low = wini[5].wn_low = 0L;
!   wini[0].wn_size = (long)((long)param0.nr_cyl * (long)param0.nr_heads * (long)NR_SECTORS);
!   for (i=5; i<10; i++)
! 	wini[i].wn_heads = param1.nr_heads;
!   wini[5].wn_size = (long)((long)param1.nr_cyl * (long)param1.nr_heads * (long)NR_SECTORS);
  
- 
    /* Initialize the controller */
!   if ((nr_drives > 0) && (win_init() != OK))
  		nr_drives = 0;
  
    /* Read the partition table for each drive and save them */
    for (i = 0; i < nr_drives; i++) {
! 	w_mess.DEVICE = i * 5;
  	w_mess.POSITION = 0L;
  	w_mess.COUNT = BLOCK_SIZE;
  	w_mess.ADDRESS = (char *) buf;
--- 691,719 ----
    nr_drives = (int) *buf;
  
    /* Set the parameters in the drive structure */
!   for (i = 0; i < DEV_PER_DRIVE; i++) {
!   	wini[i].wn_heads = param0.nr_heads;
!   	wini[i].wn_ctrl_byte = param0.ctrl_byte;
!   	wini[i].wn_drive = 0 << 5;
!   }
!   wini[0].wn_low = wini[DEV_PER_DRIVE].wn_low = 0L;
!   wini[0].wn_size = (long)((long)param0.nr_cyl * (long)param0.nr_heads *
!   	(long)NR_SECTORS);
!   for (i = DEV_PER_DRIVE; i < (2*DEV_PER_DRIVE); i++) {
!   	wini[i].wn_heads = param1.nr_heads;
!   	wini[i].wn_ctrl_byte = param1.ctrl_byte;
!   	wini[i].wn_drive = 1 << 5;
!   }
!   wini[DEV_PER_DRIVE].wn_size = (long)((long)param1.nr_cyl *
!   	(long)param1.nr_heads * (long)NR_SECTORS);
  
    /* Initialize the controller */
!   if ((nr_drives > 0) && (w_reset() != OK))
  		nr_drives = 0;
  
    /* Read the partition table for each drive and save them */
    for (i = 0; i < nr_drives; i++) {
! 	w_mess.DEVICE = i * DEV_PER_DRIVE;
  	w_mess.POSITION = 0L;
  	w_mess.COUNT = BLOCK_SIZE;
  	w_mess.ADDRESS = (char *) buf;
***************
*** 616,622 ****
  	w_mess.m_type = DISK_READ;
  	if (w_do_rdwt(&w_mess) != BLOCK_SIZE)
  		panic("Can't read partition table of winchester ", i);
! 	copy_prt(i * 5);
    }
  }
  
--- 721,730 ----
  	w_mess.m_type = DISK_READ;
  	if (w_do_rdwt(&w_mess) != BLOCK_SIZE)
  		panic("Can't read partition table of winchester ", i);
! 	copy_prt(i * DEV_PER_DRIVE);
! #if DEBUG
! 	printf("\ninit_params: drive %d processed", i);
! #endif
    }
  }
  
***************
*** 628,634 ****
  register struct param *dest;
  {
  /* This routine copies the parameters from src to dest
!  * and sets the parameters for partition 0 and 5
  */
  
    dest->nr_cyl = *(int *)src;
--- 736,742 ----
  register struct param *dest;
  {
  /* This routine copies the parameters from src to dest
!  * and sets the parameters for partition 0 and DEV_PER_DRIVE
  */
  
    dest->nr_cyl = *(int *)src;
***************
*** 636,641 ****
--- 744,750 ----
    dest->reduced_wr = *(int *)&src[3];
    dest->wr_precomp = *(int *)&src[5];
    dest->max_ecc = (int)src[7];
+   dest->ctrl_byte = (int)src[8];
  }
  
  /*============================================================================*
***************
*** 661,668 ****
--- 770,781 ----
  		adjust = wn->wn_low;
  		wn->wn_low = (wn->wn_low/(BLOCK_SIZE/SECTOR_SIZE)+1)*(BLOCK_SIZE/SECTOR_SIZE);
  		adjust = wn->wn_low - adjust;
+ 
  	}
  	wn->wn_size = *(long *)&buf[offset + sizeof(long)] - adjust;
+ #if DEBUG
+ 	printf("\nPartition %d, Low = %D, Size = %D\n",i,wn->wn_low,wn->wn_size);
+ #endif
    }
    sort(&wini[drive + 1]);
  }
***************
*** 689,691 ****
--- 802,821 ----
    *first = *second;
    *second = tmp;
  }
+ 
+ #if DEBUG
+ #undef port_out
+ xport_out(port,val)
+ int port, val;
+ {
+ 	static int __ctr = 0;
+ 	
+ 	printf(" (%x) = %x", port, val);
+ 	if(++__ctr > 4) {
+ 		printf("\n");
+ 		__ctr = 0;
+ 	}
+ 	port_out(port,val);
+ }
+ #endif
+