vserver 1.9.3
[linux-2.6.git] / drivers / ide / ide-cd.c
index 95a44a9..cc6b66e 100644 (file)
@@ -535,9 +535,7 @@ static void cdrom_prepare_request(struct request *rq)
        rq->flags = REQ_PC;
 }
 
-static void cdrom_queue_request_sense(ide_drive_t *drive, 
-                                     struct completion *wait,
-                                     void *sense,
+static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
                                      struct request *failed_command)
 {
        struct cdrom_info *info         = drive->driver_data;
@@ -554,7 +552,6 @@ static void cdrom_queue_request_sense(ide_drive_t *drive,
        rq->cmd[4] = rq->data_len = 18;
 
        rq->flags = REQ_SENSE;
-       rq->waiting = wait;
 
        /* NOTE! Save the failed command in "rq->buffer" */
        rq->buffer = (void *) failed_command;
@@ -574,7 +571,7 @@ ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat)
        if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
                return ide_stopped;
        /* retry only "normal" I/O: */
-       if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+       if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
                rq->errors = 1;
                ide_end_drive_cmd(drive, stat, err);
                return ide_stopped;
@@ -608,7 +605,7 @@ ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg)
        if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
                return ide_stopped;
        /* retry only "normal" I/O: */
-       if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+       if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
                rq->errors = 1;
                ide_end_drive_cmd(drive, BUSY_STAT, 0);
                return ide_stopped;
@@ -631,10 +628,21 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
                struct request *failed = (struct request *) rq->buffer;
                struct cdrom_info *info = drive->driver_data;
                void *sense = &info->sense_data;
-               
-               if (failed && failed->sense) {
-                       sense = failed->sense;
-                       failed->sense_len = rq->sense_len;
+               unsigned long flags;
+
+               if (failed) {
+                       if (failed->sense) {
+                               sense = failed->sense;
+                               failed->sense_len = rq->sense_len;
+                       }
+
+                       /*
+                        * now end failed request
+                        */
+                       spin_lock_irqsave(&ide_lock, flags);
+                       end_that_request_chunk(failed, 0, failed->data_len);
+                       end_that_request_last(failed);
+                       spin_unlock_irqrestore(&ide_lock, flags);
                }
 
                cdrom_analyze_sense_data(drive, failed, sense);
@@ -642,6 +650,9 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
 
        if (!rq->current_nr_sectors && blk_fs_request(rq))
                uptodate = 1;
+       /* make sure it's fully ended */
+       if (blk_pc_request(rq))
+               nsectors = (rq->data_len + 511) >> 9;
        if (!nsectors)
                nsectors = 1;
 
@@ -684,7 +695,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
 
        } else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) {
                /* All other functions, except for READ. */
-               struct completion *wait = NULL;
+               unsigned long flags;
 
                /*
                 * if we have an error, pass back CHECK_CONDITION as the
@@ -706,30 +717,23 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                        ide_dump_status(drive, "packet command error", stat);
                }
                
-               /* Set the error flag and complete the request.
-                  Then, if we have a CHECK CONDITION status,
-                  queue a request sense command.  We must be careful,
-                  though: we don't want the thread in
-                  cdrom_queue_packet_command to wake up until
-                  the request sense has completed.  We do this
-                  by transferring the semaphore from the packet
-                  command request to the request sense request. */
-
                rq->flags |= REQ_FAILED;
-               if ((stat & ERR_STAT) != 0) {
-                       wait = rq->waiting;
-                       rq->waiting = NULL;
-                       if ((rq->flags & REQ_BLOCK_PC) != 0) {
-                               cdrom_queue_request_sense(drive, wait,
-                                                         rq->sense, rq);
-                               return 1; /* REQ_BLOCK_PC self-cares */
-                       }
-               }
 
-               cdrom_end_request(drive, 0);
+               /*
+                * instead of playing games with moving completions around,
+                * remove failed request completely and end it when the
+                * request sense has completed
+                */
+               if (stat & ERR_STAT) {
+                       spin_lock_irqsave(&ide_lock, flags);
+                       blkdev_dequeue_request(rq);
+                       HWGROUP(drive)->rq = NULL;
+                       spin_unlock_irqrestore(&ide_lock, flags);
+
+                       cdrom_queue_request_sense(drive, rq->sense, rq);
+               } else
+                       cdrom_end_request(drive, 0);
 
-               if ((stat & ERR_STAT) != 0)
-                       cdrom_queue_request_sense(drive, wait, rq->sense, rq);
        } else if (blk_fs_request(rq)) {
                int do_end_request = 0;
 
@@ -781,14 +785,6 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                                do_end_request = 1;
                } else if (sense_key == ILLEGAL_REQUEST ||
                           sense_key == DATA_PROTECT) {
-                       /*
-                        * check if this was a write protected media
-                        */
-                       if (rq_data_dir(rq) == WRITE) {
-                               printk("ide-cd: media marked write protected\n");
-                               set_disk_ro(drive->disk, 1);
-                       }
-
                        /* No point in retrying after an illegal
                           request or data protect error.*/
                        ide_dump_status (drive, "command error", stat);
@@ -818,7 +814,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
                /* If we got a CHECK_CONDITION status,
                   queue a request sense command. */
                if ((stat & ERR_STAT) != 0)
-                       cdrom_queue_request_sense(drive, NULL, NULL, NULL);
+                       cdrom_queue_request_sense(drive, NULL, NULL);
        } else {
                blk_dump_rq_flags(rq, "ide-cd: bad rq");
                cdrom_end_request(drive, 0);
@@ -1666,14 +1662,8 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                dma_error = HWIF(drive)->ide_dma_end(drive);
        }
 
