* This section describes features beyond the normal audio and CD-ROM
* functions of the drive.
*
- * 2048 byte buffer mode
- *
- * If a disk is mounted with -o block=2048, data is copied straight
- * from the drive data port to the buffer. Otherwise, the readahead
- * buffer must be involved to hold the other 1K of data when a 1K
- * block operation is done. Note that with 2048 byte blocks you
- * cannot execute files from the CD.
- *
* XA compatibility
*
* The driver should support XA disks for both the CDU31A and CDU33A.
* Removed init_module & cleanup_module in favor of
* module_init & module_exit.
* Torben Mathiasen <tmm@image.dk>
+ *
+ * 22 October 2004 -- Make the driver work in 2.6.X
+ * Added workaround to fix hard lockups on eject
+ * Fixed door locking problem after mounting empty drive
+ * Set double-speed drives to double speed by default
+ * Removed all readahead things - not needed anymore
+ * Ondrej Zary <rainbow@rainbow-software.org>
*/
-#include <linux/major.h>
+#define DEBUG 1
+#include <linux/major.h>
#include <linux/module.h>
-
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/cdrom.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
-#include <linux/cdrom.h>
#include "cdu31a.h"
#define MAJOR_NR CDU31A_CDROM_MAJOR
#include <linux/blkdev.h>
-#define CDU31A_READAHEAD 4 /* 128 sector, 64kB, 32 reads read-ahead */
#define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
-#define DEBUG 0
-
-/* Define the following if you have data corruption problems. */
-#undef SONY_POLL_EACH_BYTE
+#define PFX "CDU31A: "
/*
** Edit the following data to change interrupts, DMA channels, etc.
/* The base I/O address of the Sony Interface. This is a variable (not a
#define) so it can be easily changed via some future ioctl() */
static unsigned int cdu31a_port = 0;
-MODULE_PARM(cdu31a_port, "i");
+module_param(cdu31a_port, uint, 0);
/*
* The following are I/O addresses of the various registers for the drive. The
static volatile unsigned short sony_cd_fifost_reg;
static struct request_queue *cdu31a_queue;
-static spinlock_t cdu31a_lock = SPIN_LOCK_UNLOCKED; /* queue lock */
+static DEFINE_SPINLOCK(cdu31a_lock); /* queue lock */
static int sony_spun_up = 0; /* Has the drive been spun up? */
static struct s_sony_subcode last_sony_subcode; /* Points to the last
subcode address read */
-static volatile int sony_inuse = 0; /* Is the drive in use? Only one operation
- at a time allowed */
-
-static DECLARE_WAIT_QUEUE_HEAD(sony_wait); /* Things waiting for the drive */
-
-static struct task_struct *has_cd_task = NULL; /* The task that is currently
- using the CDROM drive, or
- NULL if none. */
+static DECLARE_MUTEX(sony_sem); /* Semaphore for drive hardware access */
static int is_double_speed = 0; /* does the drive support double speed ? */
-static int is_a_cdu31a = 1; /* Is the drive a CDU31A? */
static int is_auto_eject = 1; /* Door has been locked? 1=No/0=Yes */
/* What IRQ is the drive using? 0 if none. */
static int cdu31a_irq = 0;
-MODULE_PARM(cdu31a_irq, "i");
+module_param(cdu31a_irq, int, 0);
/* The interrupt handler will wake this queue up when it gets an
interrupts. */
-DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
+static DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
+static int irq_flag = 0;
static int curr_control_reg = 0; /* Current value of the control register */
it will be cleared. */
static char disk_changed;
-/* Variable for using the readahead buffer. The readahead buffer
- is used for raw sector reads and for blocksizes that are smaller
- than 2048 bytes. */
-static char readahead_buffer[CD_FRAMESIZE_RAW];
-static int readahead_dataleft = 0;
-static int readahead_bad = 0;
+/* This was readahead_buffer once... Now it's used only for audio reads */
+static char audio_buffer[CD_FRAMESIZE_RAW];
/* Used to time a short period to abort an operation after the
drive has been idle for a while. This keeps the light on
*/
static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
{
- if (CDSL_CURRENT != slot_nr) {
+ if (CDSL_CURRENT != slot_nr)
/* we have no changer support */
return -EINVAL;
- }
- if (scd_spinup() == 0) {
+ if (sony_spun_up)
+ return CDS_DISC_OK;
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
+ if (scd_spinup() == 0)
sony_spun_up = 1;
- }
+ up(&sony_sem);
return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
}
*/
static inline void sony_sleep(void)
{
- unsigned long flags;
-
if (cdu31a_irq <= 0) {
yield();
} else { /* Interrupt driven */
+ DEFINE_WAIT(w);
+ int first = 1;
- save_flags(flags);
- cli();
- enable_interrupts();
- interruptible_sleep_on(&cdu31a_irq_wait);
- restore_flags(flags);
+ while (1) {
+ prepare_to_wait(&cdu31a_irq_wait, &w,
+ TASK_INTERRUPTIBLE);
+ if (first) {
+ enable_interrupts();
+ first = 0;
+ }
+
+ if (irq_flag != 0)
+ break;
+ if (!signal_pending(current)) {
+ schedule();
+ continue;
+ } else
+ disable_interrupts();
+ break;
+ }
+ finish_wait(&cdu31a_irq_wait, &w);
+ irq_flag = 0;
}
}
*/
static inline int is_attention(void)
{
- return ((inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0);
+ return (inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0;
}
static inline int is_busy(void)
{
- return ((inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0);
+ return (inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0;
}
static inline int is_data_ready(void)
{
- return ((inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0);
+ return (inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0;
}
static inline int is_data_requested(void)
{
- return ((inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0);
+ return (inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0;
}
static inline int is_result_ready(void)
{
- return ((inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0);
+ return (inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0;
}
static inline int is_param_write_rdy(void)
{
- return ((inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0);
+ return (inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0;
}
static inline int is_result_reg_not_empty(void)
{
- return ((inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0);
+ return (inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0;
}
static inline void reset_drive(void)
{
curr_control_reg = 0;
- readahead_dataleft = 0;
sony_toc_read = 0;
outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);
}
{
unsigned long retry_count;
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
reset_drive();
retry_count = jiffies + SONY_RESET_TIMEOUT;
sony_sleep();
}
+ up(&sony_sem);
return 0;
}
static inline unsigned char read_status_register(void)
{
- return (inb(sony_cd_status_reg));
+ return inb(sony_cd_status_reg);
}
static inline unsigned char read_result_register(void)
{
- return (inb(sony_cd_result_reg));
+ return inb(sony_cd_result_reg);
}
static inline unsigned char read_data_register(void)
{
- return (inb(sony_cd_read_reg));
+ return inb(sony_cd_read_reg);
}
static inline void write_param(unsigned char param)
/* If something was waiting, wake it up now. */
if (waitqueue_active(&cdu31a_irq_wait)) {
disable_interrupts();
- wake_up(&cdu31a_irq_wait);
+ irq_flag = 1;
+ wake_up_interruptible(&cdu31a_irq_wait);
}
} else if (waitqueue_active(&cdu31a_irq_wait)) {
disable_interrupts();
- wake_up(&cdu31a_irq_wait);
+ irq_flag = 1;
+ wake_up_interruptible(&cdu31a_irq_wait);
} else {
disable_interrupts();
- printk
- ("CDU31A: Got an interrupt but nothing was waiting\n");
+ printk(KERN_NOTICE PFX
+ "Got an interrupt but nothing was waiting\n");
}
return IRQ_HANDLED;
}
static unsigned char errbuf[80];
switch (err_code) {
- case 0x10:
- return "illegal command ";
- case 0x11:
- return "illegal parameter ";
-
- case 0x20:
- return "not loaded ";
- case 0x21:
- return "no disc ";
- case 0x22:
- return "not spinning ";
- case 0x23:
- return "spinning ";
- case 0x25:
- return "spindle servo ";
- case 0x26:
- return "focus servo ";
- case 0x29:
- return "eject mechanism ";
- case 0x2a:
- return "audio playing ";
- case 0x2c:
- return "emergency eject ";
-
- case 0x30:
- return "focus ";
- case 0x31:
- return "frame sync ";
- case 0x32:
- return "subcode address ";
- case 0x33:
- return "block sync ";
- case 0x34:
- return "header address ";
-
- case 0x40:
- return "illegal track read ";
- case 0x41:
- return "mode 0 read ";
- case 0x42:
- return "illegal mode read ";
- case 0x43:
- return "illegal block size read ";
- case 0x44:
- return "mode read ";
- case 0x45:
- return "form read ";
- case 0x46:
- return "leadout read ";
- case 0x47:
- return "buffer overrun ";
-
- case 0x53:
- return "unrecoverable CIRC ";
- case 0x57:
- return "unrecoverable LECC ";
-
- case 0x60:
- return "no TOC ";
- case 0x61:
- return "invalid subcode data ";
- case 0x63:
- return "focus on TOC read ";
- case 0x64:
- return "frame sync on TOC read ";
- case 0x65:
- return "TOC data ";
-
- case 0x70:
- return "hardware failure ";
- case 0x91:
- return "leadin ";
- case 0x92:
- return "leadout ";
- case 0x93:
- return "data track ";
+ case 0x10: return "illegal command ";
+ case 0x11: return "illegal parameter ";
+
+ case 0x20: return "not loaded ";
+ case 0x21: return "no disc ";
+ case 0x22: return "not spinning ";
+ case 0x23: return "spinning ";
+ case 0x25: return "spindle servo ";
+ case 0x26: return "focus servo ";
+ case 0x29: return "eject mechanism ";
+ case 0x2a: return "audio playing ";
+ case 0x2c: return "emergency eject ";
+
+ case 0x30: return "focus ";
+ case 0x31: return "frame sync ";
+ case 0x32: return "subcode address ";
+ case 0x33: return "block sync ";
+ case 0x34: return "header address ";
+
+ case 0x40: return "illegal track read ";
+ case 0x41: return "mode 0 read ";
+ case 0x42: return "illegal mode read ";
+ case 0x43: return "illegal block size read ";
+ case 0x44: return "mode read ";
+ case 0x45: return "form read ";
+ case 0x46: return "leadout read ";
+ case 0x47: return "buffer overrun ";
+
+ case 0x53: return "unrecoverable CIRC ";
+ case 0x57: return "unrecoverable LECC ";
+
+ case 0x60: return "no TOC ";
+ case 0x61: return "invalid subcode data ";
+ case 0x63: return "focus on TOC read ";
+ case 0x64: return "frame sync on TOC read ";
+ case 0x65: return "TOC data ";
+
+ case 0x70: return "hardware failure ";
+ case 0x91: return "leadin ";
+ case 0x92: return "leadout ";
+ case 0x93: return "data track ";
}
sprintf(errbuf, "unknown 0x%02x ", err_code);
return errbuf;
do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
params, 2, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(" Unable to set spin-down time: 0x%2.2x\n",
- res_reg[1]);
+ printk(KERN_NOTICE PFX
+ "Unable to set spin-down time: 0x%2.2x\n", res_reg[1]);
}
params[0] = SONY_SD_MECH_CONTROL;
do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
params, 2, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(" Unable to set mechanical parameters: 0x%2.2x\n",
- res_reg[1]);
+ printk(KERN_NOTICE PFX "Unable to set mechanical "
+ "parameters: 0x%2.2x\n", res_reg[1]);
}
}
else
sony_speed = speed - 1;
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
set_drive_params(sony_speed);
+ up(&sony_sem);
return 0;
}
*/
static int scd_lock_door(struct cdrom_device_info *cdi, int lock)
{
- if (lock == 0 && sony_usage == 1) {
- /* Unlock the door, only if nobody is using the drive */
+ if (lock == 0) {
is_auto_eject = 1;
} else {
is_auto_eject = 0;
}
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
set_drive_params(sony_speed);
+ up(&sony_sem);
return 0;
}
unsigned long retry_count;
- printk("cdu31a: Resetting drive on error\n");
+ printk(KERN_NOTICE PFX "Resetting drive on error\n");
reset_drive();
retry_count = jiffies + SONY_RESET_TIMEOUT;
while (time_before(jiffies, retry_count) && (!is_attention())) {
set_drive_params(sony_speed);
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk("cdu31a: Unable to spin up drive: 0x%2.2x\n",
+ printk(KERN_NOTICE PFX "Unable to spin up drive: 0x%2.2x\n",
res_reg[1]);
}
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(2 * HZ);
+ msleep(2000);
sony_get_toc();
}
while (handle_sony_cd_attention());
}
if (is_busy() || (!(is_result_ready()))) {
-#if DEBUG
- printk("CDU31A timeout out %d\n", __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
result_buffer[0] = 0x20;
result_buffer[1] = SONY_TIMEOUT_OP_ERR;
*result_size = 2;
retry_count--;
}
if (!is_result_ready()) {
-#if DEBUG
- printk("CDU31A timeout out %d\n",
+ pr_debug(PFX "timeout out %d\n",
__LINE__);
-#endif
result_buffer[0] = 0x20;
result_buffer[1] =
SONY_TIMEOUT_OP_ERR;
retry_count--;
}
if (!is_result_ready()) {
-#if DEBUG
- printk("CDU31A timeout out %d\n",
+ pr_debug(PFX "timeout out %d\n",
__LINE__);
-#endif
result_buffer[0] = 0x20;
result_buffer[1] =
SONY_TIMEOUT_OP_ERR;
unsigned char *result_buffer, unsigned int *result_size)
{
unsigned long retry_count;
- int num_retries;
- int recursive_call;
- unsigned long flags;
-
-
- save_flags(flags);
- cli();
- if (current != has_cd_task) { /* Allow recursive calls to this routine */
- while (sony_inuse) {
- interruptible_sleep_on(&sony_wait);
- if (signal_pending(current)) {
- result_buffer[0] = 0x20;
- result_buffer[1] = SONY_SIGNAL_OP_ERR;
- *result_size = 2;
- restore_flags(flags);
- return;
- }
- }
- sony_inuse = 1;
- has_cd_task = current;
- recursive_call = 0;
- } else {
- recursive_call = 1;
- }
+ int num_retries = 0;
- num_retries = 0;
retry_cd_operation:
while (handle_sony_cd_attention());
- sti();
-
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
while (time_before(jiffies, retry_count) && (is_busy())) {
sony_sleep();
while (handle_sony_cd_attention());
}
if (is_busy()) {
-#if DEBUG
- printk("CDU31A timeout out %d\n", __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
result_buffer[0] = 0x20;
result_buffer[1] = SONY_TIMEOUT_OP_ERR;
*result_size = 2;
if (((result_buffer[0] & 0xf0) == 0x20)
&& (num_retries < MAX_CDU31A_RETRIES)) {
num_retries++;
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ / 10); /* Wait .1 seconds on retries */
+ msleep(100);
goto retry_cd_operation;
}
-
- if (!recursive_call) {
- has_cd_task = NULL;
- sony_inuse = 0;
- wake_up_interruptible(&sony_wait);
- }
-
- restore_flags(flags);
}
volatile int val;
-#if 0*DEBUG
- printk("Entering handle_sony_cd_attention\n");
+#if 0
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
#endif
if (is_attention()) {
if (num_consecutive_attentions >
CDU31A_MAX_CONSECUTIVE_ATTENTIONS) {
- printk
- ("cdu31a: Too many consecutive attentions: %d\n",
- num_consecutive_attentions);
+ printk(KERN_NOTICE PFX "Too many consecutive "
+ "attentions: %d\n", num_consecutive_attentions);
num_consecutive_attentions = 0;
-#if DEBUG
- printk("Leaving handle_sony_cd_attention at %d\n",
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__,
__LINE__);
-#endif
- return (0);
+ return 0;
}
clear_attention();
}
num_consecutive_attentions++;
-#if DEBUG
- printk("Leaving handle_sony_cd_attention at %d\n",
- __LINE__);
-#endif
- return (1);
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
+ return 1;
} else if (abort_read_started) {
while (is_result_reg_not_empty()) {
val = read_result_register();
val = read_data_register();
}
abort_read_started = 0;
-#if DEBUG
- printk("Leaving handle_sony_cd_attention at %d\n",
- __LINE__);
-#endif
- return (1);
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
+ return 1;
}
num_consecutive_attentions = 0;
-#if 0*DEBUG
- printk("Leaving handle_sony_cd_attention at %d\n", __LINE__);
+#if 0
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
#endif
- return (0);
+ return 0;
}
retval = (val / 10) << 4;
retval = retval | val % 10;
- return (retval);
+ return retval;
}
/* Convert from BCD to an integer from 0-99 */
static unsigned int bcd_to_int(unsigned int bcd)
{
- return ((((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f));
+ return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
}
operation if the requested sector is not the next one from the
drive. */
static int
-start_request(unsigned int sector, unsigned int nsect, int read_nsect_only)
+start_request(unsigned int sector, unsigned int nsect)
{
unsigned char params[6];
- unsigned int read_size;
unsigned long retry_count;
-#if DEBUG
- printk("Entering start_request\n");
-#endif
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
log_to_msf(sector, params);
- /* If requested, read exactly what was asked. */
- if (read_nsect_only) {
- read_size = nsect;
- }
- /*
- * 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.
- */
- else if ((sector + nsect) >= sony_toc.lead_out_start_lba) {
- read_size = sony_toc.lead_out_start_lba - sector;
- }
- /* Read the full readahead amount. */
- else {
- read_size = CDU31A_READAHEAD / 4;
- }
- size_to_buf(read_size, ¶ms[3]);
+ size_to_buf(nsect, ¶ms[3]);
/*
* Clear any outstanding attentions and wait for the drive to
}
if (is_busy()) {
- printk("CDU31A: Timeout while waiting to issue command\n");
-#if DEBUG
- printk("Leaving start_request at %d\n", __LINE__);
-#endif
- return (1);
+ printk(KERN_NOTICE PFX "Timeout while waiting "
+ "to issue command\n");
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
+ return 1;
} else {
/* Issue the command */
clear_result_ready();
write_params(params, 6);
write_cmd(SONY_READ_BLKERR_STAT_CMD);
- sony_blocks_left = read_size * 4;
+ sony_blocks_left = nsect * 4;
sony_next_block = sector * 4;
- readahead_dataleft = 0;
- readahead_bad = 0;
-#if DEBUG
- printk("Leaving start_request at %d\n", __LINE__);
-#endif
- return (0);
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
+ return 0;
}
-#if DEBUG
- printk("Leaving start_request at %d\n", __LINE__);
-#endif
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
}
-/* Abort a pending read operation. Clear all the drive status and
- readahead variables. */
+/* Abort a pending read operation. Clear all the drive status variables. */
static void abort_read(void)
{
unsigned char result_reg[2];
do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size);
if ((result_reg[0] & 0xf0) == 0x20) {
- printk("CDU31A: Error aborting read, %s error\n",
+ printk(KERN_ERR PFX "Aborting read, %s error\n",
translate_error(result_reg[1]));
}
}
sony_blocks_left = 0;
- readahead_dataleft = 0;
- readahead_bad = 0;
}
/* Called when the timer times out. This will abort the
pending read operation. */
static void handle_abort_timeout(unsigned long data)
{
- unsigned long flags;
-
-#if DEBUG
- printk("Entering handle_abort_timeout\n");
-#endif
- save_flags(flags);
- cli();
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
/* If it is in use, ignore it. */
- if (!sony_inuse) {
+ if (down_trylock(&sony_sem) == 0) {
/* We can't use abort_read(), because it will sleep
or schedule in the timer interrupt. Just start
the operation, finish it on the next access to
write_cmd(SONY_ABORT_CMD);
sony_blocks_left = 0;
- readahead_dataleft = 0;
- readahead_bad = 0;
abort_read_started = 1;
+ up(&sony_sem);
}
- restore_flags(flags);
-#if DEBUG
- printk("Leaving handle_abort_timeout\n");
-#endif
+ pr_debug(PFX "Leaving %s\n", __FUNCTION__);
}
-/* Actually get data and status from the drive. */
+/* Actually get one sector of data from the drive. */
static void
-input_data(char *buffer,
- unsigned int bytesleft,
- unsigned int nblocks, unsigned int offset, unsigned int skip)
+input_data_sector(char *buffer)
{
- int i;
- volatile unsigned char val;
-
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
-#if DEBUG
- printk("Entering input_data\n");
-#endif
/* If an XA disk on a CDU31A, skip the first 12 bytes of data from
- the disk. The real data is after that. */
- if (sony_xa_mode) {
- for (i = 0; i < CD_XA_HEAD; i++) {
- val = read_data_register();
- }
- }
+ the disk. The real data is after that. We can use audio_buffer. */
+ if (sony_xa_mode)
+ insb(sony_cd_read_reg, audio_buffer, CD_XA_HEAD);
clear_data_ready();
- if (bytesleft == 2048) { /* 2048 byte direct buffer transfer */
- insb(sony_cd_read_reg, buffer, 2048);
- readahead_dataleft = 0;
- } else {
- /* If the input read did not align with the beginning of the block,
- skip the necessary bytes. */
- if (skip != 0) {
- insb(sony_cd_read_reg, readahead_buffer, skip);
- }
-
- /* Get the data into the buffer. */
- insb(sony_cd_read_reg, &buffer[offset], bytesleft);
-
- /* Get the rest of the data into the readahead buffer at the
- proper location. */
- readahead_dataleft = (2048 - skip) - bytesleft;
- insb(sony_cd_read_reg,
- readahead_buffer + bytesleft, readahead_dataleft);
- }
- sony_blocks_left -= nblocks;
- sony_next_block += nblocks;
+ insb(sony_cd_read_reg, buffer, 2048);
/* If an XA disk, we have to clear out the rest of the unused
- error correction data. */
- if (sony_xa_mode) {
- for (i = 0; i < CD_XA_TAIL; i++) {
- val = read_data_register();
- }
- }
-#if DEBUG
- printk("Leaving input_data at %d\n", __LINE__);
-#endif
+ error correction data. We can use audio_buffer for that. */
+ if (sony_xa_mode)
+ insb(sony_cd_read_reg, audio_buffer, CD_XA_TAIL);
+
+ pr_debug(PFX "Leaving %s\n", __FUNCTION__);
}
/* read data from the drive. Note the nsect must be <= 4. */
unsigned char res_reg[], int *res_size)
{
unsigned long retry_count;
- unsigned int bytesleft;
- unsigned int offset;
- unsigned int skip;
-
-#if DEBUG
- printk("Entering read_data_block\n");
-#endif
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
res_reg[0] = 0;
res_reg[1] = 0;
*res_size = 0;
- bytesleft = nblocks * 512;
- offset = 0;
-
- /* If the data in the read-ahead does not match the block offset,
- then fix things up. */
- if (((block % 4) * 512) != ((2048 - readahead_dataleft) % 2048)) {
- sony_next_block += block % 4;
- sony_blocks_left -= block % 4;
- skip = (block % 4) * 512;
- } else {
- skip = 0;
- }
-
- /* We have readahead data in the buffer, get that first before we
- decide if a read is necessary. */
- if (readahead_dataleft != 0) {
- if (bytesleft > readahead_dataleft) {
- /* The readahead will not fill the requested buffer, but
- get the data out of the readahead into the buffer. */
- memcpy(buffer,
- readahead_buffer + (2048 -
- readahead_dataleft),
- readahead_dataleft);
- bytesleft -= readahead_dataleft;
- offset += readahead_dataleft;
- readahead_dataleft = 0;
- } else {
- /* The readahead will fill the whole buffer, get the data
- and return. */
- memcpy(buffer,
- readahead_buffer + (2048 -
- readahead_dataleft),
- bytesleft);
- readahead_dataleft -= bytesleft;
- bytesleft = 0;
- sony_blocks_left -= nblocks;
- sony_next_block += nblocks;
-
- /* If the data in the readahead is bad, return an error so the
- driver will abort the buffer. */
- if (readahead_bad) {
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
-
- if (readahead_dataleft == 0) {
- readahead_bad = 0;
- }
-
- /* Final transfer is done for read command, get final result. */
- if (sony_blocks_left == 0) {
- get_result(res_reg, res_size);
- }
-#if DEBUG
- printk("Leaving read_data_block at %d\n",
- __LINE__);
-#endif
- return;
- }
- }
/* Wait for the drive to tell us we have something */
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
if (is_result_ready()) {
get_result(res_reg, res_size);
if ((res_reg[0] & 0xf0) != 0x20) {
- printk
- ("CDU31A: Got result that should have been error: %d\n",
- res_reg[0]);
+ printk(KERN_NOTICE PFX "Got result that should"
+ " have been error: %d\n", res_reg[0]);
res_reg[0] = 0x20;
res_reg[1] = SONY_BAD_DATA_ERR;
*res_size = 2;
}
abort_read();
} else {
-#if DEBUG
- printk("CDU31A timeout out %d\n", __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
res_reg[0] = 0x20;
res_reg[1] = SONY_TIMEOUT_OP_ERR;
*res_size = 2;
abort_read();
}
} else {
- input_data(buffer, bytesleft, nblocks, offset, skip);
+ input_data_sector(buffer);
+ sony_blocks_left -= nblocks;
+ sony_next_block += nblocks;
/* Wait for the status from the drive. */
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
}
if (!is_result_ready()) {
-#if DEBUG
- printk("CDU31A timeout out %d\n", __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
res_reg[0] = 0x20;
res_reg[1] = SONY_TIMEOUT_OP_ERR;
*res_size = 2;
SONY_NO_LECC_ERR_BLK_STAT)
|| (res_reg[0] ==
SONY_RECOV_LECC_ERR_BLK_STAT)) {
- /* The data was successful, but if data was read from
- the readahead and it was bad, set the whole
- buffer as bad. */
- if (readahead_bad) {
- readahead_bad = 0;
- res_reg[0] = 0x20;
- res_reg[1] =
- SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
+ /* nothing here */
} else {
- printk
- ("CDU31A: Data block error: 0x%x\n",
- res_reg[0]);
+ printk(KERN_ERR PFX "Data block "
+ "error: 0x%x\n", res_reg[0]);
res_reg[0] = 0x20;
res_reg[1] = SONY_BAD_DATA_ERR;
*res_size = 2;
-
- /* Data is in the readahead buffer but an error was returned.
- Make sure future requests don't use the data. */
- if (bytesleft != 2048) {
- readahead_bad = 1;
- }
}
/* Final transfer is done for read command, get final result. */
} else if ((res_reg[0] & 0xf0) != 0x20) {
/* The drive gave me bad status, I don't know what to do.
Reset the driver and return an error. */
- printk
- ("CDU31A: Invalid block status: 0x%x\n",
- res_reg[0]);
+ printk(KERN_ERR PFX "Invalid block "
+ "status: 0x%x\n", res_reg[0]);
restart_on_error();
res_reg[0] = 0x20;
res_reg[1] = SONY_BAD_DATA_ERR;
}
}
}
-#if DEBUG
- printk("Leaving read_data_block at %d\n", __LINE__);
-#endif
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
}
static void do_cdu31a_request(request_queue_t * q)
{
struct request *req;
- int block;
- int nblock;
+ int block, nblock, num_retries;
unsigned char res_reg[12];
unsigned int res_size;
- int num_retries;
- unsigned long flags;
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
-#if DEBUG
- printk("Entering do_cdu31a_request\n");
-#endif
-
- /*
- * Make sure no one else is using the driver; wait for them
- * to finish if it is so.
- */
- save_flags(flags);
- cli();
- while (sony_inuse) {
- interruptible_sleep_on(&sony_wait);
- if (signal_pending(current)) {
- restore_flags(flags);
-#if DEBUG
- printk("Leaving do_cdu31a_request at %d\n",
- __LINE__);
-#endif
- return;
- }
+ spin_unlock_irq(q->queue_lock);
+ if (down_interruptible(&sony_sem)) {
+ spin_lock_irq(q->queue_lock);
+ return;
}
- sony_inuse = 1;
- has_cd_task = current;
/* Get drive status before doing anything. */
while (handle_sony_cd_attention());
/* Make sure we have a valid TOC. */
sony_get_toc();
- /*
- * jens: driver has lots of races
- */
- spin_unlock_irq(q->queue_lock);
/* Make sure the timer is cancelled. */
del_timer(&cdu31a_abort_timer);
block = req->sector;
nblock = req->nr_sectors;
-
+ pr_debug(PFX "request at block %d, length %d blocks\n",
+ block, nblock);
if (!sony_toc_read) {
- printk("CDU31A: TOC not read\n");
+ printk(KERN_NOTICE PFX "TOC not read\n");
end_request(req, 0);
continue;
}
end_request(req, 0);
continue;
}
- if (rq_data_dir(req) != READ)
- panic("CDU31A: Unknown cmd");
+
/*
* If the block address is invalid or the request goes beyond the end of
* the media, return an error.
*/
- if ((block / 4) >= sony_toc.lead_out_start_lba) {
- printk("CDU31A: Request past end of media\n");
- end_request(req, 0);
- continue;
- }
if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) {
- printk("CDU31A: Request past end of media\n");
+ printk(KERN_NOTICE PFX "Request past end of media\n");
end_request(req, 0);
continue;
}
+ if (nblock > 4)
+ nblock = 4;
num_retries = 0;
try_read_again:
while (handle_sony_cd_attention());
if (!sony_toc_read) {
- printk("CDU31A: TOC not read\n");
+ printk(KERN_NOTICE PFX "TOC not read\n");
end_request(req, 0);
continue;
}
/* If no data is left to be read from the drive, start the
next request. */
if (sony_blocks_left == 0) {
- if (start_request(block / 4, CDU31A_READAHEAD / 4, 0)) {
+ if (start_request(block / 4, nblock / 4)) {
end_request(req, 0);
continue;
}
the driver, abort the current operation and start a
new one. */
else if (block != sony_next_block) {
-#if DEBUG
- printk("CDU31A Warning: Read for block %d, expected %d\n",
+ pr_debug(PFX "Read for block %d, expected %d\n",
block, sony_next_block);
-#endif
abort_read();
if (!sony_toc_read) {
- printk("CDU31A: TOC not read\n");
+ printk(KERN_NOTICE PFX "TOC not read\n");
end_request(req, 0);
continue;
}
- if (start_request(block / 4, CDU31A_READAHEAD / 4, 0)) {
- printk("CDU31a: start request failed\n");
+ if (start_request(block / 4, nblock / 4)) {
+ printk(KERN_NOTICE PFX "start request failed\n");
end_request(req, 0);
continue;
}
read_data_block(req->buffer, block, nblock, res_reg, &res_size);
if (res_reg[0] != 0x20) {
- end_request(req, 1);
+ if (!end_that_request_first(req, 1, nblock)) {
+ spin_lock_irq(q->queue_lock);
+ blkdev_dequeue_request(req);
+ end_that_request_last(req, 1);
+ spin_unlock_irq(q->queue_lock);
+ }
continue;
}
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
&res_size);
} else {
- printk("CDU31A: %s error for block %d, nblock %d\n",
+ printk(KERN_NOTICE PFX "%s error for block %d, nblock %d\n",
translate_error(res_reg[1]), block, nblock);
}
goto try_read_again;
}
end_do_cdu31a_request:
- spin_lock_irq(q->queue_lock);
#if 0
/* After finished, cancel any pending operations. */
abort_read();
add_timer(&cdu31a_abort_timer);
#endif
- has_cd_task = NULL;
- sony_inuse = 0;
- wake_up_interruptible(&sony_wait);
- restore_flags(flags);
-#if DEBUG
- printk("Leaving do_cdu31a_request at %d\n", __LINE__);
-#endif
+ up(&sony_sem);
+ spin_lock_irq(q->queue_lock);
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
}
int mint = 99;
int maxt = 0;
-#if DEBUG
- printk("Entering sony_get_toc\n");
-#endif
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
num_spin_ups = 0;
if (!sony_toc_read) {
/* This seems to slow things down enough to make it work. This
* appears to be a problem in do_sony_cd_cmd. This printk seems
* to address the symptoms... -Erik */
-#if 1
- printk("cdu31a: Trying session %d\n", session);
-#endif
+ pr_debug(PFX "Trying session %d\n", session);
parms[0] = session;
do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD,
parms, 1, res_reg, &res_size);
-#if DEBUG
- printk("%2.2x %2.2x\n", res_reg[0], res_reg[1]);
-#endif
+ pr_debug(PFX "%2.2x %2.2x\n", res_reg[0], res_reg[1]);
if ((res_size < 2)
|| ((res_reg[0] & 0xf0) == 0x20)) {
("Yikes! Couldn't read any sessions!");
break;
}
-#if DEBUG
- printk("Reading session %d\n", session);
-#endif
+ pr_debug(PFX "Reading session %d\n", session);
parms[0] = session;
do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,
if ((res_size < 2)
|| ((single_toc.exec_status[0] & 0xf0) ==
0x20)) {
- printk
- ("cdu31a: Error reading session %d: %x %s\n",
+ printk(KERN_ERR PFX "Error reading "
+ "session %d: %x %s\n",
session, single_toc.exec_status[0],
translate_error(single_toc.
exec_status[1]));
set. */
return;
}
-#if DEBUG
- printk
- ("add0 %01x, con0 %01x, poi0 %02x, 1st trk %d, dsktyp %x, dum0 %x\n",
+ pr_debug(PFX "add0 %01x, con0 %01x, poi0 %02x, "
+ "1st trk %d, dsktyp %x, dum0 %x\n",
single_toc.address0, single_toc.control0,
single_toc.point0,
bcd_to_int(single_toc.first_track_num),
single_toc.disk_type, single_toc.dummy0);
- printk
- ("add1 %01x, con1 %01x, poi1 %02x, lst trk %d, dummy1 %x, dum2 %x\n",
+ pr_debug(PFX "add1 %01x, con1 %01x, poi1 %02x, "
+ "lst trk %d, dummy1 %x, dum2 %x\n",
single_toc.address1, single_toc.control1,
single_toc.point1,
bcd_to_int(single_toc.last_track_num),
single_toc.dummy1, single_toc.dummy2);
- printk
- ("add2 %01x, con2 %01x, poi2 %02x leadout start min %d, sec %d, frame %d\n",
+ pr_debug(PFX "add2 %01x, con2 %01x, poi2 %02x "
+ "leadout start min %d, sec %d, frame %d\n",
single_toc.address2, single_toc.control2,
single_toc.point2,
bcd_to_int(single_toc.lead_out_start_msf[0]),
bcd_to_int(single_toc.lead_out_start_msf[1]),
bcd_to_int(single_toc.lead_out_start_msf[2]));
if (res_size > 18 && single_toc.pointb0 > 0xaf)
- printk
- ("addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
+ pr_debug(PFX "addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
"#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n",
single_toc.addressb0,
single_toc.controlb0,
max_start_outer_leadout_msf
[2]));
if (res_size > 27 && single_toc.pointb1 > 0xaf)
- printk
- ("addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
+ pr_debug(PFX "addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
single_toc.addressb1,
single_toc.controlb1,
single_toc.pointb1,
single_toc.num_skip_track_assignments,
single_toc.dummyb0_2);
if (res_size > 36 && single_toc.pointb2 > 0xaf)
- printk
- ("addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ pr_debug(PFX "addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressb2,
single_toc.controlb2,
single_toc.pointb2,
single_toc.tracksb2[5],
single_toc.tracksb2[6]);
if (res_size > 45 && single_toc.pointb3 > 0xaf)
- printk
- ("addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ pr_debug(PFX "addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressb3,
single_toc.controlb3,
single_toc.pointb3,
single_toc.tracksb3[5],
single_toc.tracksb3[6]);
if (res_size > 54 && single_toc.pointb4 > 0xaf)
- printk
- ("addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ pr_debug(PFX "addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressb4,
single_toc.controlb4,
single_toc.pointb4,
single_toc.tracksb4[5],
single_toc.tracksb4[6]);
if (res_size > 63 && single_toc.pointc0 > 0xaf)
- printk
- ("addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ pr_debug(PFX "addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressc0,
single_toc.controlc0,
single_toc.pointc0,
single_toc.dummyc0[4],
single_toc.dummyc0[5],
single_toc.dummyc0[6]);
-#endif
#undef DEBUG
#define DEBUG 0
res_size += 9;
}
#if DEBUG
- printk
- ("start track lba %u, leadout start lba %u\n",
+ printk(PRINT_INFO PFX "start track lba %u, "
+ "leadout start lba %u\n",
single_toc.start_track_lba,
single_toc.lead_out_start_lba);
{
-
bcd_to_int(single_toc.
first_track_num); i++) {
- printk
- ("trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n",
+ printk(KERN_INFO PFX "trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n",
i,
single_toc.tracks[i].address,
single_toc.tracks[i].control,
tracks[i].
track);
}
- printk
- ("min track number %d, max track number %d\n",
+ printk(KERN_INFO PFX "min track number %d, "
+ "max track number %d\n",
mint, maxt);
}
#endif
/* Let's not get carried away... */
if (session > 40) {
- printk("cdu31a: too many sessions: %d\n",
- session);
+ printk(KERN_NOTICE PFX "too many sessions: "
+ "%d\n", session);
break;
}
session++;
sony_toc.lead_out_start_msf[2];
sony_toc_read = 1;
-#undef DEBUG
-#if DEBUG
- printk
- ("Disk session %d, start track: %d, stop track: %d\n",
+
+ pr_debug(PFX "Disk session %d, start track: %d, "
+ "stop track: %d\n",
session, single_toc.start_track_lba,
single_toc.lead_out_start_lba);
-#endif
}
-#if DEBUG
- printk("Leaving sony_get_toc\n");
-#endif
+ pr_debug(PFX "Leaving %s\n", __FUNCTION__);
}
if (ms_info == NULL)
return 1;
- if (!sony_toc_read)
+ if (!sony_toc_read) {
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
sony_get_toc();
+ up(&sony_sem);
+ }
ms_info->addr_format = CDROM_LBA;
ms_info->addr.lba = sony_toc.start_track_lba;
0, (unsigned char *) &last_sony_subcode, &res_size);
if ((res_size < 2)
|| ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) {
- printk("Sony CDROM error %s (read_subcode)\n",
+ printk(KERN_ERR PFX "Sony CDROM error %s (read_subcode)\n",
translate_error(last_sony_subcode.exec_status[1]));
return -EIO;
}
unsigned int res_size;
memset(mcn->medium_catalog_number, 0, 14);
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD,
NULL, 0, resbuffer, &res_size);
+ up(&sony_sem);
if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20));
else {
/* packed bcd to single ASCII digits */
}
/* Invalid data from the drive. Shut down the operation. */
else if ((res_reg[0] & 0xf0) != 0x20) {
- printk
- ("CDU31A: Got result that should have been error: %d\n",
+ printk(KERN_WARNING PFX "Got result that "
+ "should have been error: %d\n",
res_reg[0]);
res_reg[0] = 0x20;
res_reg[1] = SONY_BAD_DATA_ERR;
}
abort_read();
} else {
-#if DEBUG
- printk("CDU31A timeout out %d\n", __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
res_reg[0] = 0x20;
res_reg[1] = SONY_TIMEOUT_OP_ERR;
*res_size = 2;
}
if (!is_result_ready()) {
-#if DEBUG
- printk("CDU31A timeout out %d\n",
- __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
res_reg[0] = 0x20;
res_reg[1] = SONY_TIMEOUT_OP_ERR;
*res_size = 2;
|| (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) {
/* Ok, nothing to do. */
} else {
- printk("CDU31A: Data block error: 0x%x\n",
+ printk(KERN_ERR PFX "Data block error: 0x%x\n",
res_reg[0]);
res_reg[0] = 0x20;
res_reg[1] = SONY_BAD_DATA_ERR;
} else if ((res_reg[0] & 0xf0) != 0x20) {
/* The drive gave me bad status, I don't know what to do.
Reset the driver and return an error. */
- printk("CDU31A: Invalid block status: 0x%x\n",
+ printk(KERN_NOTICE PFX "Invalid block status: 0x%x\n",
res_reg[0]);
restart_on_error();
res_reg[0] = 0x20;
unsigned char res_reg[12];
unsigned int res_size;
unsigned int cframe;
- unsigned long flags;
-
- /*
- * Make sure no one else is using the driver; wait for them
- * to finish if it is so.
- */
- save_flags(flags);
- cli();
- while (sony_inuse) {
- interruptible_sleep_on(&sony_wait);
- if (signal_pending(current)) {
- restore_flags(flags);
- return -EAGAIN;
- }
- }
- sony_inuse = 1;
- has_cd_task = current;
- restore_flags(flags);
- if (!sony_spun_up) {
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
+ if (!sony_spun_up)
scd_spinup();
- }
/* Set the drive to do raw operations. */
params[0] = SONY_SD_DECODE_PARAM;
do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
params, 2, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk("CDU31A: Unable to set decode params: 0x%2.2x\n",
+ printk(KERN_ERR PFX "Unable to set decode params: 0x%2.2x\n",
res_reg[1]);
- return -EIO;
+ retval = -EIO;
+ goto out_up;
}
/* From here down, we have to goto exit_read_audio instead of returning
return. */
retval = 0;
- /* start_request clears out any readahead data, so it should be safe. */
- if (start_request(ra->addr.lba, ra->nframes, 1)) {
+ if (start_request(ra->addr.lba, ra->nframes)) {
retval = -EIO;
goto exit_read_audio;
}
/* For every requested frame. */
cframe = 0;
while (cframe < ra->nframes) {
- read_audio_data(readahead_buffer, res_reg, &res_size);
+ read_audio_data(audio_buffer, res_reg, &res_size);
if ((res_reg[0] & 0xf0) == 0x20) {
if (res_reg[1] == SONY_BAD_DATA_ERR) {
- printk
- ("CDU31A: Data error on audio sector %d\n",
+ printk(KERN_ERR PFX "Data error on audio "
+ "sector %d\n",
ra->addr.lba + cframe);
} else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) {
/* Illegal track type, change track types and start over. */
2, res_reg, &res_size);
if ((res_size < 2)
|| ((res_reg[0] & 0xf0) == 0x20)) {
- printk
- ("CDU31A: Unable to set decode params: 0x%2.2x\n",
+ printk(KERN_ERR PFX "Unable to set "
+ "decode params: 0x%2.2x\n",
res_reg[1]);
retval = -EIO;
goto exit_read_audio;
/* Restart the request on the current frame. */
if (start_request
(ra->addr.lba + cframe,
- ra->nframes - cframe, 1)) {
+ ra->nframes - cframe)) {
retval = -EIO;
goto exit_read_audio;
}
/* Don't go back to the top because don't want to get into
and infinite loop. A lot of code gets duplicated, but
that's no big deal, I don't guess. */
- read_audio_data(readahead_buffer, res_reg,
+ read_audio_data(audio_buffer, res_reg,
&res_size);
if ((res_reg[0] & 0xf0) == 0x20) {
if (res_reg[1] ==
SONY_BAD_DATA_ERR) {
- printk
- ("CDU31A: Data error on audio sector %d\n",
+ printk(KERN_ERR PFX "Data error"
+ " on audio sector %d\n",
ra->addr.lba +
cframe);
} else {
- printk
- ("CDU31A: Error reading audio data on sector %d: %s\n",
+ printk(KERN_ERR PFX "Error reading audio data on sector %d: %s\n",
ra->addr.lba + cframe,
translate_error
(res_reg[1]));
} else if (copy_to_user(ra->buf +
(CD_FRAMESIZE_RAW
* cframe),
- readahead_buffer,
+ audio_buffer,
CD_FRAMESIZE_RAW)) {
retval = -EFAULT;
goto exit_read_audio;
}
} else {
- printk
- ("CDU31A: Error reading audio data on sector %d: %s\n",
+ printk(KERN_ERR PFX "Error reading audio "
+ "data on sector %d: %s\n",
ra->addr.lba + cframe,
translate_error(res_reg[1]));
retval = -EIO;
goto exit_read_audio;
}
} else if (copy_to_user(ra->buf + (CD_FRAMESIZE_RAW * cframe),
- (char *)readahead_buffer,
+ (char *)audio_buffer,
CD_FRAMESIZE_RAW)) {
retval = -EFAULT;
goto exit_read_audio;
get_result(res_reg, &res_size);
if ((res_reg[0] & 0xf0) == 0x20) {
- printk("CDU31A: Error return from audio read: %s\n",
+ printk(KERN_ERR PFX "Error return from audio read: %s\n",
translate_error(res_reg[1]));
retval = -EIO;
goto exit_read_audio;
do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
params, 2, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk("CDU31A: Unable to reset decode params: 0x%2.2x\n",
+ printk(KERN_ERR PFX "Unable to reset decode params: 0x%2.2x\n",
res_reg[1]);
- return -EIO;
+ retval = -EIO;
}
- has_cd_task = NULL;
- sony_inuse = 0;
- wake_up_interruptible(&sony_wait);
+ out_up:
+ up(&sony_sem);
- return (retval);
+ return retval;
}
static int
do_sony_cd_cmd(cmd, params, num_params, result_buffer,
result_size);
if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) {
- printk("Sony CDROM error %s (CDROM%s)\n",
+ printk(KERN_ERR PFX "Error %s (CDROM%s)\n",
translate_error(result_buffer[1]), name);
return -EIO;
}
*/
static int scd_tray_move(struct cdrom_device_info *cdi, int position)
{
+ int retval;
+
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
if (position == 1 /* open tray */ ) {
unsigned char res_reg[12];
unsigned int res_size;
&res_size);
sony_audio_status = CDROM_AUDIO_INVALID;
- return do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0,
+ retval = do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0,
res_reg, &res_size);
} else {
if (0 == scd_spinup())
sony_spun_up = 1;
- return 0;
+ retval = 0;
}
+ up(&sony_sem);
+ return retval;
}
/*
unsigned char res_reg[12];
unsigned int res_size;
unsigned char params[7];
- int i;
-
+ int i, retval;
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
switch (cmd) {
case CDROMSTART: /* Spin up the drive */
- return do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL,
+ retval = do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL,
0, res_reg, &res_size);
break;
* already not spinning.
*/
sony_audio_status = CDROM_AUDIO_NO_STATUS;
- return do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL,
+ retval = do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL,
0, res_reg, &res_size);
+ break;
case CDROMPAUSE: /* Pause the drive */
if (do_sony_cd_cmd_chk
("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size))
- return -EIO;
+ &res_size)) {
+ retval = -EIO;
+ break;
+ }
/* Get the current position and save it for resuming */
if (read_subcode() < 0) {
- return -EIO;
+ retval = -EIO;
+ break;
}
cur_pos_msf[0] = last_sony_subcode.abs_msf[0];
cur_pos_msf[1] = last_sony_subcode.abs_msf[1];
cur_pos_msf[2] = last_sony_subcode.abs_msf[2];
sony_audio_status = CDROM_AUDIO_PAUSED;
- return 0;
+ retval = 0;
break;
case CDROMRESUME: /* Start the drive after being paused */
if (sony_audio_status != CDROM_AUDIO_PAUSED) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
params[0] = 0x03;
if (do_sony_cd_cmd_chk
("RESUME", SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg,
- &res_size) < 0)
- return -EIO;
+ &res_size) < 0) {
+ retval = -EIO;
+ break;
+ }
sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
+ retval = 0;
+ break;
case CDROMPLAYMSF: /* Play starting at the given MSF address. */
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
params[0] = 0x03;
if (do_sony_cd_cmd_chk
("PLAYMSF", SONY_AUDIO_PLAYBACK_CMD, params, 7,
- res_reg, &res_size) < 0)
- return -EIO;
+ res_reg, &res_size) < 0) {
+ retval = -EIO;
+ break;
+ }
/* Save the final position for pauses and resumes */
final_pos_msf[0] = bcd_to_int(params[4]);
final_pos_msf[1] = bcd_to_int(params[5]);
final_pos_msf[2] = bcd_to_int(params[6]);
sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
+ retval = 0;
+ break;
case CDROMREADTOCHDR: /* Read the table of contents header */
{
sony_get_toc();
if (!sony_toc_read) {
- return -EIO;
+ retval = -EIO;
+ break;
}
hdr = (struct cdrom_tochdr *) arg;
hdr->cdth_trk0 = sony_toc.first_track_num;
hdr->cdth_trk1 = sony_toc.last_track_num;
}
- return 0;
+ retval = 0;
+ break;
case CDROMREADTOCENTRY: /* Read a given table of contents entry */
{
sony_get_toc();
if (!sony_toc_read) {
- return -EIO;
+ retval = -EIO;
+ break;
}
entry = (struct cdrom_tocentry *) arg;
track_idx = find_track(entry->cdte_track);
if (track_idx < 0) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
entry->cdte_adr =
*(msf_val + 2);
}
}
- return 0;
+ retval = 0;
break;
case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
sony_get_toc();
if (!sony_toc_read) {
- return -EIO;
+ retval = -EIO;
+ break;
}
if ((ti->cdti_trk0 < sony_toc.first_track_num)
|| (ti->cdti_trk0 > sony_toc.last_track_num)
|| (ti->cdti_trk1 < ti->cdti_trk0)) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
track_idx = find_track(ti->cdti_trk0);
if (track_idx < 0) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
params[1] =
int_to_bcd(sony_toc.tracks[track_idx].
track_idx = find_track(ti->cdti_trk1 + 1);
}
if (track_idx < 0) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
params[4] =
int_to_bcd(sony_toc.tracks[track_idx].
if ((res_size < 2)
|| ((res_reg[0] & 0xf0) == 0x20)) {
- printk("Params: %x %x %x %x %x %x %x\n",
+ printk(KERN_ERR PFX
+ "Params: %x %x %x %x %x %x %x\n",
params[0], params[1], params[2],
params[3], params[4], params[5],
params[6]);
- printk
- ("Sony CDROM error %s (CDROMPLAYTRKIND)\n",
+ printk(KERN_ERR PFX
+ "Error %s (CDROMPLAYTRKIND)\n",
translate_error(res_reg[1]));
- return -EIO;
+ retval = -EIO;
+ break;
}
/* Save the final position for pauses and resumes */
final_pos_msf[1] = bcd_to_int(params[5]);
final_pos_msf[2] = bcd_to_int(params[6]);
sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
+ retval = 0;
+ break;
}
case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */
params[0] = SONY_SD_AUDIO_VOLUME;
params[1] = volctrl->channel0;
params[2] = volctrl->channel1;
- return do_sony_cd_cmd_chk("VOLCTRL",
+ retval = do_sony_cd_cmd_chk("VOLCTRL",
SONY_SET_DRIVE_PARAM_CMD,
params, 3, res_reg,
&res_size);
+ break;
}
case CDROMSUBCHNL: /* Get subchannel info */
- return sony_get_subchnl_info((struct cdrom_subchnl *) arg);
+ retval = sony_get_subchnl_info((struct cdrom_subchnl *) arg);
+ break;
default:
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
+ up(&sony_sem);
+ return retval;
}
-static int scd_dev_ioctl(struct cdrom_device_info *cdi,
+static int scd_read_audio(struct cdrom_device_info *cdi,
unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
- int i;
+ int retval;
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
switch (cmd) {
case CDROMREADAUDIO: /* Read 2352 byte audio tracks and 2340 byte
raw data tracks. */
sony_get_toc();
if (!sony_toc_read) {
- return -EIO;
+ retval = -EIO;
+ break;
}
- if (copy_from_user(&ra, argp, sizeof(ra)))
- return -EFAULT;
+ if (copy_from_user(&ra, argp, sizeof(ra))) {
+ retval = -EFAULT;
+ break;
+ }
if (ra.nframes == 0) {
- return 0;
+ retval = 0;
+ break;
}
- i = verify_area(VERIFY_WRITE, ra.buf,
- CD_FRAMESIZE_RAW * ra.nframes);
- if (i < 0)
- return i;
+ if (!access_ok(VERIFY_WRITE, ra.buf,
+ CD_FRAMESIZE_RAW * ra.nframes))
+ return -EFAULT;
if (ra.addr_format == CDROM_LBA) {
if ((ra.addr.lba >=
sony_toc.lead_out_start_lba)
|| (ra.addr.lba + ra.nframes >=
sony_toc.lead_out_start_lba)) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
} else if (ra.addr_format == CDROM_MSF) {
if ((ra.addr.msf.minute >= 75)
|| (ra.addr.msf.second >= 60)
|| (ra.addr.msf.frame >= 75)) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
ra.addr.lba = ((ra.addr.msf.minute * 4500)
sony_toc.lead_out_start_lba)
|| (ra.addr.lba + ra.nframes >=
sony_toc.lead_out_start_lba)) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
/* I know, this can go negative on an unsigned. However,
so this should compensate and allow direct msf access. */
ra.addr.lba -= LOG_START_OFFSET;
} else {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
- return (read_audio(&ra));
+ retval = read_audio(&ra);
+ break;
}
- return 0;
+ retval = 0;
break;
default:
- return -EINVAL;
+ retval = -EINVAL;
}
+ up(&sony_sem);
+ return retval;
}
static int scd_spinup(void)
/* The drive sometimes returns error 0. I don't know why, but ignore
it. It seems to mean the drive has already done the operation. */
if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- printk("Sony CDROM %s error (scd_open, spin up)\n",
+ printk(KERN_ERR PFX "%s error (scd_open, spin up)\n",
translate_error(res_reg[1]));
return 1;
}
goto respinup_on_open;
}
- printk("Sony CDROM error %s (scd_open, read toc)\n",
+ printk(KERN_ERR PFX "Error %s (scd_open, read toc)\n",
translate_error(res_reg[1]));
do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
&res_size);
* Open the drive for operations. Spin the drive up and read the table of
* contents if these have not already been done.
*/
-static int scd_open(struct cdrom_device_info *cdi, int openmode)
+static int scd_open(struct cdrom_device_info *cdi, int purpose)
{
unsigned char res_reg[12];
unsigned int res_size;
unsigned char params[2];
+ if (purpose == 1) {
+ /* Open for IOCTLs only - no media check */
+ sony_usage++;
+ return 0;
+ }
+
if (sony_usage == 0) {
if (scd_spinup() != 0)
return -EIO;
params, 2, res_reg, &res_size);
if ((res_size < 2)
|| ((res_reg[0] & 0xf0) == 0x20)) {
- printk
- ("CDU31A: Unable to set XA params: 0x%2.2x\n",
- res_reg[1]);
+ printk(KERN_WARNING PFX "Unable to set "
+ "XA params: 0x%2.2x\n", res_reg[1]);
}
sony_xa_mode = 1;
}
params, 2, res_reg, &res_size);
if ((res_size < 2)
|| ((res_reg[0] & 0xf0) == 0x20)) {
- printk
- ("CDU31A: Unable to reset XA params: 0x%2.2x\n",
- res_reg[1]);
+ printk(KERN_WARNING PFX "Unable to reset "
+ "XA params: 0x%2.2x\n", res_reg[1]);
}
sony_xa_mode = 0;
}
.get_mcn = scd_get_mcn,
.reset = scd_reset,
.audio_ioctl = scd_audio_ioctl,
- .dev_ioctl = scd_dev_ioctl,
.capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK |
CDC_SELECT_SPEED | CDC_MULTI_SESSION |
- CDC_MULTI_SESSION | CDC_MCN |
- CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
- CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS,
+ CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
+ CDC_RESET | CDC_DRIVE_STATUS,
.n_minors = 1,
};
static int scd_block_ioctl(struct inode *inode, struct file *file,
unsigned cmd, unsigned long arg)
{
- return cdrom_ioctl(file, &scd_info, inode, cmd, arg);
+ int retval;
+
+ /* The eject and close commands should be handled by Uniform CD-ROM
+ * driver - but I always got hard lockup instead of eject
+ * until I put this here.
+ */
+ switch (cmd) {
+ case CDROMEJECT:
+ scd_lock_door(&scd_info, 0);
+ retval = scd_tray_move(&scd_info, 1);
+ break;
+ case CDROMCLOSETRAY:
+ retval = scd_tray_move(&scd_info, 0);
+ break;
+ case CDROMREADAUDIO:
+ retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg);
+ break;
+ default:
+ retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg);
+ }
+ return retval;
}
static int scd_block_media_changed(struct gendisk *disk)
return cdrom_media_changed(&scd_info);
}
-struct block_device_operations scd_bdops =
+static struct block_device_operations scd_bdops =
{
.owner = THIS_MODULE,
.open = scd_block_open,
#ifndef MODULE
/*
* Set up base I/O and interrupts, called from main.c.
-
*/
static int __init cdu31a_setup(char *strings)
if (strcmp(strings, "PAS") == 0) {
sony_pas_init = 1;
} else {
- printk("CDU31A: Unknown interface type: %s\n",
+ printk(KERN_NOTICE PFX "Unknown interface type: %s\n",
strings);
}
}
tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */
cdu31a_irq = 0;
+ sony_speed = is_double_speed; /* Set 2X drives to 2X by default */
set_drive_params(sony_speed);
cdu31a_irq = tmp_irq;
if (request_irq
(cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT,
"cdu31a", NULL)) {
- printk
- ("Unable to grab IRQ%d for the CDU31A driver\n",
- cdu31a_irq);
+ printk(KERN_WARNING PFX "Unable to grab IRQ%d for "
+ "the CDU31A driver\n", cdu31a_irq);
cdu31a_irq = 0;
}
}
strcat(msg, buf);
}
strcat(msg, "\n");
-
- is_a_cdu31a =
- strcmp("CD-ROM CDU31A", drive_config.product_id) == 0;
+ printk(KERN_INFO PFX "%s",msg);
cdu31a_queue = blk_init_queue(do_cdu31a_request, &cdu31a_lock);
if (!cdu31a_queue)
goto errout0;
+ blk_queue_hardsect_size(cdu31a_queue, 2048);
init_timer(&cdu31a_abort_timer);
cdu31a_abort_timer.function = handle_abort_timeout;
add_disk(disk);
disk_changed = 1;
- return (0);
+ return 0;
err:
blk_cleanup_queue(cdu31a_queue);
errout0:
if (cdu31a_irq)
free_irq(cdu31a_irq, NULL);
- printk("Unable to register CDU-31a with Uniform cdrom driver\n");
+ printk(KERN_ERR PFX "Unable to register with Uniform cdrom driver\n");
put_disk(disk);
errout1:
if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
- printk("Can't unregister block device for cdu31a\n");
+ printk(KERN_WARNING PFX "Can't unregister block device\n");
}
errout2:
release_region(cdu31a_port, 4);
}
-void __exit cdu31a_exit(void)
+static void __exit cdu31a_exit(void)
{
del_gendisk(scd_gendisk);
put_disk(scd_gendisk);
if (unregister_cdrom(&scd_info)) {
- printk
- ("Can't unregister cdu31a from Uniform cdrom driver\n");
+ printk(KERN_WARNING PFX "Can't unregister from Uniform "
+ "cdrom driver\n");
return;
}
if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) {
- printk("Can't unregister cdu31a\n");
+ printk(KERN_WARNING PFX "Can't unregister\n");
return;
}
free_irq(cdu31a_irq, NULL);
release_region(cdu31a_port, 4);
- printk(KERN_INFO "cdu31a module released.\n");
+ printk(KERN_INFO PFX "module released.\n");
}
#ifdef MODULE