fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / scsi / sr.c
index a4db57a..89e9b36 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
-#include "scsi.h"
-#include "hosts.h"
-
+#include <scsi/scsi.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
 #include <scsi/scsi_driver.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>   /* For the door lock/unlock commands */
 
 #include "scsi_logging.h"
 #include "sr.h"
 
 
-MODULE_PARM(xa_test, "i");     /* see sr_ioctl.c */
-
+MODULE_DESCRIPTION("SCSI cdrom (sr) driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR);
 
 #define SR_DISKS       256
 
@@ -66,7 +71,7 @@ MODULE_PARM(xa_test, "i");    /* see sr_ioctl.c */
 #define SR_CAPABILITIES \
        (CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|CDC_SELECT_SPEED| \
         CDC_SELECT_DISC|CDC_MULTI_SESSION|CDC_MCN|CDC_MEDIA_CHANGED| \
-        CDC_PLAY_AUDIO|CDC_RESET|CDC_IOCTLS|CDC_DRIVE_STATUS| \
+        CDC_PLAY_AUDIO|CDC_RESET|CDC_DRIVE_STATUS| \
         CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \
         CDC_MRW|CDC_MRW_W|CDC_RAM)
 
@@ -85,12 +90,12 @@ static struct scsi_driver sr_template = {
 };
 
 static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG];
-static spinlock_t sr_index_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(sr_index_lock);
 
 /* This semaphore is used to mediate the 0->1 reference get in the
  * face of object destruction (i.e. we can't allow a get on an
  * object after last put) */
-static DECLARE_MUTEX(sr_ref_sem);
+static DEFINE_MUTEX(sr_ref_mutex);
 
 static int sr_open(struct cdrom_device_info *, int);
 static void sr_release(struct cdrom_device_info *);
@@ -99,7 +104,7 @@ static void get_sectorsize(struct scsi_cd *);
 static void get_capabilities(struct scsi_cd *);
 
 static int sr_media_change(struct cdrom_device_info *, int);
-static int sr_packet(struct cdrom_device_info *, struct cdrom_generic_command *);
+static int sr_packet(struct cdrom_device_info *, struct packet_command *);
 
 static struct cdrom_device_ops sr_dops = {
        .open                   = sr_open,
@@ -113,7 +118,6 @@ static struct cdrom_device_ops sr_dops = {
        .get_mcn                = sr_get_mcn,
        .reset                  = sr_reset,
        .audio_ioctl            = sr_audio_ioctl,
-       .dev_ioctl              = sr_dev_ioctl,
        .capability             = SR_CAPABILITIES,
        .generic_packet         = sr_packet,
 };
@@ -133,22 +137,31 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
 {
        struct scsi_cd *cd = NULL;
 
-       down(&sr_ref_sem);
+       mutex_lock(&sr_ref_mutex);
        if (disk->private_data == NULL)
                goto out;
        cd = scsi_cd(disk);
-       if (!kref_get(&cd->kref))
-               cd = NULL;
+       kref_get(&cd->kref);
+       if (scsi_device_get(cd->device))
+               goto out_put;
+       goto out;
+
+ out_put:
+       kref_put(&cd->kref, sr_kref_release);
+       cd = NULL;
  out:
-       up(&sr_ref_sem);
+       mutex_unlock(&sr_ref_mutex);
        return cd;
 }
 
-static inline void scsi_cd_put(struct scsi_cd *cd)
+static void scsi_cd_put(struct scsi_cd *cd)
 {
-       down(&sr_ref_sem);
-       kref_put(&cd->kref);
-       up(&sr_ref_sem);
+       struct scsi_device *sdev = cd->device;
+
+       mutex_lock(&sr_ref_mutex);
+       kref_put(&cd->kref, sr_kref_release);
+       scsi_device_put(sdev);
+       mutex_unlock(&sr_ref_mutex);
 }
 
 /*
@@ -171,7 +184,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
                return -EINVAL;
        }
 
-       retval = scsi_ioctl(cd->device, SCSI_IOCTL_TEST_UNIT_READY, 0);
+       retval = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES);
        if (retval) {
                /* Unable to test, unit probably not ready.  This usually
                 * means there is no disc in the drive.  Mark as changed,
@@ -190,15 +203,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
                /* check multisession offset etc */
                sr_cd_check(cdi);
 
-               /* 
-                * If the disk changed, the capacity will now be different,
-                * so we force a re-read of this information 
-                * Force 2048 for the sector size so that filesystems won't
-                * be trying to use something that is too small if the disc
-                * has changed.
-                */
-               cd->needs_sector_size = 1;
-               cd->device->sector_size = 2048;
+               get_sectorsize(cd);
        }
        return retval;
 }
