Path: utzoo!utgpu!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!mcsun!unido!ztivax!yip From: yip@ztivax.UUCP (Dr Yeung-Cho Ip) Newsgroups: comp.os.minix Subject: new at_wini.c (Was: RE: How to get hard disk parameters ...) Keywords: at_wini.c Message-ID: <885@ztivax.UUCP> Date: 20 Dec 89 10:26:57 GMT References: <26317@sequent.UUCP> <901@crash.cts.com> <832@ocsmd.ocs.com> <83311@linus.UUCP> <868@ztivax.UUCP> Reply-To: yip@ztivax.UUCP (Dr Yeung-Cho Ip) Organization: Siemens AG in Munich, W-Germany Lines: 192 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 : during boot up, you know that the driver couldn't find the drive parameters for some reason. By examining the you'll probably be able to figure out what to do. If 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)