Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!rutgers!njin!princeton!notecnirp!nfs From: nfs@notecnirp.Princeton.EDU (Norbert Schlenker) Newsgroups: comp.os.minix Subject: Minix 1.3 on a Toshiba 5100 Summary: It works (with a patch) Keywords: Minix 1.3 Toshiba 5100 patch Message-ID: <16753@princeton.Princeton.EDU> Date: 3 May 89 04:07:47 GMT Sender: news@princeton.Princeton.EDU Reply-To: nfs@notecnirp.UUCP (Norbert Schlenker) Organization: Dept. of Computer Science, Princeton University Lines: 129 Here is a context diff that will turn the standard 1.3 at_wini.c into a working driver for a Toshiba 5100's hard disk. The Toshiba controller appears to generate two interrupts almost simultaneously when asked for two disk sectors, and Minix doesn't handle it very well. The diff changes the single request for a two sector read into two consecutive single sector reads, which appears to fix the problem nicely. *** at_wini.c Tue May 2 23:22:07 1989 --- my_wini.c Tue May 2 23:25:26 1989 *************** *** 197,226 **** usr_buf = umap(proc_addr(wn->wn_procnr), D, wn->wn_address, BLOCK_SIZE); if (usr_buf == (phys_bytes)0) return(ERR); ! command[0] = wn->wn_ctlbyte; ! command[1] = wn->wn_precomp; ! command[2] = BLOCK_SIZE/SECTOR_SIZE; ! command[3] = wn->wn_sector; ! command[4] = wn->wn_cylinder & 0xFF; ! command[5] = ((wn->wn_cylinder & 0x0300) >> 8); ! command[6] = (wn->wn_drive << 4) | wn->wn_head | 0xA0; ! command[7] = (wn->wn_opcode == DISK_READ ? WIN_READ : WIN_WRITE); ! ! if (com_out() != OK) ! return(ERR); /* Block, waiting for disk interrupt. */ if (wn->wn_opcode == DISK_READ) { for (i=0; i> 4), (unsigned)(usr_buf & 0x0F)); ! /* restore(old_state); */ ! usr_buf += 0x200; if (win_results() != OK) { w_need_reset = TRUE; return(ERR); } } r = OK; } else { --- 197,239 ---- usr_buf = umap(proc_addr(wn->wn_procnr), D, wn->wn_address, BLOCK_SIZE); if (usr_buf == (phys_bytes)0) return(ERR); ! ! /* Set up controller registers (mostly an inline com_out). */ ! ! if (drive_busy()) { ! w_need_reset = TRUE; ! return(ERR); ! } ! port_out(WIN_REG9, wn->wn_ctlbyte); ! port_out(WIN_REG2, wn->wn_precomp); ! port_out(WIN_REG3, 1); ! port_out(WIN_REG4, wn->wn_sector); ! port_out(WIN_REG5, wn->wn_cylinder & 0xFF); ! port_out(WIN_REG6, (wn->wn_cylinder & 0x0300) >> 8); ! port_out(WIN_REG7, (wn->wn_drive << 4) | wn->wn_head | 0xA0); /* Block, waiting for disk interrupt. */ if (wn->wn_opcode == DISK_READ) { for (i=0; i> 4), (unsigned)(usr_buf & 0x0F)); if (win_results() != OK) { w_need_reset = TRUE; return(ERR); } + if (++wn->wn_sector > wn->wn_maxsec) { + wn->wn_sector = 1; + if (++wn->wn_head >= wn->wn_heads) { + wn->wn_head = 0; + ++wn->wn_cylinder; + port_out(WIN_REG5, wn->wn_cylinder & 0xFF); + port_out(WIN_REG6, (wn->wn_cylinder & 0x0300) >> 8); + } + port_out(WIN_REG7, (wn->wn_drive << 4) | wn->wn_head | 0xA0); + } + port_out(WIN_REG4, wn->wn_sector); + usr_buf += 0x200; } r = OK; } else { *************** *** 231,245 **** return(ERR); } for (i=0; i> 4), (unsigned)(usr_buf&0x0F)); ! /* restore(old_state); */ ! usr_buf += 0x200; receive(HARDWARE, &w_mess); if (win_results() != OK) { w_need_reset = TRUE; return(ERR); } } r = OK; } --- 244,268 ---- return(ERR); } for (i=0; i> 4), (unsigned)(usr_buf&0x0F)); receive(HARDWARE, &w_mess); if (win_results() != OK) { w_need_reset = TRUE; return(ERR); } + if (++wn->wn_sector > wn->wn_maxsec) { + wn->wn_sector = 1; + if (++wn->wn_head >= wn->wn_heads) { + wn->wn_head = 0; + ++wn->wn_cylinder; + port_out(WIN_REG5, wn->wn_cylinder & 0xFF); + port_out(WIN_REG6, (wn->wn_cylinder & 0x0300) >> 8); + } + port_out(WIN_REG7, (wn->wn_drive << 4) | wn->wn_head | 0xA0); + } + port_out(WIN_REG4, wn->wn_sector); + usr_buf += 0x200; } r = OK; }