@@ -212,7 +217,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
 static void rw_intr(struct scsi_cmnd * SCpnt)
 {
        int result = SCpnt->result;
-       int this_count = SCpnt->bufflen;
+       int this_count = SCpnt->request_bufflen;
        int good_bytes = (result == 0 ? this_count : 0);
        int block_sectors = 0;
        long error_sector;
@@ -236,8 +241,6 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
                case ILLEGAL_REQUEST:
                        if (!(SCpnt->sense_buffer[0] & 0x90))
                                break;
-                       if (!blk_fs_request(SCpnt->request))
-                               break;
                        error_sector = (SCpnt->sense_buffer[3] << 24) |
                                (SCpnt->sense_buffer[4] << 16) |
                                (SCpnt->sense_buffer[5] << 8) |
@@ -273,7 +276,7 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
                         * user, but make sure that it's not treated as a
                         * hard error.
                         */
-                       print_sense("sr", SCpnt);
+                       scsi_print_sense("sr", SCpnt);
                        SCpnt->result = 0;
                        SCpnt->sense_buffer[0] = 0x0;
                        good_bytes = this_count;
@@ -289,7 +292,7 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
         * how many actual sectors finished, and how many sectors we need
         * to say have failed.
         */
-       scsi_io_completion(SCpnt, good_bytes, block_sectors << 9);
+       scsi_io_completion(SCpnt, good_bytes);
 }
 
 static int sr_init_command(struct scsi_cmnd * SCpnt)
@@ -315,36 +318,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
                return 0;
        }
 
-       /*
-        * these are already setup, just copy cdb basically
-        */
-       if (SCpnt->request->flags & REQ_BLOCK_PC) {
-               struct request *rq = SCpnt->request;
-
-               if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd))
-                       return 0;
-
-               memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
-               if (!rq->data_len)
-                       SCpnt->sc_data_direction = SCSI_DATA_NONE;
-               else if (rq_data_dir(rq) == WRITE)
-                       SCpnt->sc_data_direction = SCSI_DATA_WRITE;
-               else
-                       SCpnt->sc_data_direction = SCSI_DATA_READ;
-
-               this_count = rq->data_len;
-               if (rq->timeout)
-                       timeout = rq->timeout;
-
-               SCpnt->transfersize = rq->data_len;
-               goto queue;
-       }
-
-       if (!(SCpnt->request->flags & REQ_CMD)) {
-               blk_dump_rq_flags(SCpnt->request, "sr unsup command");
-               return 0;
-       }
-
        /*
         * we do lazy blocksize switching (when reading XA sectors,
         * see CDROMREADMODE2 ioctl) 
@@ -358,7 +331,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
        }
 
        if (s_size != 512 && s_size != 1024 && s_size != 2048) {
-               printk("sr: bad sector size %d\n", s_size);
+               scmd_printk(KERN_ERR, SCpnt, "bad sector size %d\n", s_size);
                return 0;
        }
 
@@ -366,10 +339,11 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
                if (!cd->device->writeable)
                        return 0;
                SCpnt->cmnd[0] = WRITE_10;
-               SCpnt->sc_data_direction = SCSI_DATA_WRITE;
+               SCpnt->sc_data_direction = DMA_TO_DEVICE;
+               cd->cdi.media_written = 1;
        } else if (rq_data_dir(SCpnt->request) == READ) {
                SCpnt->cmnd[0] = READ_10;
-               SCpnt->sc_data_direction = SCSI_DATA_READ;
+               SCpnt->sc_data_direction = DMA_FROM_DEVICE;
        } else {
                blk_dump_rq_flags(SCpnt->request, "Unknown sr command");
                return 0;
@@ -382,10 +356,11 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
                        size += sg[i].length;
 
                if (size != SCpnt->request_bufflen && SCpnt->use_sg) {
-                       printk(KERN_ERR "sr: mismatch count %d, bytes %d\n",
-                                       size, SCpnt->request_bufflen);
+                       scmd_printk(KERN_ERR, SCpnt,
+                               "mismatch count %d, bytes %d\n",
+                               size, SCpnt->request_bufflen);
                        if (SCpnt->request_bufflen > size)
-                               SCpnt->request_bufflen = SCpnt->bufflen = size;
+                               SCpnt->request_bufflen = size;
                }
        }
 
@@ -394,7 +369,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
         */
        if (((unsigned int)SCpnt->request->sector % (s_size >> 9)) ||
            (SCpnt->request_bufflen % s_size)) {
-               printk("sr: unaligned transfer\n");
+               scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n");
                return 0;
        }
 
