[comp.os.minix] Minix 1.3 on a Toshiba 5100

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;
    }