myxm@beta.UUCP (05/08/87)
What follows are diffs from the original xt_wini.c for the Western Digital Controller. The diffs presented here come from a couple of sources. Thanks to Gary Oliver for the original set of diffs which allowed the Western Digital Controller to operate fairly well under Minix. Thanx to Harry McGavren for the second set of diffs which made the winchester controller a little more robust and operate on turbo clones better. I have also incorperated some code which will sense if the WD controller is being used in auto-configuration mode and will retrieve the drive parameter tables from the hard disk. This will give some Minix users greater flexibility as to what drives Minix will now work with. (Hopefully if you are able to talk to your drive with DOS, then you should be able to now have Minix operate with it). These patches were prompted by the fact that I have a Seagate 4038 on my controller and there are no drive tables in the ROM for this particular drive. I figured that the cleanest way to patch xt_wini.c was to force it to query the drive for the actual parameters. The context diffs which follow are suitable for use with the most recent version of patch. To make use of these diffs, place a copy of xt_wini.c (original) and these diffs in the same directory and use the command "patch -l xt_wini.c < xt_wini.diffs". You should then wind up with an updated copy of xt_wini.c. Have fun. #include <stddisclaimer.h> Mike Mitchell myxm@lanl.gov | ...!{cmcl2,ucbvax,decvax}!lanl!myxm ---/---/---/---/---/---/--- TEAR HERE ---/---/---/---/---/---/--- *** xt_wini.c Thu May 7 23:48:28 1987 --- xt_wini.new Thu May 7 23:50:21 1987 *************** *** 27,35 **** --- 27,44 ---- #include "type.h" #include "proc.h" + #define AUTO_BIOS TRUE /* TRUE: working with western autoconfig bios */ + #define DEBUG FALSE /* TRUE: enable debug messages */ + #define MONITOR TRUE /* TRUE: monitor performance of busy loops */ + /* 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 WST_REQ 0x001 /* Request bit */ + #define WST_INPUT 0x002 /* Set if controller is writing to cpu */ + #define WST_BUS 0x004 /* Command/status bit */ + #define WST_BUSY 0x008 /* Busy */ + #define WST_INTERRUPT 0x020 /* Interrupt generated ?? */ #define WIN_SELECT 0x322 /* winchester disk controller select port */ #define WIN_DMA 0x323 /* winchester disk controller dma register */ #define DMA_ADDR 0x006 /* port for low 16 bits of DMA address */ *************** *** 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 ---- *************** *** 67,85 **** #define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ #define MAX_RESULTS 4 /* max number of bytes controller returns */ #define NR_DEVICES 10 /* maximum number of drives */ ! #define MAX_WIN_RETRY 10000 /* max # times to try to output to WIN */ #define PART_TABLE 0x1C6 /* IBM partition table starts here in sect 0 */ #define DEV_PER_DRIVE 5 /* hd0 + hd1 + hd2 + hd3 + hd4 = 5 */ /* Variables. */ 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 */ --- 75,106 ---- #define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ #define MAX_RESULTS 4 /* max number of bytes controller returns */ #define NR_DEVICES 10 /* maximum number of drives */ ! #define MAX_WIN_RETRY 32000 /* max # times to try to output to WIN */ #define PART_TABLE 0x1C6 /* IBM partition table starts here in sect 0 */ #define DEV_PER_DRIVE 5 /* hd0 + hd1 + hd2 + hd3 + hd4 = 5 */ + #if AUTO_BIOS + #define AUTO_PARAM 0x1AD /* drive parameter table starts here in sect 0 */ + #define AUTO_ENABLE 0x10 /* auto bios enabled bit from status reg */ + /* some start up parameters in order to extract the drive parameter table */ + /* from the winchester. these should not need changed. */ + #define AUTO_CYLS 306 /* default number of cylinders */ + #define AUTO_HEADS 4 /* default number of heads */ + #define AUTO_RWC 307 /* default reduced write cylinder */ + #define AUTO_WPC 307 /* default write precomp cylinder */ + #define AUTO_ECC 11 /* default ecc burst */ + #define AUTO_CTRL 5 /* default winchester stepping speed byte */ + #endif /* Variables. */ 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; /* Control byte for COMMANDS (10-Apr-87 GO) */ long wn_low; /* lowest cylinder of partition */ long wn_size; /* size of partition in blocks */ int wn_count; /* byte count */ *************** *** 102,109 **** --- 123,134 ---- 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; /* Copied control-byte from bios tables */ } param0, param1; + #if DEBUG + #define port_out(port, val) xport_out(port, val) + #endif /* DEBUG */ /*===========================================================================* * 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. --- 139,145 ---- 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); --- 190,196 ---- 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) --- 287,304 ---- /* 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); } --- 324,354 ---- port_in(WIN_DATA, &status); port_out(WIN_DMA, 0); ! if (!(status & 2)) /* Test "error" bit */ 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) /* Missing from */ ! return (ERR); /* Original. 11-Apr-87 G.O. */ ! ! port_in(WIN_DATA, &status); /* Read "error" flag */ ! ! if(((status & 2) != 0) || (wn->wn_results[0] & 0x3F)) { ! #if DEBUG ! printf("\nwin_results: results[0] = %x", wn->wn_results[0]); ! #endif /* DEBUG */ return(ERR); ! } else return(OK); } *************** *** 331,339 **** * 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); } --- 363,376 ---- * 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,361 **** * 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); } --- 383,409 ---- * like the controller refusing to respond. */ ! int r = 0, i; /* Strobe reset bit low. */ ! port_out(WIN_STATUS, 0); ! ! for(i = MAX_WIN_RETRY/10; i; --i) ! ; /* Spin loop for a while */ ! ! port_out(WIN_SELECT, 0); /* Issue select pulse */ ! for (i = 0; i < MAX_WIN_RETRY; i++) { port_in(WIN_STATUS, &r); ! if(r & 0x30) /* What is 10? 20 = INTERRUPT */ ! 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, status = %x\n", r); return(ERR); } *************** *** 362,462 **** /* 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 */ ! 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); } --- 410,529 ---- /* Reset succeeded. Tell WIN drive parameters. */ w_need_reset = FALSE; ! if(win_specify(0, ¶m0) != OK) ! return (ERR); ! #if DEBUG ! printf("\nw_reset: drive 0 specified"); ! #endif /* DEBUG */ ! if ((nr_drives > 1) && (win_specify(1, ¶m1) != OK)) return(ERR); ! #if DEBUG ! printf("\nw_reset: drive 1 specified"); ! #endif /* DEBUG */ ! 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, ctrl_byte = %x", i, command[5]); ! #endif /* DEBUG */ ! 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 /* DEBUG */ ! return(ERR); ! } ! } ! return(OK); ! } ! /*===========================================================================* ! * w_wait_int * ! *===========================================================================*/ ! PRIVATE w_wait_int() ! { ! /*DEBUG: loop looking for 0x20 in status (I don't know what that is!!) */ ! /* 10-Apr-87. G. Oliver */ ! int r, i; /* Some local storage */ ! receive(HARDWARE, &w_mess); ! ! port_out(DMA_INIT, 0x07); /* Disable int from DMA */ ! ! for(i=0; i<MAX_WIN_RETRY; ++i) { ! 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); } } --- 533,562 ---- 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; --- 570,578 ---- 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 */ --- 584,591 ---- /*============================================================================* * 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); --- 594,607 ---- 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); } --- 615,664 ---- { /* 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); } *************** *** 572,580 **** /* Read the switches from the controller */ 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]; --- 679,728 ---- /* Read the switches from the controller */ port_in(WIN_SELECT, &i); + #if AUTO_BIOS + /* Get the drive parameters from sector zero of the drive if the */ + /* autoconfig mode of the controller has been selected */ + if(i & AUTO_ENABLE) { + + /* set up some phoney parameters so that we can read the first sector */ + /* from the winchester. all drives will have one cylinder and one head */ + /* but set up initially to the mini scribe drives from ibm */ + nr_drives = 1; + param0.nr_cyl = AUTO_CYLS; + param0.nr_heads = AUTO_HEADS; + param0.reduced_wr = AUTO_RWC; + param0.wr_precomp = AUTO_WPC; + param0.max_ecc = AUTO_ECC; + param0.ctrl_byte = AUTO_CTRL; + wini[0].wn_heads = param0.nr_heads; + wini[0].wn_low = 0L; + wini[0].wn_size = (long)AUTO_CYLS * (long)AUTO_HEADS * (long)NR_SECTORS; + if(w_reset() != OK) + panic("cannot setup for reading winchester parameter table",0); + + /* generate the request to read the first sector from the winchester */ + w_mess.DEVICE = 0; + w_mess.POSITION = 0L; + w_mess.COUNT = BLOCK_SIZE; + w_mess.ADDRESS = (char *) buf; + w_mess.PROC_NR = WINCHESTER; + w_mess.m_type = DISK_READ; + if(w_do_rdwt(&w_mess) != BLOCK_SIZE) + panic("cannot read drive parameters from winchester", 0); + + /* copy the parameter tables into the structures for later use */ + copy_param(&buf[AUTO_PARAM], ¶m0); + copy_param(&buf[AUTO_PARAM + 16], ¶m1); + + /* whoever compiled the kernel wanted the auto bios code included. if it + * turns out that the tables should be read from the rom, then handle + * this case the regular way */ + } else { + #endif + /* 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]), ¶m0); ! copy_param((&buf[type_1 * 16]), ¶m1); ! /* 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; --- 729,777 ---- 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], ¶m0); ! copy_param(&buf[type_1 * 16], ¶m1); ! #if AUTO_BIOS ! /* close up the code to be executed when the controller has not been ! * set up to for auto configuration */ ! } ! #endif ! ! /* 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); } } --- 779,788 ---- 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; --- 794,800 ---- 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 **** --- 802,808 ---- 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 **** --- 856,876 ---- *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 */