Commit 57175350 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] sonycd535.c

	* switched to private queue
	* set ->queue
	* switched to new methods
	* slightly cleaned up
parent fe6ffad0
...@@ -135,7 +135,6 @@ ...@@ -135,7 +135,6 @@
#include <linux/cdrom.h> #include <linux/cdrom.h>
#define MAJOR_NR CDU535_CDROM_MAJOR #define MAJOR_NR CDU535_CDROM_MAJOR
#define DEVICE_NR(device) (minor(device))
#include <linux/blk.h> #include <linux/blk.h>
#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */ #define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
...@@ -221,6 +220,7 @@ static unsigned short read_status_reg; ...@@ -221,6 +220,7 @@ static unsigned short read_status_reg;
static unsigned short data_reg; static unsigned short data_reg;
static spinlock_t sonycd535_lock = SPIN_LOCK_UNLOCKED; /* queue lock */ static spinlock_t sonycd535_lock = SPIN_LOCK_UNLOCKED; /* queue lock */
static struct request_queue sonycd535_queue;
static int initialized; /* Has the drive been initialized? */ static int initialized; /* Has the drive been initialized? */
static int sony_disc_changed = 1; /* Has the disk been changed static int sony_disc_changed = 1; /* Has the disk been changed
...@@ -280,17 +280,10 @@ static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait); ...@@ -280,17 +280,10 @@ static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);
* check or 0 if it hasn't. Setting flag to 0 resets the changed flag. * check or 0 if it hasn't. Setting flag to 0 resets the changed flag.
*/ */
static int static int
cdu535_check_media_change(kdev_t full_dev) cdu535_check_media_change(struct gendisk *disk)
{ {
int retval;
if (minor(full_dev) != 0) {
printk(CDU535_MESSAGE_NAME " request error: invalid device.\n");
return 0;
}
/* if driver is not initialized, always return 0 */ /* if driver is not initialized, always return 0 */
retval = initialized ? sony_disc_changed : 0; int retval = initialized ? sony_disc_changed : 0;
sony_disc_changed = 0; sony_disc_changed = 0;
return retval; return retval;
} }
...@@ -793,7 +786,7 @@ size_to_buf(unsigned int size, Byte *buf) ...@@ -793,7 +786,7 @@ size_to_buf(unsigned int size, Byte *buf)
static void static void
do_cdu535_request(request_queue_t * q) do_cdu535_request(request_queue_t * q)
{ {
unsigned int dev; struct request *req;
unsigned int read_size; unsigned int read_size;
int block; int block;
int nsect; int nsect;
...@@ -804,130 +797,121 @@ do_cdu535_request(request_queue_t * q) ...@@ -804,130 +797,121 @@ do_cdu535_request(request_queue_t * q)
Byte cmd[2]; Byte cmd[2];
while (1) { while (1) {
if (blk_queue_empty(QUEUE)) if (blk_queue_empty(q))
return; return;
dev = minor(CURRENT->rq_dev); req = elv_next_request(q);
block = CURRENT->sector; block = req->sector;
nsect = CURRENT->nr_sectors; nsect = req->nr_sectors;
if (dev != 0) { if (!(req->flags & REQ_CMD))
end_request(CURRENT, 0); continue; /* FIXME */
if (rq_data_dir(req) == WRITE) {
end_request(req, 0);
continue; continue;
} }
if(CURRENT->flags & REQ_CMD) { if (rq_data_dir(req) != READ)
switch (rq_data_dir(CURRENT)) { panic("Unknown SONY CD cmd");
case READ: /*
* If the block address is invalid or the request goes beyond
* the end of the media, return an error.
*/
if (sony_toc->lead_out_start_lba <= (block/4)) {
end_request(req, 0);
return;
}
if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
end_request(req, 0);
return;
}
while (0 < nsect) {
/*
* If the requested sector is not currently in
* the read-ahead buffer, it must be read in.
*/
if ((block < sony_first_block) || (sony_last_block < block)) {
sony_first_block = (block / 4) * 4;
log_to_msf(block / 4, params);
/* /*
* If the block address is invalid or the request goes beyond the end of * If the full read-ahead would go beyond the end of the media, trim
* the media, return an error. * it back to read just till the end of the media.
*/ */
if (sony_toc->lead_out_start_lba <= (block / 4)) { if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
end_request(CURRENT, 0); sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
return; read_size = sony_toc->lead_out_start_lba - (block / 4);
} } else {
if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) { sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
end_request(CURRENT, 0); read_size = sony_buffer_sectors;
return;
} }
while (0 < nsect) { size_to_buf(read_size, &params[3]);
/*
* Read the data. If the drive was not spinning,
* spin it up and try some more.
*/
for (spin_up_retry=0 ;; ++spin_up_retry) {
/* This loop has been modified to support the Sony
* CDU-510/515 series, thanks to Claudio Porfiri
* <C.Porfiri@nisms.tei.ericsson.se>.
*/
/* /*
* If the requested sector is not currently in the read-ahead buffer, * This part is to deal with very slow hardware. We
* it must be read in. * try at most MAX_SPINUP_RETRY times to read the same
* block. A check for seek_and_read_N_blocks' result is
* performed; if the result is wrong, the CDROM's engine
* is restarted and the operation is tried again.
*/ */
if ((block < sony_first_block) || (sony_last_block < block)) {
sony_first_block = (block / 4) * 4;
log_to_msf(block / 4, params);
/*
* If the full read-ahead would go beyond the end of the media, trim
* it back to read just till the end of the media.
*/
if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
read_size = sony_toc->lead_out_start_lba - (block / 4);
} else {
sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
read_size = sony_buffer_sectors;
}
size_to_buf(read_size, &params[3]);
/*
* Read the data. If the drive was not spinning,
* spin it up and try some more.
*/
for (spin_up_retry=0 ;; ++spin_up_retry) {
/* This loop has been modified to support the Sony
* CDU-510/515 series, thanks to Claudio Porfiri
* <C.Porfiri@nisms.tei.ericsson.se>.
*/
/*
* This part is to deal with very slow hardware. We
* try at most MAX_SPINUP_RETRY times to read the same
* block. A check for seek_and_read_N_blocks' result is
* performed; if the result is wrong, the CDROM's engine
* is restarted and the operation is tried again.
*/
/*
* 1995-06-01: The system got problems when downloading
* from Slackware CDROM, the problem seems to be:
* seek_and_read_N_blocks returns BAD_STATUS and we
* should wait for a while before retrying, so a new
* part was added to discriminate the return value from
* seek_and_read_N_blocks for the various cases.
*/
int readStatus = seek_and_read_N_blocks(params, read_size,
status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
if (0 <= readStatus) /* Good data; common case, placed first */
break;
if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
/* give up */
if (readStatus == NO_ROOM)
printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
else
printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
status[0]);
sony_first_block = -1;
sony_last_block = -1;
end_request(CURRENT, 0);
return;
}
if (readStatus == BAD_STATUS) {
/* Sleep for a while, then retry */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
}
#if DEBUG > 0
printk(CDU535_MESSAGE_NAME
" debug: calling spin up when reading data!\n");
#endif
cmd[0] = SONY535_SPIN_UP;
do_sony_cmd(cmd, 1, status, NULL, 0, 0);
}
}
/* /*
* The data is in memory now, copy it to the buffer and advance to the * 1995-06-01: The system got problems when downloading
* next block to read. * from Slackware CDROM, the problem seems to be:
* seek_and_read_N_blocks returns BAD_STATUS and we
* should wait for a while before retrying, so a new
* part was added to discriminate the return value from
* seek_and_read_N_blocks for the various cases.
*/ */
copyoff = block - sony_first_block; int readStatus = seek_and_read_N_blocks(params, read_size,
memcpy(CURRENT->buffer, status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512); if (0 <= readStatus) /* Good data; common case, placed first */
break;
block += 1; if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
nsect -= 1; /* give up */
CURRENT->buffer += 512; if (readStatus == NO_ROOM)
printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
else
printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
status[0]);
sony_first_block = -1;
sony_last_block = -1;
end_request(req, 0);
return;
}
if (readStatus == BAD_STATUS) {
/* Sleep for a while, then retry */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
}
#if DEBUG > 0
printk(CDU535_MESSAGE_NAME
" debug: calling spin up when reading data!\n");
#endif
cmd[0] = SONY535_SPIN_UP;
do_sony_cmd(cmd, 1, status, NULL, 0, 0);
} }
end_request(CURRENT, 1);
break;
case WRITE:
end_request(CURRENT, 0);
break;
default:
panic("Unknown SONY CD cmd");
} }
/*
* The data is in memory now, copy it to the buffer and advance to the
* next block to read.
*/
copyoff = block - sony_first_block;
memcpy(req->buffer,
sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
block += 1;
nsect -= 1;
req->buffer += 512;
} }
end_request(req, 1);
} }
} }
...@@ -1071,20 +1055,12 @@ cdu_ioctl(struct inode *inode, ...@@ -1071,20 +1055,12 @@ cdu_ioctl(struct inode *inode,
unsigned int cmd, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
unsigned int dev;
Byte status[2]; Byte status[2];
Byte cmd_buff[10], params[10]; Byte cmd_buff[10], params[10];
int i; int i;
int dsc_status; int dsc_status;
int err; int err;
if (!inode) {
return -EINVAL;
}
dev = minor(inode->i_rdev) >> 6;
if (dev != 0) {
return -EINVAL;
}
if (check_drive_status() != 0) if (check_drive_status() != 0)
return -EIO; return -EIO;
...@@ -1447,11 +1423,11 @@ cdu_release(struct inode *inode, ...@@ -1447,11 +1423,11 @@ cdu_release(struct inode *inode,
static struct block_device_operations cdu_fops = static struct block_device_operations cdu_fops =
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = cdu_open, .open = cdu_open,
.release = cdu_release, .release = cdu_release,
.ioctl = cdu_ioctl, .ioctl = cdu_ioctl,
.check_media_change = cdu535_check_media_change, .media_changed = cdu535_check_media_change,
}; };
static struct gendisk *cdu_disk; static struct gendisk *cdu_disk;
...@@ -1582,9 +1558,8 @@ static int __init sony535_init(void) ...@@ -1582,9 +1558,8 @@ static int __init sony535_init(void)
err = -EIO; err = -EIO;
goto out1; goto out1;
} }
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_cdu535_request, blk_init_queue(&sonycd535_queue, do_cdu535_request, &sonycd535_lock);
&sonycd535_lock); blk_queue_hardsect_size(&sonycd535_queue, CDU535_BLOCK_SIZE);
blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CDU535_BLOCK_SIZE);
sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL); sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
err = -ENOMEM; err = -ENOMEM;
if (!sony_toc) if (!sony_toc)
...@@ -1618,6 +1593,7 @@ static int __init sony535_init(void) ...@@ -1618,6 +1593,7 @@ static int __init sony535_init(void)
sony535_cd_base_io); sony535_cd_base_io);
goto out7; goto out7;
} }
cdu_disk->queue = &sonycd535_queue;
add_disk(cdu_disk); add_disk(cdu_disk);
return 0; return 0;
...@@ -1634,7 +1610,7 @@ static int __init sony535_init(void) ...@@ -1634,7 +1610,7 @@ static int __init sony535_init(void)
out3: out3:
kfree(sony_toc); kfree(sony_toc);
out2: out2:
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(&sonycd535_queue);
unregister_blkdev(MAJOR_NR, CDU535_HANDLE); unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
out1: out1:
devfs_unregister(sony_devfs_handle); devfs_unregister(sony_devfs_handle);
...@@ -1699,6 +1675,7 @@ static sony535_exit(void) ...@@ -1699,6 +1675,7 @@ static sony535_exit(void)
DEVFS_SPECIAL_BLK, 0); DEVFS_SPECIAL_BLK, 0);
del_gendisk(cdu_disk); del_gendisk(cdu_disk);
put_disk(cdu_disk); put_disk(cdu_disk);
blk_cleanup_queue(&sonycd535_queue);
if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL) if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n"); printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
else else
......
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