Get soft reset at initialization working again. Remove reset_time code. (Re-add timeouts some time later.) Eliminate remaining sleep_on() calls. Encapsulate access to esdi attention register. Correct some formatting in config display. Correct soft reset logic. Also... http://www.sound.net/~hald/projects/ps2esdi/ps2esdi-2.4.4-patch4 Hal Duston [EMAIL PROTECTED]
Get soft reset at initialization working again. Remove reset_time code. (Re-add timeouts some time later.) Eliminate remaining sleep_on() calls. Encapsulate access to esdi attention register. Correct some formatting in config display. Correct soft reset logic. --- linux-2.4.5-pre4/drivers/block/ps2esdi.c.3 Mon May 21 00:07:38 2001 +++ linux-2.4.5-pre4/drivers/block/ps2esdi.c.4 Mon May 21 00:16:49 2001 @@ -107,6 +107,8 @@ static void ps2esdi_reset_timer(unsigned long unused); +static int ps2esdi_attention(u_int device, u_int request); + static u_int dma_arb_level; /* DMA arbitration level */ static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int); @@ -460,19 +462,8 @@ current_int_handler = ps2esdi_initial_reset_int_handler; reset_ctrl(); reset_status = 0; - reset_start = jiffies; - while (!reset_status) { - init_timer(&esdi_timer); - esdi_timer.expires = jiffies + HZ; - esdi_timer.data = 0; - add_timer(&esdi_timer); - sleep_on(&ps2esdi_int); - } - reset_end = jiffies; + wait_event(ps2esdi_int, reset_status); LITE_OFF; - printk("%s: reset interrupt after %d jiffies, %u.%02u secs\n", - DEVICE_NAME, reset_end - reset_start, (reset_end - reset_start) / HZ, - (reset_end - reset_start) % HZ); /* Integrated ESDI Disk and Controller has only one drive! */ @@ -522,8 +513,7 @@ cmd_blk[1] = 0; no_int_yet = TRUE; ps2esdi_out_cmd_blk(cmd_blk); - if (no_int_yet) - sleep_on(&ps2esdi_int); + wait_event(ps2esdi_int, !no_int_yet); } return; } @@ -597,32 +587,20 @@ { u_long expire; - u_short status; - - /* enable interrupts on the controller */ - status = inb(ESDI_INTRPT); - outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); /* to be sure we don't have - any interrupt pending... */ - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - /* read the ESDI status port - if the controller is not busy, - simply do a soft reset (fast) - otherwise we'll have to do a - hard (slow) reset. */ - if (!(inb(ESDI_STATUS) & STATUS_BUSY)) { + if(!ps2esdi_attention(0x07, 0x04)) { /*BA */ printk("%s: soft reset...\n", DEVICE_NAME); - outb(CTRL_SOFT_RESET, ESDI_ATTN); } - /* soft reset */ + /* soft reset */ else { /*BA */ printk("%s: hard reset...\n", DEVICE_NAME); outb(CTRL_HARD_RESET, ESDI_CONTROL); - expire = jiffies + 2*HZ; - while (time_before(jiffies, expire)); - outb(1, ESDI_CONTROL); + expire = jiffies + 2 * HZ; + while(time_before(jiffies, expire)) + {} + outb(CTRL_ENABLE_INTR, ESDI_CONTROL); } /* hard reset */ - - } /* reset the controller */ /* called by the strategy routine to handle read and write requests */ @@ -695,13 +673,10 @@ printk("%s: i(1)=%d\n", DEVICE_NAME, i); #endif - /* if device is still busy - then just time out */ - if (inb(ESDI_STATUS) & STATUS_BUSY) { - printk("%s: ps2esdi_out_cmd timed out (1)\n", DEVICE_NAME); + if(ps2esdi_attention((cmd_blk[0] & 0xe0) >> 5, 0x01)) { + printk("%s: ps2esdi_out_cmd timed out (%x)\n", DEVICE_NAME, +(cmd_blk[0] & 0xe0) >> 5); return ERROR; - } /* timeout ??? */ - /* Set up the attention register in the controller */ - outb(((*cmd_blk) & 0xE0) | 1, ESDI_ATTN); + } #if 0 printk("%s: sending %d words to controller\n", DEVICE_NAME, (((*cmd_blk) >> 14) + 1) << 1); @@ -774,25 +749,25 @@ static void ps2esdi_initial_reset_int_handler(u_int int_ret_code) { + reset_status = int_ret_code; switch (int_ret_code & 0xf) { case INT_RESET: /*BA */ printk("%s: initial reset completed.\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); wake_up(&ps2esdi_int); break; case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, + printk("%s: Attention error during reset. interrupt status : %02X\n", +DEVICE_NAME, int_ret_code); printk("%s: status: %02x\n", DEVICE_NAME, inb(ESDI_STATUS)); break; default: printk("%s: initial reset handler received interrupt: %02X\n", DEVICE_NAME, int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); break; } - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); } @@ -821,10 +796,10 @@ printk("%s: Device Configuration Status for drive %u\n", DEVICE_NAME, drive_num); - printk("%s: Spares/cyls: %u", DEVICE_NAME, reply[0] >> 8); + printk("%s: Spares/cyls: %u\n", DEVICE_NAME, reply[0] +>> 8); printk - ("Config bits: %s%s%s%s%s\n", + ("%s: Config bits: %s%s%s%s%s\n", DEVICE_NAME, (reply[0] & CONFIG_IS) ? "Invalid Secondary, " : "", ((reply[0] & CONFIG_ZD) && !(reply[0] & CONFIG_IS)) ? "Zero Defect, " : "Defects Present, ", @@ -877,11 +852,11 @@ printk("%s: command %02X unknown by geometry handler\n", DEVICE_NAME, status & 0x1f); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); break; case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, + printk("%s: Attention error during geometry. interrupt status : +%02X\n", DEVICE_NAME, int_ret_code); printk("%s: Device not available\n", DEVICE_NAME); --ps2esdi_drives; @@ -896,19 +871,18 @@ case INT_CMD_BLK_ERR: /*BA */ printk("%s: Whaa. Error occurred...\n", DEVICE_NAME); dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); --ps2esdi_drives; break; default: printk("%s: Unknown interrupt reason: %02X\n", DEVICE_NAME, int_ret_code & 0xf); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); break; } wake_up(&ps2esdi_int); no_int_yet = FALSE; - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); } @@ -930,7 +904,7 @@ break; case INT_ATTN_ERROR: - printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME, + printk("%s: Attention error during normal. interrupt status : %02X\n", +DEVICE_NAME, int_ret_code); outb(CTRL_ENABLE_INTR, ESDI_CONTROL); ending = FAIL; @@ -940,8 +914,7 @@ for (i = ESDI_TIMEOUT; i & !(inb(ESDI_STATUS) & STATUS_STAT_AVAIL); i--); if (!(inb(ESDI_STATUS) & STATUS_STAT_AVAIL)) { printk("%s: timeout reading status word\n", DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); if ((++CURRENT->errors) >= MAX_RETRIES) ending = FAIL; else @@ -953,8 +926,7 @@ case (CMD_READ & 0xff): case (CMD_WRITE & 0xff): LITE_OFF; - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); #if 0 printk("ps2esdi: cmd_complete b_wait: %p\n", &CURRENT->bh->b_wait); #endif @@ -963,8 +935,7 @@ default: printk("%s: interrupt for unknown command %02X\n", DEVICE_NAME, status & 0x1f); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); ending = -1; break; } @@ -974,8 +945,7 @@ case INT_CMD_ECC_RETRY: LITE_OFF; dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); ending = SUCCES; break; case INT_CMD_WARNING: @@ -984,8 +954,7 @@ case INT_DMA_ERR: LITE_OFF; dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); if ((++CURRENT->errors) >= MAX_RETRIES) ending = FAIL; else @@ -994,31 +963,27 @@ case INT_CMD_BLK_ERR: dump_cmd_complete_status(int_ret_code); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); ending = FAIL; break; case INT_CMD_FORMAT: printk("%s: huh ? Who issued this format command ?\n" ,DEVICE_NAME); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); ending = -1; break; case INT_RESET: /* BA printk("%s: reset completed.\n", DEVICE_NAME) */ ; - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); ending = -1; break; default: printk("%s: Unknown interrupt reason: %02X\n", DEVICE_NAME, int_ret_code & 0xf); - outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); + ps2esdi_attention((int_ret_code & 0xe0) >> 5, ATT_EOI); ending = -1; break; } @@ -1125,8 +1090,7 @@ int dev = DEVICE_NR(inode->i_rdev); if (dev < ps2esdi_drives) { - while (!ps2esdi_valid[dev]) - sleep_on(&ps2esdi_wait_open); + wait_event(ps2esdi_wait_open, ps2esdi_valid[dev]); access_count[dev]++; @@ -1236,11 +1200,34 @@ status = inb(ESDI_INTRPT); if ((status & 0xf) == INT_RESET) { - outb((status & 0xe0) | ATT_EOI, ESDI_ATTN); - outb(CTRL_ENABLE_INTR, ESDI_CONTROL); - reset_status = 1; + ps2esdi_attention((status & 0xe0) >> 5, ATT_EOI); + reset_status = -1; } wake_up(&ps2esdi_int); } +static int ps2esdi_attention(u_int device, u_int request) +{ + int busy; + u_char status; + + outb(CTRL_DISABLE_INTR, ESDI_CONTROL); + if(request == ATT_EOI || !(status = inb(ESDI_STATUS) & 0x50)) { + outb((device << 5) | request, ESDI_ATTN); + busy = 0; + } + else { + if(status & 0x10) { + printk("%s: Attention port in use (0x%x)\n", + DEVICE_NAME, status); + } + if(status & 0x40) { + printk("%s: Interrupt pending (0x%x)\n", + DEVICE_NAME, status); + } + busy = 1; + } + outb(CTRL_ENABLE_INTR, ESDI_CONTROL); + return busy; +} #endif