@@ -412,8 +387,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
 
        if (this_count > 0xffff) {
                this_count = 0xffff;
-               SCpnt->request_bufflen = SCpnt->bufflen =
-                               this_count * s_size;
+               SCpnt->request_bufflen = this_count * s_size;
        }
 
        SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
@@ -431,8 +405,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
         */
        SCpnt->transfersize = cd->device->sector_size;
        SCpnt->underflow = this_count << 9;
-
-queue:
        SCpnt->allowed = MAX_RETRIES;
        SCpnt->timeout_per_command = timeout;
 
@@ -452,7 +424,7 @@ queue:
 static int sr_block_open(struct inode *inode, struct file *file)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
-       struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk);
+       struct scsi_cd *cd;
        int ret = 0;
 
        if(!(cd = scsi_cd_get(disk)))
@@ -482,17 +454,33 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
 {
        struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk);
        struct scsi_device *sdev = cd->device;
+       void __user *argp = (void __user *)arg;
+       int ret;
 
-        /*
-         * Send SCSI addressing ioctls directly to mid level, send other
-         * ioctls to cdrom/block level.
-         */
-        switch (cmd) {
-                case SCSI_IOCTL_GET_IDLUN:
-                case SCSI_IOCTL_GET_BUS_NUMBER:
-                        return scsi_ioctl(sdev, cmd, (void *)arg);
+       /*
+        * Send SCSI addressing ioctls directly to mid level, send other
+        * ioctls to cdrom/block level.
+        */
+       switch (cmd) {
+       case SCSI_IOCTL_GET_IDLUN:
+       case SCSI_IOCTL_GET_BUS_NUMBER:
+               return scsi_ioctl(sdev, cmd, argp);
        }
-       return cdrom_ioctl(&cd->cdi, inode, cmd, arg);
+
+       ret = cdrom_ioctl(file, &cd->cdi, inode, cmd, arg);
+       if (ret != -ENOSYS)
+               return ret;
+
+       /*
+        * ENODEV means that we didn't recognise the ioctl, or that we
+        * cannot execute it in the current device state.  In either
+        * case fall through to scsi_ioctl, which will return ENDOEV again
+        * if it doesn't recognise the ioctl
+        */
+       ret = scsi_nonblockable_ioctl(sdev, cmd, argp, NULL);
+       if (ret != -ENODEV)
+               return ret;
+       return scsi_ioctl(sdev, cmd, argp);
 }
 
 static int sr_block_media_changed(struct gendisk *disk)
@@ -501,13 +489,17 @@ static int sr_block_media_changed(struct gendisk *disk)
        return cdrom_media_changed(&cd->cdi);
 }
 
