Commit e8782ed7 authored by Alexander Viro's avatar Alexander Viro Committed by James Bottomley

[PATCH] ps2esdi

	* switched to private queues
	* set ->queue and ->private_data
	* switched to use of ->bd_disk and ->rq_disk
	* somewhat cleaned up
parent dc931f53
...@@ -116,6 +116,8 @@ struct ps2esdi_i_struct { ...@@ -116,6 +116,8 @@ struct ps2esdi_i_struct {
unsigned int head, sect, cyl, wpcom, lzone, ctl; unsigned int head, sect, cyl, wpcom, lzone, ctl;
}; };
static spinlock_t ps2esdi_lock = SPIN_LOCK_UNLOCKED; static spinlock_t ps2esdi_lock = SPIN_LOCK_UNLOCKED;
static struct request_queue ps2esdi_queue;
static struct request *current_req;
#if 0 #if 0
#if 0 /* try both - I don't know which one is better... UB */ #if 0 /* try both - I don't know which one is better... UB */
...@@ -156,8 +158,7 @@ int __init ps2esdi_init(void) ...@@ -156,8 +158,7 @@ int __init ps2esdi_init(void)
return -1; return -1;
} }
/* set up some global information - indicating device specific info */ /* set up some global information - indicating device specific info */
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_ps2esdi_request, blk_init_queue(&ps2esdi_queue, do_ps2esdi_request, &ps2esdi_lock);
&ps2esdi_lock);
/* some minor housekeeping - setup the global gendisk structure */ /* some minor housekeeping - setup the global gendisk structure */
error = ps2esdi_geninit(); error = ps2esdi_geninit();
...@@ -165,7 +166,7 @@ int __init ps2esdi_init(void) ...@@ -165,7 +166,7 @@ int __init ps2esdi_init(void)
printk(KERN_WARNING "PS2ESDI: error initialising" printk(KERN_WARNING "PS2ESDI: error initialising"
" device, releasing resources\n"); " device, releasing resources\n");
unregister_blkdev(MAJOR_NR, "ed"); unregister_blkdev(MAJOR_NR, "ed");
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(&ps2esdi_queue);
return error; return error;
} }
return 0; return 0;
...@@ -214,7 +215,7 @@ cleanup_module(void) { ...@@ -214,7 +215,7 @@ cleanup_module(void) {
free_dma(dma_arb_level); free_dma(dma_arb_level);
free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk); free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk);
unregister_blkdev(MAJOR_NR, "ed"); unregister_blkdev(MAJOR_NR, "ed");
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(&ps2esdi_queue);
for (i = 0; i < ps2esdi_drives; i++) { for (i = 0; i < ps2esdi_drives; i++) {
del_gendisk(ps2esdi_gendisk[i]); del_gendisk(ps2esdi_gendisk[i]);
put_disk(ps2esdi_gendisk[i]); put_disk(ps2esdi_gendisk[i]);
...@@ -413,7 +414,7 @@ static int __init ps2esdi_geninit(void) ...@@ -413,7 +414,7 @@ static int __init ps2esdi_geninit(void)
error = -EBUSY; error = -EBUSY;
goto err_out3; goto err_out3;
} }
blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 128); blk_queue_max_sectors(&ps2esdi_queue, 128);
error = -ENOMEM; error = -ENOMEM;
for (i = 0; i < ps2esdi_drives; i++) { for (i = 0; i < ps2esdi_drives; i++) {
...@@ -431,6 +432,8 @@ static int __init ps2esdi_geninit(void) ...@@ -431,6 +432,8 @@ static int __init ps2esdi_geninit(void)
struct gendisk *disk = ps2esdi_gendisk[i]; struct gendisk *disk = ps2esdi_gendisk[i];
set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect * set_capacity(disk, ps2esdi_info[i].head * ps2esdi_info[i].sect *
ps2esdi_info[i].cyl); ps2esdi_info[i].cyl);
disk->queue = &ps2esdi_queue;
disk->private_data = &ps2esdi_info[i];
add_disk(disk); add_disk(disk);
} }
return 0; return 0;
...@@ -477,65 +480,52 @@ static void __init ps2esdi_get_device_cfg(void) ...@@ -477,65 +480,52 @@ static void __init ps2esdi_get_device_cfg(void)
/* strategy routine that handles most of the IO requests */ /* strategy routine that handles most of the IO requests */
static void do_ps2esdi_request(request_queue_t * q) static void do_ps2esdi_request(request_queue_t * q)
{ {
u_int block, count; struct request *req;
int unit;
/* since, this routine is called with interrupts cleared - they /* since, this routine is called with interrupts cleared - they
must be before it finishes */ must be before it finishes */
#if 0
printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
DEVICE_NAME,
DEVICE_NR(CURRENT->rq_dev), minor(CURRENT->rq_dev),
CURRENT->cmd, CURRENT->sector,
CURRENT->current_nr_sectors, CURRENT->buffer);
#endif
/* standard procedure to ensure that requests are really on the /* standard procedure to ensure that requests are really on the
list + sanity checks. */ list + sanity checks. */
if (blk_queue_empty(QUEUE)) if (blk_queue_empty(q))
return; return;
unit = DEVICE_NR(CURRENT->rq_dev); req = elv_next_request(q);
if (isa_virt_to_bus(CURRENT->buffer + CURRENT->current_nr_sectors * 512) > 16 * MB) {
printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
end_request(CURRENT, FAIL);
} /* check for above 16Mb dmas */
else if ((unit < ps2esdi_drives) &&
(CURRENT->sector + CURRENT->current_nr_sectors <=
get_capacity(ps2esdi_gendisk[unit])) &&
CURRENT->flags & REQ_CMD) {
#if 0 #if 0
printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld\n", printk("%s:got request. device : %d minor : %d command : %d sector : %ld count : %ld, buffer: %p\n",
DEVICE_NAME, DEVICE_NAME,
unit, minor(CURRENT->rq_dev), DEVICE_NR(req->rq_dev), minor(req->rq_dev),
CURRENT->cmd, CURRENT->sector, req->cmd, req->sector,
CURRENT->current_nr_sectors); req->current_nr_sectors, req->buffer);
#endif #endif
block = CURRENT->sector; /* check for above 16Mb dmas */
count = CURRENT->current_nr_sectors; if (isa_virt_to_bus(req->buffer + req->current_nr_sectors * 512) > 16 * MB) {
printk("%s: DMA above 16MB not supported\n", DEVICE_NAME);
end_request(req, FAIL);
return;
}
if (req->sector+req->current_nr_sectors > get_capacity(req->rq_disk)) {
printk("Grrr. error. ps2esdi_drives: %d, %lu %llu\n",
ps2esdi_drives, req->sector,
(unsigned long long)get_capacity(req->rq_disk));
end_request(req, FAIL);
return;
}
switch (rq_data_dir(CURRENT)) { switch (rq_data_dir(req)) {
case READ: case READ:
ps2esdi_readwrite(READ, unit, block, count); ps2esdi_readwrite(READ, req);
break; break;
case WRITE: case WRITE:
ps2esdi_readwrite(WRITE, unit, block, count); ps2esdi_readwrite(WRITE, req);
break; break;
default: default:
printk("%s: Unknown command\n", DEVICE_NAME); printk("%s: Unknown command\n", req->rq_disk->disk_name);
end_request(CURRENT, FAIL); end_request(req, FAIL);
break; break;
} /* handle different commands */ } /* handle different commands */
}
/* is request is valid */
else {
printk("Grrr. error. ps2esdi_drives: %d, %lu %llu\n",
ps2esdi_drives, CURRENT->sector,
(unsigned long long)get_capacity(ps2esdi_gendisk[unit]));
end_request(CURRENT, FAIL);
}
} /* main strategy routine */ } /* main strategy routine */
/* resets the ESDI adapter */ /* resets the ESDI adapter */
...@@ -572,17 +562,20 @@ static void reset_ctrl(void) ...@@ -572,17 +562,20 @@ static void reset_ctrl(void)
} /* reset the controller */ } /* reset the controller */
/* called by the strategy routine to handle read and write requests */ /* called by the strategy routine to handle read and write requests */
static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count) static void ps2esdi_readwrite(int cmd, struct request *req)
{ {
struct ps2esdi_i_struct *p = req->rq_disk->private_data;
unsigned block = req->sector;
unsigned count = req->current_nr_sectors;
int drive = DEVICE_NR(req->rq_dev);
u_short track, head, cylinder, sector; u_short track, head, cylinder, sector;
u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH]; u_short cmd_blk[TYPE_1_CMD_BLK_LENGTH];
/* do some relevant arithmatic */ /* do some relevant arithmatic */
track = block / ps2esdi_info[drive].sect; track = block / p->sect;
head = track % ps2esdi_info[drive].head; head = track % p->head;
cylinder = track / ps2esdi_info[drive].head; cylinder = track / p->head;
sector = block % ps2esdi_info[drive].sect; sector = block % p->sect;
#if 0 #if 0
printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector); printk("%s: cyl=%d head=%d sect=%d\n", DEVICE_NAME, cylinder, head, sector);
...@@ -591,16 +584,16 @@ static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count) ...@@ -591,16 +584,16 @@ static void ps2esdi_readwrite(int cmd, u_char drive, u_int block, u_int count)
ps2esdi_fill_cmd_block ps2esdi_fill_cmd_block
(cmd_blk, (cmd_blk,
(cmd == READ) ? CMD_READ : CMD_WRITE, (cmd == READ) ? CMD_READ : CMD_WRITE,
cylinder, head, sector, cylinder, head, sector, count, drive);
CURRENT->current_nr_sectors, drive);
/* send the command block to the controller */ /* send the command block to the controller */
current_req = req;
spin_unlock_irq(&ps2esdi_lock); spin_unlock_irq(&ps2esdi_lock);
if (ps2esdi_out_cmd_blk(cmd_blk)) { if (ps2esdi_out_cmd_blk(cmd_blk)) {
spin_lock_irq(&ps2esdi_lock); spin_lock_irq(&ps2esdi_lock);
printk("%s: Controller failed\n", DEVICE_NAME); printk("%s: Controller failed\n", DEVICE_NAME);
if ((++CURRENT->errors) >= MAX_RETRIES) if ((++req->errors) >= MAX_RETRIES)
end_request(CURRENT, FAIL); end_request(req, FAIL);
} }
/* check for failure to put out the command block */ /* check for failure to put out the command block */
else { else {
...@@ -680,11 +673,7 @@ static int ps2esdi_out_cmd_blk(u_short * cmd_blk) ...@@ -680,11 +673,7 @@ static int ps2esdi_out_cmd_blk(u_short * cmd_blk)
/* prepare for dma - do all the necessary setup */ /* prepare for dma - do all the necessary setup */
static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode) static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
{ {
unsigned long flags; unsigned long flags = claim_dma_lock();
#if 0
printk("ps2esdi: b_wait: %p\n", &CURRENT->bh->b_wait);
#endif
flags = claim_dma_lock();
mca_disable_dma(dma_arb_level); mca_disable_dma(dma_arb_level);
...@@ -873,8 +862,9 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) ...@@ -873,8 +862,9 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
switch (int_ret_code & 0x0f) { switch (int_ret_code & 0x0f) {
case INT_TRANSFER_REQ: case INT_TRANSFER_REQ:
ps2esdi_prep_dma(CURRENT->buffer, CURRENT->current_nr_sectors, ps2esdi_prep_dma(current_req->buffer,
(rq_data_dir(CURRENT) == READ) current_req->current_nr_sectors,
(rq_data_dir(current_req) == READ)
? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER ? MCA_DMA_MODE_16 | MCA_DMA_MODE_WRITE | MCA_DMA_MODE_XFER
: MCA_DMA_MODE_16 | MCA_DMA_MODE_READ); : MCA_DMA_MODE_16 | MCA_DMA_MODE_READ);
outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL); outb(CTRL_ENABLE_DMA | CTRL_ENABLE_INTR, ESDI_CONTROL);
...@@ -894,7 +884,7 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) ...@@ -894,7 +884,7 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
printk("%s: timeout reading status word\n", DEVICE_NAME); printk("%s: timeout reading status word\n", DEVICE_NAME);
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL); outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
if ((++CURRENT->errors) >= MAX_RETRIES) if ((++current_req->errors) >= MAX_RETRIES)
ending = FAIL; ending = FAIL;
else else
ending = -1; ending = -1;
...@@ -907,9 +897,6 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) ...@@ -907,9 +897,6 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
LITE_OFF; LITE_OFF;
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL); outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
#if 0
printk("ps2esdi: cmd_complete b_wait: %p\n", &CURRENT->bh->b_wait);
#endif
ending = SUCCES; ending = SUCCES;
break; break;
default: default:
...@@ -938,7 +925,7 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) ...@@ -938,7 +925,7 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
dump_cmd_complete_status(int_ret_code); dump_cmd_complete_status(int_ret_code);
outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN); outb((int_ret_code & 0xe0) | ATT_EOI, ESDI_ATTN);
outb(CTRL_ENABLE_INTR, ESDI_CONTROL); outb(CTRL_ENABLE_INTR, ESDI_CONTROL);
if ((++CURRENT->errors) >= MAX_RETRIES) if ((++current_req->errors) >= MAX_RETRIES)
ending = FAIL; ending = FAIL;
else else
ending = -1; ending = -1;
...@@ -976,8 +963,9 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code) ...@@ -976,8 +963,9 @@ static void ps2esdi_normal_interrupt_handler(u_int int_ret_code)
} }
if(ending != -1) { if(ending != -1) {
spin_lock_irqsave(&ps2esdi_lock, flags); spin_lock_irqsave(&ps2esdi_lock, flags);
end_request(CURRENT, ending); end_request(current_req, ending);
do_ps2esdi_request(BLK_DEFAULT_QUEUE(MAJOR_NR)); current_req = NULL;
do_ps2esdi_request(&ps2esdi_queue);
spin_unlock_irqrestore(&ps2esdi_lock, flags); spin_unlock_irqrestore(&ps2esdi_lock, flags);
} }
} /* handle interrupts */ } /* handle interrupts */
...@@ -1074,16 +1062,17 @@ static void dump_cmd_complete_status(u_int int_ret_code) ...@@ -1074,16 +1062,17 @@ static void dump_cmd_complete_status(u_int int_ret_code)
static int ps2esdi_ioctl(struct inode *inode, static int ps2esdi_ioctl(struct inode *inode,
struct file *file, u_int cmd, u_long arg) struct file *file, u_int cmd, u_long arg)
{ {
struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data;
struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg; struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
int dev = DEVICE_NR(inode->i_rdev), err; int err;
if (cmd != HDIO_GETGEO) if (cmd != HDIO_GETGEO)
return -EINVAL; return -EINVAL;
if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry)))) if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
return (err); return (err);
put_user(ps2esdi_info[dev].head, (char *) &geometry->heads); put_user(p->head, (char *) &geometry->heads);
put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors); put_user(p->sect, (char *) &geometry->sectors);
put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders); put_user(p->cyl, (short *) &geometry->cylinders);
put_user(get_start_sect(inode->i_bdev), (long *) &geometry->start); put_user(get_start_sect(inode->i_bdev), (long *) &geometry->start);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment