fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / cdrom / cdu31a.c
index 3a758a0..2157c58 100644 (file)
  * 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/hdreg.h>
 #include <linux/genhd.h>
 #include <linux/ioport.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/string.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.
@@ -222,7 +216,7 @@ static unsigned int sony_blocks_left = 0;   /* Number of 512 byte blocks left
 /* 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
@@ -238,7 +232,7 @@ static volatile unsigned short sony_cd_read_reg;
 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? */
 
@@ -269,17 +263,9 @@ static int sony_toc_read = 0;      /* Has the TOC been read for
 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 */
 
@@ -301,11 +287,12 @@ static unsigned volatile char final_pos_msf[3] = { 0, 0, 0 };
 
 /* 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 */
 
@@ -314,12 +301,8 @@ 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
@@ -351,13 +334,16 @@ static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
  */
 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;
 }
 
@@ -383,17 +369,31 @@ static inline void disable_interrupts(void)
  */
 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;
        }
 }
 
@@ -404,43 +404,42 @@ static inline void sony_sleep(void)
  */
 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);
 }
@@ -453,6 +452,8 @@ static int scd_reset(struct cdrom_device_info *cdi)
 {
        unsigned long retry_count;
 
+       if (down_interruptible(&sony_sem))
+               return -ERESTARTSYS;
        reset_drive();
 
        retry_count = jiffies + SONY_RESET_TIMEOUT;
@@ -460,6 +461,7 @@ static int scd_reset(struct cdrom_device_info *cdi)
                sony_sleep();
        }
 
+       up(&sony_sem);
        return 0;
 }
 
@@ -486,17 +488,17 @@ static inline void clear_param_reg(void)
 
 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)
@@ -511,7 +513,7 @@ static inline void write_cmd(unsigned char cmd)
        outb(cmd, sony_cd_cmd_reg);
 }
 
-static irqreturn_t cdu31a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t cdu31a_interrupt(int irq, void *dev_id)
 {
        unsigned char val;
 
@@ -535,15 +537,17 @@ static irqreturn_t cdu31a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                /* 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;
 }
@@ -556,82 +560,47 @@ static unsigned char *translate_error(unsigned char err_code)
        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;
@@ -653,8 +622,8 @@ static void set_drive_params(int want_doublespeed)
        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;
@@ -670,8 +639,8 @@ static void set_drive_params(int want_doublespeed)
        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]);
        }
 }
 
@@ -686,7 +655,10 @@ static int scd_select_speed(struct cdrom_device_info *cdi, int speed)
        else
                sony_speed = speed - 1;
 
+       if (down_interruptible(&sony_sem))
+               return -ERESTARTSYS;
        set_drive_params(sony_speed);
+       up(&sony_sem);
        return 0;
 }
 
@@ -696,13 +668,15 @@ static int scd_select_speed(struct cdrom_device_info *cdi, int speed)
  */
 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;
 }
 
@@ -716,7 +690,7 @@ static void restart_on_error(void)
        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())) {
@@ -725,12 +699,11 @@ static void restart_on_error(void)
        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();
 }
@@ -786,9 +759,7 @@ get_result(unsigned char *result_buffer, unsigned int *result_size)
                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;
@@ -839,10 +810,8 @@ get_result(unsigned char *result_buffer, unsigned int *result_size)
                                        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;
@@ -868,10 +837,8 @@ get_result(unsigned char *result_buffer, unsigned int *result_size)
                                        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;
@@ -902,38 +869,12 @@ do_sony_cd_cmd(unsigned char cmd,
               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();
@@ -941,9 +882,7 @@ retry_cd_operation:
                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;
@@ -960,18 +899,9 @@ retry_cd_operation:
        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);
 }
 
 
@@ -991,21 +921,18 @@ static int handle_sony_cd_attention(void)
        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();
@@ -1045,11 +972,8 @@ static int handle_sony_cd_attention(void)
                }
 
                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();
@@ -1061,18 +985,15 @@ static int handle_sony_cd_attention(void)
                        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;
 }
 
 
@@ -1084,14 +1005,14 @@ static inline unsigned int int_to_bcd(unsigned int val)
 
        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);
 }
 
 
@@ -1145,33 +1066,15 @@ static void size_to_buf(unsigned int size, unsigned char *buf)
    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, &params[3]);
+       size_to_buf(nsect, &params[3]);
 
        /*
         * Clear any outstanding attentions and wait for the drive to
@@ -1187,11 +1090,10 @@ start_request(unsigned int sector, unsigned int nsect, int read_nsect_only)
        }
 
        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();
@@ -1200,22 +1102,15 @@ start_request(unsigned int sector, unsigned int nsect, int read_nsect_only)
                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];
@@ -1225,7 +1120,7 @@ static void abort_read(void)
 
        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]));
        }
 
@@ -1240,23 +1135,15 @@ static void abort_read(void)
        }
 
        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
@@ -1266,71 +1153,33 @@ static void handle_abort_timeout(unsigned long data)
                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. */