-struct block_device_operations sr_bdops =
+static struct block_device_operations sr_bdops =
 {
        .owner          = THIS_MODULE,
        .open           = sr_block_open,
        .release        = sr_block_release,
        .ioctl          = sr_block_ioctl,
        .media_changed  = sr_block_media_changed,
+       /* 
+        * No compat_ioctl for now because sr_block_ioctl never
+        * seems to pass arbitary ioctls down to host drivers.
+        */
 };
 
 static int sr_open(struct cdrom_device_info *cdi, int purpose)
@@ -524,17 +516,9 @@ static int sr_open(struct cdrom_device_info *cdi, int purpose)
        if (!scsi_block_when_processing_errors(sdev))
                goto error_out;
 
-       /*
-        * If this device did not have media in the drive at boot time, then
-        * we would have been unable to get the sector size.  Check to see if
-        * this is the case, and try again.
-        */
-       if (cd->needs_sector_size)
-               get_sectorsize(cd);
        return 0;
 
 error_out:
-       scsi_cd_put(cd);
        return retval;  
 }
 
@@ -558,16 +542,12 @@ static int sr_probe(struct device *dev)
        if (sdev->type != TYPE_ROM && sdev->type != TYPE_WORM)
                goto fail;
 
-       if ((error = scsi_device_get(sdev)) != 0)
-               goto fail;
-
        error = -ENOMEM;
-       cd = kmalloc(sizeof(*cd), GFP_KERNEL);
+       cd = kzalloc(sizeof(*cd), GFP_KERNEL);
        if (!cd)
-               goto fail_put_sdev;
-       memset(cd, 0, sizeof(*cd));
+               goto fail;
 
-       kref_init(&cd->kref, sr_kref_release);
+       kref_init(&cd->kref);
 
        disk = alloc_disk(1);
        if (!disk)
@@ -594,7 +574,6 @@ static int sr_probe(struct device *dev)
        cd->driver = &sr_template;
        cd->disk = disk;
        cd->capacity = 0x1fffff;
-       cd->needs_sector_size = 1;
        cd->device->changed = 1;        /* force recheck CD type */
        cd->use = 1;
        cd->readcd_known = 0;
@@ -612,8 +591,6 @@ static int sr_probe(struct device *dev)
        get_capabilities(cd);
        sr_vendor_init(cd);
 
-       snprintf(disk->devfs_name, sizeof(disk->devfs_name),
-                       "%s/cd", sdev->devfs_name);
        disk->driverfs_dev = &sdev->sdev_gendev;
        set_capacity(disk, cd->capacity);
        disk->private_data = &cd->driver;
@@ -627,18 +604,14 @@ static int sr_probe(struct device *dev)
        disk->flags |= GENHD_FL_REMOVABLE;
        add_disk(disk);
 
-       printk(KERN_DEBUG
-           "Attached scsi CD-ROM %s at scsi%d, channel %d, id %d, lun %d\n",
-           cd->cdi.name, sdev->host->host_no, sdev->channel,
-           sdev->id, sdev->lun);
+       sdev_printk(KERN_DEBUG, sdev,
+                   "Attached scsi CD-ROM %s\n", cd->cdi.name);
        return 0;
 
 fail_put:
        put_disk(disk);
 fail_free:
        kfree(cd);
-fail_put_sdev:
-       scsi_device_put(sdev);
 fail:
        return error;
 }
@@ -650,43 +623,30 @@ static void get_sectorsize(struct scsi_cd *cd)
        unsigned char *buffer;
        int the_result, retries = 3;
        int sector_size;
-       struct scsi_request *SRpnt = NULL;
        request_queue_t *queue;
 
        buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
        if (!buffer)
                goto Enomem;
-       SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL);
-       if (!SRpnt)
-               goto Enomem;
 
        do {
                cmd[0] = READ_CAPACITY;
                memset((void *) &cmd[1], 0, 9);
-               /* Mark as really busy */
-               SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
-               SRpnt->sr_cmd_len = 0;
-
                memset(buffer, 0, 8);
 
                /* Do the command and wait.. */
-               SRpnt->sr_data_direction = SCSI_DATA_READ;
-               scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
-                             8, SR_TIMEOUT, MAX_RETRIES);
+               the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE,
+                                             buffer, 8, NULL, SR_TIMEOUT,
+                                             MAX_RETRIES);
 
