patch-2.4.4 linux/drivers/block/ps2esdi.c
Next file: linux/drivers/cdrom/sbpcd.c
Previous file: linux/drivers/block/paride/ppc6lnx.c
Back to the patch index
Back to the overall index
- Lines: 301
- Date:
Wed Apr 18 11:49:13 2001
- Orig file:
v2.4.3/linux/drivers/block/ps2esdi.c
- Orig date:
Thu Oct 26 23:35:47 2000
diff -u --recursive --new-file v2.4.3/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
@@ -52,6 +52,7 @@
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/dma.h>
+#include <asm/mca_dma.h>
#include <asm/uaccess.h>
#define PS2ESDI_IRQ 14
@@ -89,8 +90,6 @@
static void ps2esdi_initial_reset_int_handler(u_int);
static void ps2esdi_geometry_int_handler(u_int);
-static void ps2esdi_continue_request(void);
-
static int ps2esdi_open(struct inode *inode, struct file *file);
static int ps2esdi_release(struct inode *inode, struct file *file);
@@ -469,29 +468,26 @@
DEVICE_NAME,
CURRENT_DEV, MINOR(CURRENT->rq_dev),
CURRENT->cmd, CURRENT->sector,
- CURRENT->nr_sectors, CURRENT->buffer);
+ CURRENT->current_nr_sectors, CURRENT->buffer);
#endif
/* standard macro that ensures that requests are really on the
list + sanity checks. */
INIT_REQUEST;
- if (virt_to_bus(CURRENT->buffer + CURRENT->nr_sectors * 512) > 16 * MB) {
+ if (virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) {
printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
end_request(FAIL);
- if (!QUEUE_EMPTY)
- do_ps2esdi_request(q);
- return;
} /* check for above 16Mb dmas */
- if ((CURRENT_DEV < ps2esdi_drives) &&
- (CURRENT->sector + CURRENT->nr_sectors <=
+ else if ((CURRENT_DEV < ps2esdi_drives) &&
+ (CURRENT->sector + CURRENT->current_nr_sectors <=
ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects)) {
#if 0
printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n",
DEVICE_NAME,
- CURRENT_DEV, MINOR(CURRENT->dev),
+ CURRENT_DEV, MINOR(CURRENT->rq_dev),
CURRENT->cmd, CURRENT->sector,
- CURRENT->nr_sectors);
+ CURRENT->current_nr_sectors);
#endif
@@ -500,21 +496,17 @@
#if 0
printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
#endif
- count = CURRENT->nr_sectors;
+ count = CURRENT->current_nr_sectors;
switch (CURRENT->cmd) {
case READ:
ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
- return;
break;
case WRITE:
ps2esdi_readwrite(WRITE, CURRENT_DEV, block, count);
- return;
break;
default:
printk("%s: Unknown command\n", DEVICE_NAME);
end_request(FAIL);
- if (!QUEUE_EMPTY)
- do_ps2esdi_request(q);
break;
} /* handle different commands */
}
@@ -523,8 +515,6 @@
printk("Grrr. error. ps2esdi_drives: %d, %lu %lu\n", ps2esdi_drives,
CURRENT->sector, ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects);
end_request(FAIL);
- if (!QUEUE_EMPTY)
- do_ps2esdi_request(q);
}
} /* main strategy routine */
@@ -570,8 +560,6 @@
u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
/* do some relevant arithmatic */
- CURRENT->current_nr_sectors =
- (count < (2 * MAX_16BIT / SECT_SIZE)) ? count : (2 * MAX_16BIT / SECT_SIZE);
track = block / ps2esdi_info[drive].sect;
head = track % ps2esdi_info[drive].head;
cylinder = track / ps2esdi_info[drive].head;
@@ -590,13 +578,8 @@
/* send the command block to the controller */
if (ps2esdi_out_cmd_blk(cmd_blk)) {
printk("%s: Controller failed\n", DEVICE_NAME);
- if ((++CURRENT->errors) < MAX_RETRIES)
- return do_ps2esdi_request(NULL);
- else {
+ if ((++CURRENT->errors) >= MAX_RETRIES)
end_request(FAIL);
- if (!QUEUE_EMPTY)
- do_ps2esdi_request(NULL);
- }
}
/* check for failure to put out the command block */
else {
@@ -675,33 +658,23 @@
/* prepare for dma - do all the necessary setup */
static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
{
- u_int tc;
-
- buffer=(char *)virt_to_bus(buffer);
-
+ unsigned long flags;
#if 0
- printk("ps2esdi: b_wait: %p\n", CURRENT->bh->b_wait);
+ printk("ps2esdi: b_wait: %p\n", &CURRENT->bh->b_wait);
#endif
- cli();
+ flags = claim_dma_lock();
- outb(dma_arb_level | DMA_MASK_CHAN, PORT_DMA_FN);
+ mca_disable_dma(dma_arb_level);
- outb(dma_arb_level | DMA_WRITE_ADDR, PORT_DMA_FN);
- outb((u_int) buffer & (u_int) 0xff, PORT_DMA_EX);
- outb(((u_int) buffer >> 8) & (u_int) 0xff, PORT_DMA_EX);
- outb(((u_int) buffer >> 16) & (u_int) 0xff, PORT_DMA_EX);
+ mca_set_dma_addr(dma_arb_level, virt_to_bus(buffer));
- outb(dma_arb_level | DMA_WRITE_TC, PORT_DMA_FN);
- tc = (length * SECT_SIZE / 2) - 1;
- outb(tc & 0xff, PORT_DMA_EX);
- outb((tc >> 8) & 0xff, PORT_DMA_EX);
+ mca_set_dma_count(dma_arb_level, length * 512 / 2);
- outb(dma_arb_level | DMA_WRITE_MODE, PORT_DMA_FN);
- outb(dma_xmode, PORT_DMA_EX);
+ mca_set_dma_mode(dma_arb_level, dma_xmode);
- outb(dma_arb_level | DMA_UNMASK_CHAN, PORT_DMA_FN);
+ mca_enable_dma(dma_arb_level);
- sti();
+ release_dma_lock(flags);
} /* prepare for dma */
@@ -871,20 +844,26 @@
static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
{
+ unsigned long flags;
u_int status;
+ u_int ending;
int i;
switch (int_ret_code & 0x0f) {
case INT_TRANSFER_REQ:
ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors,
- (CURRENT->cmd == READ) ? DMA_READ_16 : DMA_WRITE_16);
+ (CURRENT->cmd == READ)
+ ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER
+ : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ);
outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
+ ending = -1;
break;
case INT_ATTN_ERROR:
printk("%s: Attention error. interrupt status : %02X\n", DEVICE_NAME,
int_ret_code);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+ ending = FAIL;
break;
case INT_CMD_COMPLETE:
@@ -893,13 +872,10 @@
printk("%s: timeout reading status word\n", DEVICE_NAME);
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
- if ((++CURRENT->errors) < MAX_RETRIES)
- do_ps2esdi_request(NULL);
- else {
- end_request(FAIL);
- if (!QUEUE_EMPTY)
- do_ps2esdi_request(NULL);
- }
+ if ((++CURRENT->errors) >= MAX_RETRIES)
+ ending = FAIL;
+ else
+ ending = -1;
break;
}
status = inw(ESDI_STT_INT);
@@ -910,15 +886,16 @@
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
#if 0
- printk("ps2esdi: cmd_complete b_wait: %p\n", CURRENT->bh->b_wait);
+ printk("ps2esdi: cmd_complete b_wait: %p\n", &CURRENT->bh->b_wait);
#endif
- ps2esdi_continue_request();
+ ending = SUCCES;
break;
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);
+ ending = -1;
break;
}
break;
@@ -929,7 +906,7 @@
dump_cmd_complete_status(int_ret_code);
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
- ps2esdi_continue_request();
+ ending = SUCCES;
break;
case INT_CMD_WARNING:
case INT_CMD_ABORT:
@@ -939,22 +916,17 @@
dump_cmd_complete_status(int_ret_code);
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
- if ((++CURRENT->errors) < MAX_RETRIES)
- do_ps2esdi_request(NULL);
- else {
- end_request(FAIL);
- if (!QUEUE_EMPTY)
- do_ps2esdi_request(NULL);
- }
+ if ((++CURRENT->errors) >= MAX_RETRIES)
+ ending = FAIL;
+ else
+ ending = -1;
break;
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);
- end_request(FAIL);
- if (!QUEUE_EMPTY)
- do_ps2esdi_request(NULL);
+ ending = FAIL;
break;
case INT_CMD_FORMAT:
@@ -962,12 +934,14 @@
,DEVICE_NAME);
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+ 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);
+ ending = -1;
break;
default:
@@ -975,24 +949,16 @@
DEVICE_NAME, int_ret_code & 0xf);
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
+ ending = -1;
break;
}
-
-} /* handle interrupts */
-
-
-static void ps2esdi_continue_request(void)
-{
- if (CURRENT->nr_sectors -= CURRENT->current_nr_sectors) {
- CURRENT->buffer += CURRENT->current_nr_sectors * SECT_SIZE;
- CURRENT->sector += CURRENT->current_nr_sectors;
- do_ps2esdi_request(NULL);
- } else {
- end_request(SUCCES);
- if (!QUEUE_EMPTY)
- do_ps2esdi_request(NULL);
+ if(ending != -1) {
+ spin_lock_irqsave(io_request_lock, flags);
+ end_request(ending);
+ do_ps2esdi_request(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ spin_unlock_irqrestore(io_request_lock, flags);
}
-}
+} /* handle interrupts */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)