@@ -1341,79 +1190,12 @@ read_data_block(char *buffer,
                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;
@@ -1426,25 +1208,24 @@ read_data_block(char *buffer,
                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;
@@ -1456,9 +1237,7 @@ read_data_block(char *buffer,
                }
 
                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;
@@ -1475,29 +1254,13 @@ read_data_block(char *buffer,
                                        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. */
@@ -1507,9 +1270,8 @@ read_data_block(char *buffer,
                        } 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;
@@ -1517,9 +1279,7 @@ read_data_block(char *buffer,
                        }
                }
        }
-#if DEBUG
-       printk("Leaving read_data_block at %d\n", __LINE__);
-#endif
+       pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
 }
 
 
@@ -1533,37 +1293,17 @@ read_data_block(char *buffer,
 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;
-
 
-#if DEBUG
-       printk("Entering do_cdu31a_request\n");
-#endif
+       pr_debug(PFX "Entering %s\n", __FUNCTION__);
 
-       /* 
-        * 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());
@@ -1571,10 +1311,6 @@ static void do_cdu31a_request(request_queue_t * q)
        /* 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);
@@ -1593,44 +1329,43 @@ static void do_cdu31a_request(request_queue_t * q)
 
                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;
                }
 
                /* WTF??? */
-               if (!(req->flags & REQ_CMD))
+               if (!blk_fs_request(req)) {
+                       end_request(req, 0);
                        continue;
+               }
                if (rq_data_dir(req) == WRITE) {
                        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;
                }
@@ -1638,7 +1373,7 @@ static void do_cdu31a_request(request_queue_t * q)
                /* 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;
                        }
@@ -1647,18 +1382,16 @@ static void do_cdu31a_request(request_queue_t * q)
                   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;
                        }
@@ -1667,7 +1400,12 @@ static void do_cdu31a_request(request_queue_t * q)
                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;
                }
 
@@ -1681,13 +1419,12 @@ static void do_cdu31a_request(request_queue_t * q)
                        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();
@@ -1698,13 +1435,9 @@ static void do_cdu31a_request(request_queue_t * q)
        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__);
 }
 
 
@@ -1723,9 +1456,7 @@ static void sony_get_toc(void)
        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) {
@@ -1776,16 +1507,12 @@ static void sony_get_toc(void)
 /* 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)) {
@@ -1795,9 +1522,7 @@ static void sony_get_toc(void)
                                            ("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,
@@ -1808,8 +1533,8 @@ static void sony_get_toc(void)
                        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]));
@@ -1817,29 +1542,27 @@ static void sony_get_toc(void)
                                   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,
@@ -1864,8 +1587,7 @@ static void sony_get_toc(void)
                                                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,
@@ -1877,8 +1599,7 @@ static void sony_get_toc(void)
                                     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,
@@ -1890,8 +1611,7 @@ static void sony_get_toc(void)
                                     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,
@@ -1903,8 +1623,7 @@ static void sony_get_toc(void)
                                     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,
@@ -1916,8 +1635,7 @@ static void sony_get_toc(void)
                                     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,
@@ -1928,7 +1646,6 @@ static void sony_get_toc(void)
                                     single_toc.dummyc0[4],
                                     single_toc.dummyc0[5],
                                     single_toc.dummyc0[6]);
-#endif
 #undef DEBUG
 #define DEBUG 0
 
@@ -1997,8 +1714,8 @@ static void sony_get_toc(void)
                                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);
                        {
@@ -2010,8 +1727,7 @@ static void sony_get_toc(void)
                                     -
                                     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,
@@ -2044,8 +1760,8 @@ static void sony_get_toc(void)
                                                               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
@@ -2150,8 +1866,8 @@ static void sony_get_toc(void)
 
                        /* 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++;
@@ -2169,17 +1885,13 @@ static void sony_get_toc(void)
                    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__);
 }
 
 
@@ -2193,8 +1905,12 @@ static int scd_get_last_session(struct cdrom_device_info *cdi,
        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;
@@ -2234,7 +1950,7 @@ static int read_subcode(void)
                       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;
        }
@@ -2272,8 +1988,11 @@ scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
        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 */
@@ -2402,8 +2121,8 @@ read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
                        }
                        /* 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;
@@ -2411,9 +2130,7 @@ read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
                        }
                        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;
@@ -2443,10 +2160,7 @@ read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
                        }
 
                        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;
@@ -2464,7 +2178,7 @@ read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
                            || (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;
@@ -2473,7 +2187,7 @@ read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
                } 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;
@@ -2492,28 +2206,11 @@ static int read_audio(struct cdrom_read_audio *ra)
        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;
@@ -2521,9 +2218,10 @@ static int read_audio(struct cdrom_read_audio *ra)
        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
@@ -2531,8 +2229,7 @@ static int read_audio(struct cdrom_read_audio *ra)
           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;
        }
@@ -2540,11 +2237,11 @@ static int read_audio(struct cdrom_read_audio *ra)
        /* 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. */