-               the_result = SRpnt->sr_result;
                retries--;
 
        } while (the_result && retries);
 
 
-       scsi_release_request(SRpnt);
-       SRpnt = NULL;
-
        if (the_result) {
                cd->capacity = 0x1fffff;
                sector_size = 2048;     /* A guess, just in case */
-               cd->needs_sector_size = 1;
        } else {
 #if 0
                if (cdrom_get_last_written(&cd->cdi,
@@ -719,7 +679,6 @@ static void get_sectorsize(struct scsi_cd *cd)
                        printk("%s: unsupported sector size %d.\n",
                               cd->cdi.name, sector_size);
                        cd->capacity = 0;
-                       cd->needs_sector_size = 1;
                }
 
                cd->device->sector_size = sector_size;
@@ -728,7 +687,6 @@ static void get_sectorsize(struct scsi_cd *cd)
                 * Add this so that we have the ability to correctly gauge
                 * what the device is capable of.
                 */
-               cd->needs_sector_size = 0;
                set_capacity(cd->disk, cd->capacity);
        }
 
@@ -740,24 +698,20 @@ out:
 
 Enomem:
        cd->capacity = 0x1fffff;
-       sector_size = 2048;     /* A guess, just in case */
-       cd->needs_sector_size = 1;
-       if (SRpnt)
-               scsi_release_request(SRpnt);
+       cd->device->sector_size = 2048; /* A guess, just in case */
        goto out;
 }
 
 static void get_capabilities(struct scsi_cd *cd)
 {
        unsigned char *buffer;
-       int rc, n, mrw_write = 0, mrw = 1,ram_write=0;
        struct scsi_mode_data data;
-       struct scsi_request *SRpnt;
        unsigned char cmd[MAX_COMMAND_SIZE];
+       struct scsi_sense_hdr sshdr;
        unsigned int the_result;
-       int retries;
+       int retries, rc, n;
 
-       static char *loadmech[] =
+       static const char *loadmech[] =
        {
                "caddy",
                "tray",
@@ -769,22 +723,11 @@ static void get_capabilities(struct scsi_cd *cd)
                ""
        };
 
-       /* Set read only initially */
-       set_disk_ro(cd->disk, 1);
-
-       /* allocate a request for the TEST_UNIT_READY */
-       SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL);
-       if (!SRpnt) {
-               printk(KERN_WARNING "(get_capabilities:) Request allocation "
-                      "failure.\n");
-               return;
-       }
 
        /* allocate transfer buffer */
        buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
        if (!buffer) {
                printk(KERN_ERR "sr: out of memory.\n");
-               scsi_release_request(SRpnt);
                return;
        }
 
@@ -796,50 +739,32 @@ static void get_capabilities(struct scsi_cd *cd)
                memset((void *)cmd, 0, MAX_COMMAND_SIZE);
                cmd[0] = TEST_UNIT_READY;
 
-               SRpnt->sr_cmd_len = 0;
-               SRpnt->sr_sense_buffer[0] = 0;
-               SRpnt->sr_sense_buffer[2] = 0;
-               SRpnt->sr_data_direction = DMA_NONE;
-
-               scsi_wait_req (SRpnt, (void *) cmd, buffer,
-                              0, SR_TIMEOUT, MAX_RETRIES);
+               the_result = scsi_execute_req (cd->device, cmd, DMA_NONE, NULL,
+                                              0, &sshdr, SR_TIMEOUT,
+                                              MAX_RETRIES);
 
-               the_result = SRpnt->sr_result;
                retries++;
        } while (retries < 5 && 
                 (!scsi_status_is_good(the_result) ||
-                 ((driver_byte(the_result) & DRIVER_SENSE) &&
-                  SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION)));
+                 (scsi_sense_valid(&sshdr) &&
+                  sshdr.sense_key == UNIT_ATTENTION)));
 
        /* ask for mode page 0x2a */
        rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128,
