nfs@notecnirp.Princeton.EDU (Norbert Schlenker) (05/03/89)
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<BLOCK_SIZE/SECTOR_SIZE; i++) { ! receive(HARDWARE, &w_mess); ! /* old_state = lock(); */ ! dma_read((unsigned)(usr_buf >> 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<BLOCK_SIZE/SECTOR_SIZE; i++) { ! port_out(WIN_REG8, WIN_READ); ! receive(HARDWARE, &w_mess); ! dma_read((unsigned)(usr_buf >> 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<BLOCK_SIZE/SECTOR_SIZE; i++) { ! /* old_state = lock(); */ ! dma_write((unsigned)(usr_buf >> 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<BLOCK_SIZE/SECTOR_SIZE; i++) { ! port_out(WIN_REG8, WIN_WRITE); ! dma_write((unsigned)(usr_buf >> 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; }