@@ -2559,8 +2256,8 @@ static int read_audio(struct cdrom_read_audio *ra)
                                               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;
@@ -2569,7 +2266,7 @@ static int read_audio(struct cdrom_read_audio *ra)
                                /* 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;
                                }
@@ -2577,18 +2274,17 @@ static int read_audio(struct cdrom_read_audio *ra)
                                /* 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]));
@@ -2598,21 +2294,21 @@ static int read_audio(struct cdrom_read_audio *ra)
                                } 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;
@@ -2623,7 +2319,7 @@ static int read_audio(struct cdrom_read_audio *ra)
 
        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;
@@ -2641,16 +2337,15 @@ static int read_audio(struct cdrom_read_audio *ra)
        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
@@ -2663,7 +2358,7 @@ do_sony_cd_cmd_chk(const char *name,
        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;
        }
@@ -2676,6 +2371,10 @@ do_sony_cd_cmd_chk(const char *name,
  */
 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;
@@ -2686,13 +2385,15 @@ static int scd_tray_move(struct cdrom_device_info *cdi, int position)
                               &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;
 }
 
 /*
@@ -2704,12 +2405,13 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
        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;
 
@@ -2722,28 +2424,33 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
                 * 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,
@@ -2759,10 +2466,13 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
                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,
@@ -2776,15 +2486,18 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
                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 */
                {
@@ -2792,14 +2505,16 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
 
                        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 */
                {
@@ -2809,14 +2524,16 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
 
                        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 =
@@ -2837,7 +2554,7 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
                                    *(msf_val + 2);
                        }
                }
-               return 0;
+               retval = 0;
                break;
 
        case CDROMPLAYTRKIND:   /* Play a track.  This currently ignores index. */
@@ -2847,18 +2564,21 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
 
                        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].
@@ -2880,7 +2600,8 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
                                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].
@@ -2901,14 +2622,16 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
 
                        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 */
@@ -2916,7 +2639,8 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
                        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? */
@@ -2927,25 +2651,32 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
                        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. */
@@ -2955,33 +2686,38 @@ static int scd_dev_ioctl(struct cdrom_device_info *cdi,
 
                        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)
@@ -2991,7 +2727,8 @@ static int scd_dev_ioctl(struct cdrom_device_info *cdi,
                                     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,
@@ -2999,17 +2736,21 @@ static int scd_dev_ioctl(struct cdrom_device_info *cdi,
                                   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)
@@ -3026,7 +2767,7 @@ 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;
        }
@@ -3050,7 +2791,7 @@ static int scd_spinup(void)
                        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);
@@ -3063,12 +2804,18 @@ static int scd_spinup(void)
  * 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;
@@ -3090,9 +2837,8 @@ static int scd_open(struct cdrom_device_info *cdi, int openmode)
                                       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;
                }
@@ -3104,9 +2850,8 @@ static int scd_open(struct cdrom_device_info *cdi, int openmode)
                                       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;
                }
@@ -3150,12 +2895,10 @@ static struct cdrom_device_ops scd_dops = {
        .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,
 };
 
@@ -3179,7 +2922,27 @@ static int scd_block_release(struct inode *inode, struct file *file)
 static int scd_block_ioctl(struct inode *inode, struct file *file,
                                unsigned cmd, unsigned long arg)
 {
-       return cdrom_ioctl(&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)
@@ -3187,7 +2950,7 @@ 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,
@@ -3272,7 +3035,6 @@ out_err:
 #ifndef MODULE
 /*
  * Set up base I/O and interrupts, called from main.c.
  */
 
 static int __init cdu31a_setup(char *strings)
@@ -3291,7 +3053,7 @@ 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);
                }
        }
@@ -3374,17 +3136,17 @@ int __init cdu31a_init(void)
        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 (cdu31a_irq > 0) {
                if (request_irq
-                   (cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT,
+                   (cdu31a_irq, cdu31a_interrupt, IRQF_DISABLED,
                     "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;
                }
        }
@@ -3419,13 +3181,12 @@ int __init cdu31a_init(void)
                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;
@@ -3438,18 +3199,18 @@ int __init cdu31a_init(void)
        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);
@@ -3458,17 +3219,17 @@ errout3:
 }
 
 
-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;
        }
 
@@ -3478,7 +3239,7 @@ void __exit cdu31a_exit(void)
                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