PS/2 Esdi patch #8

Hal Duston
2001-05-23T22:57:40Z

[-- Attachment #1: Type: TEXT/PLAIN, Size: 364 bytes --]

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
hald@sound.net

[-- Attachment #2: Type: TEXT/PLAIN, Size: 10456 bytes --]

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