hgm@beta.UUCP (05/06/87)
Here is part 2 of 2. ----------------Concatenate below onto first part-------------------------- ! 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); } } --- 520,549 ---- 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; --- 557,565 ---- 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 */ --- 571,578 ---- /*============================================================================* * 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); --- 581,594 ---- 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); } --- 602,651 ---- { /* 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); } *************** *** 573,580 **** 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]; --- 667,674 ---- port_in(WIN_SELECT, &i); /* 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; --- 675,717 ---- 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); ! /* 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); } } --- 719,728 ---- 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; --- 734,740 ---- 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 **** --- 742,748 ---- 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 **** --- 796,816 ---- *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 */ --------------------------------Cut here------------------------------ Harry McGavran hgm@LANL.GOV Los Alamos National Laboratory MS-B294, Group C-8 Los Alamos, New Mexico 87545 505/667-4050