-       if (cdrom_decode_status(drive, 0, &stat)) {
-               if ((stat & ERR_STAT) != 0) {
-                       end_that_request_chunk(rq, 0, rq->data_len);
-                       goto end_request; /* purge the whole thing... */
-               }
-               end_that_request_chunk(rq, 1, rq->data_len);
+       if (cdrom_decode_status(drive, 0, &stat))
                return ide_stopped;
-       }
 
        /*
         * using dma, transfer is complete now
@@ -1969,13 +1959,17 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
         * sg request
         */
        if (rq->bio) {
-               if (rq->data_len & 3) {
-                       printk("%s: block pc not aligned, len=%d\n", drive->name, rq->data_len);
-                       cdrom_end_request(drive, 0);
-                       return ide_stopped;
-               }
-               info->dma = drive->using_dma;
+               int mask = drive->queue->dma_alignment;
+               unsigned long addr = (unsigned long) page_address(bio_page(rq->bio));
+
                info->cmd = rq_data_dir(rq);
+               info->dma = drive->using_dma;
+
+               /*
+                * check if dma is safe
+                */
+               if ((rq->data_len & mask) || (addr & mask))
+                       info->dma = 0;
        }
 
        /* Start sending the command to the drive. */
@@ -2491,7 +2485,7 @@ static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
 
 /* the generic packet interface to cdrom.c */
 static int ide_cdrom_packet(struct cdrom_device_info *cdi,
-                           struct cdrom_generic_command *cgc)
+                           struct packet_command *cgc)
 {
        struct request req;
        ide_drive_t *drive = (ide_drive_t*) cdi->handle;
@@ -2524,7 +2518,7 @@ static
 int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
                         unsigned int cmd, unsigned long arg)
 {
-       struct cdrom_generic_command cgc;
+       struct packet_command cgc;
        char buffer[16];
        int stat;
 
@@ -2535,7 +2529,7 @@ int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
        case CDROMSETSPINDOWN: {
                char spindown;
  
-               if (copy_from_user(&spindown, (void *) arg, sizeof(char)))
+               if (copy_from_user(&spindown, (void __user *) arg, sizeof(char)))
                        return -EFAULT;
  
                 if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
@@ -2554,7 +2548,7 @@ int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
  
                spindown = buffer[11] & 0x0f;
  
-               if (copy_to_user((void *) arg, &spindown, sizeof (char)))
+               if (copy_to_user((void __user *) arg, &spindown, sizeof (char)))
                        return -EFAULT;
  
                return 0;
@@ -2725,8 +2719,10 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
        if (!cdrom_get_media_event(cdi, &med)) {
                if (med.media_present)
                        return CDS_DISC_OK;
-               if (med.door_open)
+               else if (med.door_open)
                        return CDS_TRAY_OPEN;
+               else
+                       return CDS_NO_DISC;
        }
 
        if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04)
@@ -2738,10 +2734,12 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
         * any other way to detect this...
         */
        if (sense.sense_key == NOT_READY) {
-               if (sense.asc == 0x3a && sense.ascq == 1)
-                       return CDS_NO_DISC;
-               else
-                       return CDS_TRAY_OPEN;
+               if (sense.asc == 0x3a) {
+                       if (sense.ascq == 0 || sense.ascq == 1)
+                               return CDS_NO_DISC;
+                       else if (sense.ascq == 2)
+                               return CDS_TRAY_OPEN;
+               }
        }
 
        return CDS_DRIVE_NOT_READY;
@@ -2818,7 +2816,6 @@ int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose)
        return 0;
 }
 