-                            SR_TIMEOUT, 3, &data);
+                            SR_TIMEOUT, 3, &data, NULL);
 
        if (!scsi_status_is_good(rc)) {
                /* failed, drive doesn't have capabilities mode page */
                cd->cdi.speed = 1;
                cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
-                                        CDC_DVD | CDC_DVD_RAM |
-                                        CDC_SELECT_DISC | CDC_SELECT_SPEED);
-               scsi_release_request(SRpnt);
+                                CDC_DVD | CDC_DVD_RAM |
+                                CDC_SELECT_DISC | CDC_SELECT_SPEED |
+                                CDC_MRW | CDC_MRW_W | CDC_RAM);
                kfree(buffer);
                printk("%s: scsi-1 drive\n", cd->cdi.name);
                return;
        }
 
-       if (cdrom_is_mrw(&cd->cdi, &mrw_write)) {
-               mrw = 0;
-               cd->cdi.mask |= CDC_MRW;
-               cd->cdi.mask |= CDC_MRW_W;
-       }
-       if (!mrw_write)
-               cd->cdi.mask |= CDC_MRW_W;
-
-       if (cdrom_is_random_writable(&cd->cdi, &ram_write))
-               cd->cdi.mask |= CDC_RAM;
-       if (!ram_write)
-               cd->cdi.mask |= CDC_RAM;
-
        n = data.header_length + data.block_descriptor_length;
        cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;
        cd->readcd_known = 1;
@@ -887,15 +812,13 @@ static void get_capabilities(struct scsi_cd *cd)
                cd->cdi.mask |= CDC_CLOSE_TRAY; */
 
        /*
-        * if DVD-RAM of MRW-W, we are randomly writeable
+        * if DVD-RAM, MRW-W or CD-RW, we are randomly writable
         */
-       if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM)) !=
-                       (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM)) {
+       if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) !=
+                       (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) {
                cd->device->writeable = 1;
-               set_disk_ro(cd->disk, 0);
        }
 
-       scsi_release_request(SRpnt);
        kfree(buffer);
 }
 
@@ -904,7 +827,7 @@ static void get_capabilities(struct scsi_cd *cd)
  * by the Uniform CD-ROM layer. 
  */
 static int sr_packet(struct cdrom_device_info *cdi,
-               struct cdrom_generic_command *cgc)
+               struct packet_command *cgc)
 {
        if (cgc->timeout <= 0)
                cgc->timeout = IOCTL_TIMEOUT;
@@ -918,7 +841,7 @@ static int sr_packet(struct cdrom_device_info *cdi,
  *     sr_kref_release - Called to free the scsi_cd structure
  *     @kref: pointer to embedded kref
  *
- *     sr_ref_sem must be held entering this routine.  Because it is
+ *     sr_ref_mutex must be held entering this routine.  Because it is
  *     called on last put, you should always use the scsi_cd_get()
  *     scsi_cd_put() helpers which manipulate the semaphore directly
  *     and never do a direct kref_put().
@@ -926,7 +849,6 @@ static int sr_packet(struct cdrom_device_info *cdi,
 static void sr_kref_release(struct kref *kref)
 {
        struct scsi_cd *cd = container_of(kref, struct scsi_cd, kref);
-       struct scsi_device *sdev = cd->device;
        struct gendisk *disk = cd->disk;
 
        spin_lock(&sr_index_lock);
@@ -940,8 +862,6 @@ static void sr_kref_release(struct kref *kref)
        put_disk(disk);
 
        kfree(cd);
-
-       scsi_device_put(sdev);
 }
 
 static int sr_remove(struct device *dev)
@@ -950,7 +870,9 @@ static int sr_remove(struct device *dev)
 
        del_gendisk(cd->disk);
 
-       scsi_cd_put(cd);
+       mutex_lock(&sr_ref_mutex);
+       kref_put(&cd->kref, sr_kref_release);
+       mutex_unlock(&sr_ref_mutex);
 
        return 0;
 }