[comp.os.minix] harddisk driver fixes 2 of 2

hgm@beta.UUCP (05/06/87)

Here is part 2 of 2.



----------------Concatenate below onto first part--------------------------
! 	port_in(WIN_STATUS, &r);
! 	if(r & WST_INTERRUPT)
! 		break;		/* Exit if end of int */
     }
  
! #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);
!    }
! #endif	/* MONITOR */
! }
! 
! 
! /*============================================================================*
!  *				win_specify				      *
!  *============================================================================*/
! PRIVATE win_specify(drive, paramp)
! int drive;
! struct param *paramp;
! {
!   command[0] = WIN_SPECIFY;		/* Specify some parameters */
!   command[1] = drive << 5;		/* Drive number */
! 
    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 */
  	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);
    }
  }
  
--- 520,549 ----
  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);		/* Loop while still busy */
! 
!        if (r & 2)		/* Test error bit */
! 		{
! #if	DEBUG
! 		printf("\ncheck_init: error bit set in %x", r);
! #endif	/* DEBUG */
  		return(ERR);
+ 		}
  	else
  		return(OK);
+   } else
+ 	{
+ #if	DEBUG
+ 	printf("\ncheck_init: INPUT not active");
+ #endif	/* DEBUG */
+ 	return (ERR);	/* Missing from original: 11-Apr-87 G.O. */
  	}
  }
  
***************
*** 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;
--- 557,565 ----
    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 */
  
--- 571,578 ----
  /*============================================================================*
   *				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);
--- 581,594 ----
  
    do {
  	port_in(WIN_STATUS, &r);
! 	r &= bits;
!   } while ((i++ < MAX_WIN_RETRY) && r != bits); 	/* Wait for ALL bits */
  
    if (i >= MAX_WIN_RETRY) {
  	w_need_reset = TRUE;
+ #if	DEBUG
+ 	printf("\nhd_wait: timeout waiting for %x (%x)", bits, r);
+ #endif	/* DEBUG */
  	return(ERR);
    } else
  	return(OK);
***************
*** 529,557 ****
  {
  /* 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);
  }
  
--- 602,651 ----
  {
  /* 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	/* DEBUG */
  		return(ERR);
  	}
+ 
+ 
  	lock();
! 
! 	for (i=0; i<6; i++) {
! 		if(hd_wait(WST_REQ) != OK)
! 			break;		/* No data request pending */
! 
! 		port_in(WIN_STATUS, &r);
! 
! 		if((r & (WST_BUSY | WST_BUS | WST_INPUT)) !=
! 			(WST_BUSY | WST_BUS))
! 			break;
! 
  		port_out(WIN_DATA, command[i]);
+ 	}
+ 
  	unlock();
! 
! 	if(i != 6) {
! #if	DEBUG
! 		printf("\ncom_out: packet write aborted, status=%x", r);
! #endif	/* DEBUG */
  		return (ERR);
! 	}
! 	else
  		return(OK);
  }
  
***************
*** 573,580 ****
    port_in(WIN_SELECT, &i);
  
    /* Calculate the drive types */
!   type_0 = (i >> 2) & 3;
!   type_1 = i & 3;
  
    /* Copy the parameter vector from the saved vector table */
    offset = vec_table[2 * 0x41];
--- 667,674 ----
    port_in(WIN_SELECT, &i);
  
    /* 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];
***************
*** 581,614 ****
    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);
    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;
--- 675,717 ----
    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 */
!   copy_param(&buf[type_0 * 16], &param0);
!   copy_param(&buf[type_1 * 16], &param1);
  
!   /* Get the number of drives from the bios */
    phys_copy(0x475L, umap(proc_addr(WINCHESTER), D, buf, 1), 1L);
    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;	/* Set drive number */
!   }
! 
!   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;	/* Set drive number */
!   }
!   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);
    }
  }
  
--- 719,728 ----
  	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	/* DEBUG */
    }
  }
  
***************
*** 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;
--- 734,740 ----
  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 ****
--- 742,748 ----
    dest->reduced_wr = *(int *)&src[3];
    dest->wr_precomp = *(int *)&src[5];
    dest->max_ecc = (int)src[7];
+   dest->ctrl_byte = (int)src[8];
  }
  
  /*============================================================================*
***************
*** 689,691 ****
--- 796,816 ----
    *first = *second;
    *second = tmp;
  }
+ 
+ #if	DEBUG
+ #undef	port_out
+ /* Write values written to ports with debugging version of 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	/* DEBUG */
--------------------------------Cut here------------------------------

Harry McGavran
hgm@LANL.GOV
Los Alamos National Laboratory
MS-B294, Group C-8
Los Alamos, New Mexico 87545
505/667-4050