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)