-
 /*
  * Close down the device.  Invalidate all cached blocks.
  */
@@ -2892,12 +2889,6 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
                devinfo->mask |= CDC_CLOSE_TRAY;
        if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
                devinfo->mask |= CDC_MO_DRIVE;
-       if (!CDROM_CONFIG_FLAGS(drive)->mrw)
-               devinfo->mask |= CDC_MRW;
-       if (!CDROM_CONFIG_FLAGS(drive)->mrw_w)
-               devinfo->mask |= CDC_MRW_W;
-       if (!CDROM_CONFIG_FLAGS(drive)->ram)
-               devinfo->mask |= CDC_RAM;
 
        devinfo->disk = drive->disk;
        return register_cdrom(devinfo);
@@ -2908,7 +2899,7 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_pag
 {
        struct cdrom_info *info = drive->driver_data;
        struct cdrom_device_info *cdi = &info->devinfo;
-       struct cdrom_generic_command cgc;
+       struct packet_command cgc;
        int stat, attempts = 3, size = sizeof(*cap);
 
        /*
@@ -2934,7 +2925,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
        struct cdrom_info *info = drive->driver_data;
        struct cdrom_device_info *cdi = &info->devinfo;
        struct atapi_capabilities_page cap;
-       int nslots = 1, mrw_write = 0, ram_write = 0;
+       int nslots = 1;
 
        if (drive->media == ide_optical) {
                CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
@@ -2963,17 +2954,6 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
        if (ide_cdrom_get_capabilities(drive, &cap))
                return 0;
 
-       if (!cdrom_is_mrw(cdi, &mrw_write)) {
-               CDROM_CONFIG_FLAGS(drive)->mrw = 1;
-               if (mrw_write) {
-                       CDROM_CONFIG_FLAGS(drive)->mrw_w = 1;
-                       CDROM_CONFIG_FLAGS(drive)->ram = 1;
-               }
-       }
-       if (!cdrom_is_random_writable(cdi, &ram_write))
-               if (ram_write)
-                       CDROM_CONFIG_FLAGS(drive)->ram = 1;
-
        if (cap.lock == 0)
                CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
        if (cap.eject)
@@ -3053,9 +3033,6 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
                (CDROM_CONFIG_FLAGS(drive)->cd_r)? "-R" : "", 
                (CDROM_CONFIG_FLAGS(drive)->cd_rw)? "/RW" : "");
 
-       if (CDROM_CONFIG_FLAGS(drive)->mrw || CDROM_CONFIG_FLAGS(drive)->mrw_w)
-               printk(" CD-MR%s", CDROM_CONFIG_FLAGS(drive)->mrw_w ? "W" : "");
-
         if (CDROM_CONFIG_FLAGS(drive)->is_changer) 
                printk(" changer w/%d slots", nslots);
         else   
@@ -3164,7 +3141,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
        int nslots;
 
        blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
-       blk_queue_dma_alignment(drive->queue, 3);
+       blk_queue_dma_alignment(drive->queue, 31);
        drive->queue->unplug_delay = (1 * HZ) / 1000;
        if (!drive->queue->unplug_delay)
                drive->queue->unplug_delay = 1;
@@ -3271,9 +3248,8 @@ int ide_cdrom_setup (ide_drive_t *drive)
        nslots = ide_cdrom_probe_capabilities (drive);
 
        /*
-        * set correct block size and read-only for non-ram media
+        * set correct block size
         */
-       set_disk_ro(drive->disk, !CDROM_CONFIG_FLAGS(drive)->ram);
        blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
 
 #if 0
@@ -3423,10 +3399,10 @@ static int idecd_ioctl (struct inode *inode, struct file *file,
 {
        struct block_device *bdev = inode->i_bdev;
        ide_drive_t *drive = bdev->bd_disk->private_data;
-       int err = generic_ide_ioctl(bdev, cmd, arg);
+       int err = generic_ide_ioctl(file, bdev, cmd, arg);
        if (err == -EINVAL) {
                struct cdrom_info *info = drive->driver_data;
-               err = cdrom_ioctl(&info->devinfo, inode, cmd, arg);
+               err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg);
        }
        return err;
 }