[comp.os.minix] new at_wini.c

yip@ztivax.UUCP (Dr Yeung-Cho Ip) (12/20/89)

In article <868@ztivax.UUCP> I wrote:
>The problem with our ADAPTEC controller board was, that MINIX overwrites
>the  controller generated disk geometry parameters at boot up. When the
>"init_params" routine in the at_wini driver tried to read the RAM location,
>wich is referenced to by the vector 0x41, it allways got wrong disk parameters.
>We fixed this quick and dirty by hardcoding the right parameters into our
>at_wini.c .

Since I posted this, I revised the original 1.3 at_wini.c so that it now
handels our ADAPTEC controller. Besides, this new version is fully upwards
compatible with the old version. I tested it on our ADAPTEC controller
(ACB 2372B) and also on a standard controller/drive combination.

The only new thing this new version does is to read the disk parameters from
the array "vec_table", which is a copy of the DOS low ram locations, provided
the vector at 0x41 points to a location below VECTOR_BYTES-16. However, to 
make it work correctly, you have to adjust the constant VECTOR_BYTES in 
../kernel/const.h to 420 (decimal), and the definition of _vec_table at the end
of ../kernel/klib88.s to "_vec_table:  .zerow 210".

If you get the message:

wini: invalid drive parameter address for drive <x>: <addr_value>

during boot up, you know that the driver couldn't find the drive parameters for
some reason. By examining the <addr_value> you'll probably be able to figure
out what to do. If <addr_value> is below 0x400, further increase
VECTOR_BYTES and the vec_table array to contain these RAM addresses.

Good luck

Michael

Michael Franzen, c/o yip@ztivax, Siemens AG, Munich

PS: The following is a cdiff to the V1.3 at_wini.c!

----------------------cut here-----------------
*** /wini.c	Wed Dec 20 09:29:09 1989
--- wini.c	Wed Dec 20 09:17:18 1989
***************
*** 410,446 ****
  /* This routine is called at startup to initialize the partition table,O
   * the number of drives and the controller
  */
!   unsigned int i, segment, offset;
!   phys_bytes address;
!   extern phys_bytes umap();
!   extern int vec_table[];
! 
!   /* Copy the parameter vector from the saved vector table */
!   offset = vec_table[2 * 0x41];
!   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, (vir_bytes)buf, 16), 16L);
! 
!   /* Copy the parameters to the structures */
!   copy_params(buf, &wini[0]);
! 
!   /* Copy the parameter vector from the saved vector table */
!   offset = vec_table[2 * 0x46];
!   segment = vec_table[2 * 0x46 + 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, (vir_bytes)buf, 16), 16L);
! 
!   /* Copy the parameters to the structures */
!   copy_params(buf, &wini[5]);
  
    /* Get the nummer of drives from the bios */
    phys_copy(0x475L, umap(proc_addr(WINCHESTER), D, (vir_bytes)buf, 1), 1L);
    nr_drives = (int) *buf;
  
    /* Set the parameters in the drive structure */
    wini[0].wn_low = wini[5].wn_low = 0L;
  
--- 410,425 ----
  /* This routine is called at startup to initialize the partition table,
   * the number of drives and the controller
  */
!   unsigned int i;
!   extern phys_bytes umap();
  
    /* Get the nummer of drives from the bios */
    phys_copy(0x475L, umap(proc_addr(WINCHESTER), D, (vir_bytes)buf, 1), 1L);
    nr_drives = (int) *buf;
  
+   /* Get the drive parameters */
+   for (i=0; i < nr_drives; i++) get_params(i);
+ 
    /* Set the parameters in the drive structure */
    wini[0].wn_low = wini[5].wn_low = 0L;
  
***************
*** 471,501 ****
  }
  
  /*============================================================================*
!  *				copy_params				      *
!  *============================================================================*/
! PRIVATE copy_params(src, dest)
! register unsigned char *src;
! register struct wini *dest;
! {
! /* This routine copies the parameters from src to dest
!  * and sets the parameters for partition 0 and 5
! */
!   register int i;
!   long cyl, heads, sectors;
! 
!   for (i=0; i<5; i++) {
! 	dest[i].wn_heads = (int)src[2];
! 	dest[i].wn_precomp = *(int *)&src[5] >> 2;
! 	dest[i].wn_ctlbyte = (int)src[8];
! 	dest[i].wn_maxsec = (int)src[14];
!   }
!   cyl = (long)(*(int *)src);
!   heads = (long)dest[0].wn_heads;
!   sectors = (long)dest[0].wn_maxsec;
!   dest[0].wn_size = cyl * heads * sectors;
  }
  
  /*============================================================================*
   *				copy_prt				      *
   *============================================================================*/
  PRIVATE copy_prt(drive)
--- 450,511 ----
  }
  
  /*============================================================================*
!  *				get_params				      *
!  *============================================================================*/
! PRIVATE get_params(drive)
! unsigned int drive;
! {
! /* This routine gets the parameters for drive "drive" from the BIOS */
! 
!   unsigned int segment, offset, d;
!   phys_bytes address;
!   extern phys_bytes umap();
!   extern int vec_table[];
! 
!   d = 5*drive;
!   /* Copy the parameter vector from the saved vector table */
!   offset = vec_table[2 * (0x41 + d)];
!   segment = vec_table[2 * (0x41 + d) + 1];
! 
!   /* Calculate the address off the parameters and copy them to buf */
!   address = ((long)segment << 4) + offset;
!   if (address > 0xA0000L) /* Parameters are within bios rom */
!     phys_copy(address, umap(proc_addr(WINCHESTER), D, (vir_bytes)buf, 16), 16L);
!   else if (address > VECTOR_BYTES - 16)
!          printf("wini: invalid drive parameter address for drive %d: %lx\n", drive, address);
! 
!   /* Copy the parameters to the structures */
!   if (address <= VECTOR_BYTES - 16)
!     copy_params(((unsigned char *)vec_table) + (int)address, &wini[d]);
!   else copy_params(buf, &wini[d]);
  }
  
  /*============================================================================*
+  *				copy_params				      *
+  *============================================================================*/
+ PRIVATE copy_params(src, dest)
+ register unsigned char *src;
+ register struct wini *dest;
+ {
+ /* This routine copies the parameters from src to dest
+  * and sets the parameters for partition 0 and 5
+ */
+   register int i;
+   long cyl, heads, sectors;
+ 
+   for (i=0; i<5; i++) {
+ 	dest[i].wn_heads = (int)src[2];
+ 	dest[i].wn_precomp = *(int *)&src[5] >> 2;
+ 	dest[i].wn_ctlbyte = (int)src[8];
+ 	dest[i].wn_maxsec = (int)src[14];
+   }
+   cyl = (long)(*(int *)src);
+   heads = (long)dest[0].wn_heads;
+   sectors = (long)dest[0].wn_maxsec;
+   dest[0].wn_size = cyl * heads * sectors;
+ }
+ 
+ /*============================================================================*
   *				copy_prt				      *
   *============================================================================*/
  PRIVATE copy_prt(drive)