X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fide%2Fide-cd.c;h=39f3e9101ed4b9eebb45237de5d1d3c982063d89;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=6f14bbfc3839bff777c835202fb0be46effa14ca;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 6f14bbfc3..39f3e9101 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -324,6 +324,34 @@ #include "ide-cd.h" +static DECLARE_MUTEX(idecd_ref_sem); + +#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) + +#define ide_cd_g(disk) \ + container_of((disk)->private_data, struct cdrom_info, driver) + +static struct cdrom_info *ide_cd_get(struct gendisk *disk) +{ + struct cdrom_info *cd = NULL; + + down(&idecd_ref_sem); + cd = ide_cd_g(disk); + if (cd) + kref_get(&cd->kref); + up(&idecd_ref_sem); + return cd; +} + +static void ide_cd_release(struct kref *); + +static void ide_cd_put(struct cdrom_info *cd) +{ + down(&idecd_ref_sem); + kref_put(&cd->kref, ide_cd_release); + up(&idecd_ref_sem); +} + /**************************************************************************** * Generic packet command support and error handling routines. */ @@ -456,7 +484,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, s = "(reserved error code)"; } - printk(" %s -- (asc=0x%02x, ascq=0x%02x)\n", + printk(KERN_ERR " %s -- (asc=0x%02x, ascq=0x%02x)\n", s, sense->asc, sense->ascq); if (failed_command != NULL) { @@ -478,7 +506,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, lo = mid+1; } - printk (" The failed \"%s\" packet command was: \n \"", s); + printk (KERN_ERR " The failed \"%s\" packet command was: \n \"", s); for (i=0; icmd); i++) printk ("%02x ", failed_command->cmd[i]); printk ("\"\n"); @@ -491,13 +519,13 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, */ if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) { int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100; - printk(" Command is %02d%% complete\n", progress / 0xffff); + printk(KERN_ERR " Command is %02d%% complete\n", progress / 0xffff); } if (sense->sense_key == ILLEGAL_REQUEST && (sense->sks[0] & 0x80) != 0) { - printk(" Error in %s byte %d", + printk(KERN_ERR " Error in %s byte %d", (sense->sks[0] & 0x40) != 0 ? "command packet" : "command data", (sense->sks[1] << 8) + sense->sks[2]); @@ -519,7 +547,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, sense->asc == 0x3a))) return; - printk("%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n", + printk(KERN_ERR "%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n", drive->name, sense->error_code, sense->sense_key, sense->asc, sense->ascq); @@ -529,10 +557,13 @@ void cdrom_analyze_sense_data(ide_drive_t *drive, /* * Initialize a ide-cd packet command request */ -static void cdrom_prepare_request(struct request *rq) +static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq) { + struct cdrom_info *cd = drive->driver_data; + ide_init_drive_cmd(rq); rq->flags = REQ_PC; + rq->rq_disk = cd->disk; } static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, @@ -545,7 +576,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, sense = &info->sense_data; /* stuff the sense request in front of our current request */ - cdrom_prepare_request(rq); + cdrom_prepare_request(drive, rq); rq->data = sense; rq->cmd[0] = GPCMD_REQUEST_SENSE; @@ -559,62 +590,6 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, (void) ide_do_drive_cmd(drive, rq, ide_preempt); } -/* - * ide_error() takes action based on the error returned by the drive. - */ -ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat) -{ - struct request *rq; - byte err; - - err = ide_dump_atapi_status(drive, msg, 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 | REQ_DRIVE_TASKFILE)) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); - return ide_stopped; - } - - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { - /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { - /* add decoding error stuff */ - } - if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) - /* force an abort */ - HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); - if (rq->errors >= ERROR_MAX) { - DRIVER(drive)->end_request(drive, 0, 0); - } else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - ++rq->errors; - } - return ide_stopped; -} - -ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg) -{ - struct request *rq; - - 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 | REQ_DRIVE_TASKFILE)) { - rq->errors = 1; - ide_end_drive_cmd(drive, BUSY_STAT, 0); - return ide_stopped; - } - rq->errors |= ERROR_RESET; - DRIVER(drive)->end_request(drive, 0, 0); - return ide_stopped; -} - static void cdrom_end_request (ide_drive_t *drive, int uptodate) { struct request *rq = HWGROUP(drive)->rq; @@ -690,7 +665,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) rq->flags |= REQ_FAILED; cdrom_end_request(drive, 0); - DRIVER(drive)->error(drive, "request sense failure", stat); + ide_error(drive, "request sense failure", stat); return 1; } else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) { @@ -785,14 +760,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); @@ -809,7 +776,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) } else if ((err & ~ABRT_ERR) != 0) { /* Go to the default handler for other errors. */ - DRIVER(drive)->error(drive, "cdrom_decode_status",stat); + ide_error(drive, "cdrom_decode_status", stat); return 1; } else if ((++rq->errors > ERROR_MAX)) { /* We've racked up too many retries. Abort. */ @@ -873,20 +840,14 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, { ide_startstop_t startstop; struct cdrom_info *info = drive->driver_data; + ide_hwif_t *hwif = drive->hwif; /* Wait for the controller to be idle. */ if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) return startstop; - if (info->dma) { - if (info->cmd == READ) { - info->dma = !HWIF(drive)->ide_dma_read(drive); - } else if (info->cmd == WRITE) { - info->dma = !HWIF(drive)->ide_dma_write(drive); - } else { - printk("ide-cd: DMA set, but not allowed\n"); - } - } + if (info->dma) + info->dma = !hwif->dma_setup(drive); /* Set up the controller registers. */ /* FIXME: for Virtual DMA we must check harder */ @@ -904,8 +865,14 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry); return ide_started; } else { + unsigned long flags; + /* packet command */ - HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); + spin_lock_irqsave(&ide_lock, flags); + hwif->OUTBSYNC(drive, WIN_PACKETCMD, IDE_COMMAND_REG); + ndelay(400); + spin_unlock_irqrestore(&ide_lock, flags); + return (*handler) (drive); } } @@ -924,6 +891,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, struct request *rq, ide_handler_t *handler) { + ide_hwif_t *hwif = drive->hwif; int cmd_len; struct cdrom_info *info = drive->driver_data; ide_startstop_t startstop; @@ -955,7 +923,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, /* Start the DMA if need be */ if (info->dma) - (void) HWIF(drive)->ide_dma_begin(drive); + hwif->dma_start(drive); return ide_started; } @@ -1021,7 +989,7 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) return 0; else if (ireason == 0) { /* Whoops... The drive is expecting to receive data from us! */ - printk("%s: read_intr: Drive wants to transfer data the " + printk(KERN_ERR "%s: read_intr: Drive wants to transfer data the " "wrong way!\n", drive->name); /* Throw some data at the drive so it doesn't hang @@ -1039,7 +1007,7 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) return 0; } else { /* Drive wants a command packet, or invalid ireason... */ - printk("%s: read_intr: bad interrupt reason %x\n", drive->name, + printk(KERN_ERR "%s: read_intr: bad interrupt reason %x\n", drive->name, ireason); } @@ -1077,7 +1045,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) ide_end_request(drive, 1, rq->nr_sectors); return ide_stopped; } else - return DRIVER(drive)->error(drive, "dma error", stat); + return ide_error(drive, "dma error", stat); } /* Read the interrupt reason and the transfer length. */ @@ -1092,7 +1060,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) /* If we're not done filling the current buffer, complain. Otherwise, complete the command normally. */ if (rq->current_nr_sectors > 0) { - printk ("%s: cdrom_read_intr: data underrun (%d blocks)\n", + printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n", drive->name, rq->current_nr_sectors); rq->flags |= REQ_FAILED; cdrom_end_request(drive, 0); @@ -1109,12 +1077,12 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) of at least SECTOR_SIZE, as it gets hairy to keep track of the transfers otherwise. */ if ((len % SECTOR_SIZE) != 0) { - printk ("%s: cdrom_read_intr: Bad transfer size %d\n", + printk (KERN_ERR "%s: cdrom_read_intr: Bad transfer size %d\n", drive->name, len); if (CDROM_CONFIG_FLAGS(drive)->limit_nframes) - printk (" This drive is not supported by this version of the driver\n"); + printk (KERN_ERR " This drive is not supported by this version of the driver\n"); else { - printk (" Trying to limit transfer sizes\n"); + printk (KERN_ERR " Trying to limit transfer sizes\n"); CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; } cdrom_end_request(drive, 0); @@ -1228,7 +1196,7 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) paranoid and check. */ if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) && (rq->sector & (sectors_per_frame - 1))) { - printk("%s: cdrom_read_from_buffer: buffer botch (%ld)\n", + printk(KERN_ERR "%s: cdrom_read_from_buffer: buffer botch (%ld)\n", drive->name, (long)rq->sector); cdrom_end_request(drive, 0); return -1; @@ -1263,7 +1231,7 @@ static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive) /* Sanity check... */ if (rq->current_nr_sectors != bio_cur_sectors(rq->bio) && (rq->sector & (sectors_per_frame - 1))) { - printk ("%s: cdrom_start_read_continuation: buffer botch (%u)\n", + printk(KERN_ERR "%s: cdrom_start_read_continuation: buffer botch (%u)\n", drive->name, rq->current_nr_sectors); cdrom_end_request(drive, 0); return ide_stopped; @@ -1488,7 +1456,7 @@ static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) rq->sense_len += thislen; } else { confused: - printk ("%s: cdrom_pc_intr: The drive " + printk (KERN_ERR "%s: cdrom_pc_intr: The drive " "appears confused (ireason = 0x%02x)\n", drive->name, ireason); rq->flags |= REQ_FAILED; @@ -1527,19 +1495,6 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive) } -/* Sleep for TIME jiffies. - Not to be called from an interrupt handler. */ -static -void cdrom_sleep (int time) -{ - int sleep = time; - - do { - set_current_state(TASK_INTERRUPTIBLE); - sleep = schedule_timeout(sleep); - } while (sleep); -} - static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) { @@ -1574,7 +1529,7 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) /* The drive is in the process of loading a disk. Retry, but wait a little to give the drive time to complete the load. */ - cdrom_sleep(2 * HZ); + ssleep(2); } else { /* Otherwise, don't retry. */ retries = 0; @@ -1602,7 +1557,7 @@ static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ire return 0; else if (ireason == 2) { /* Whoops... The drive wants to send data. */ - printk("%s: write_intr: wrong transfer direction!\n", + printk(KERN_ERR "%s: write_intr: wrong transfer direction!\n", drive->name); while (len > 0) { @@ -1612,7 +1567,7 @@ static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ire } } else { /* Drive wants a command packet, or invalid ireason... */ - printk("%s: write_intr: bad interrupt reason %x\n", + printk(KERN_ERR "%s: write_intr: bad interrupt reason %x\n", drive->name, ireason); } @@ -1678,9 +1633,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) */ if (dma) { if (dma_error) { - printk("ide-cd: dma error\n"); + printk(KERN_ERR "ide-cd: dma error\n"); __ide_dma_off(drive); - return DRIVER(drive)->error(drive, "dma error", stat); + return ide_error(drive, "dma error", stat); } end_that_request_chunk(rq, 1, rq->data_len); @@ -1743,7 +1698,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) } if (!ptr) { - printk("%s: confused, missing data\n", drive->name); + printk(KERN_ERR "%s: confused, missing data\n", drive->name); break; } @@ -1805,7 +1760,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) if (dma) { info->dma = 0; if ((dma_error = HWIF(drive)->ide_dma_end(drive))) { - printk("ide-cd: write dma error\n"); + printk(KERN_ERR "ide-cd: write dma error\n"); __ide_dma_off(drive); } } @@ -1818,7 +1773,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) */ if (dma) { if (dma_error) - return DRIVER(drive)->error(drive, "dma error", stat); + return ide_error(drive, "dma error", stat); ide_end_request(drive, 1, rq->nr_sectors); return ide_stopped; @@ -1838,7 +1793,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) */ uptodate = 1; if (rq->current_nr_sectors > 0) { - printk("%s: write_intr: data underrun (%d blocks)\n", + printk(KERN_ERR "%s: write_intr: data underrun (%d blocks)\n", drive->name, rq->current_nr_sectors); uptodate = 0; } @@ -1859,7 +1814,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) int this_transfer; if (!rq->current_nr_sectors) { - printk("ide-cd: write_intr: oops\n"); + printk(KERN_ERR "ide-cd: write_intr: oops\n"); break; } @@ -1905,7 +1860,7 @@ static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive) static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) { struct cdrom_info *info = drive->driver_data; - struct gendisk *g = drive->disk; + struct gendisk *g = info->disk; unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; /* @@ -1940,6 +1895,8 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) info->dma = drive->using_dma ? 1 : 0; info->cmd = WRITE; + info->devinfo.media_written = 1; + /* Start sending the write request to the drive. */ return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont); } @@ -1967,13 +1924,20 @@ 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 + * + * NOTE! The "len" and "addr" checks should possibly have + * separate masks. + */ + if ((rq->data_len & 15) || (addr & mask)) + info->dma = 0; } /* Start sending the command to the drive. */ @@ -1999,11 +1963,11 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block) ide_stall_queue(drive, IDECD_SEEK_TIMER); return ide_stopped; } - printk ("%s: DSC timeout\n", drive->name); + printk (KERN_ERR "%s: DSC timeout\n", drive->name); } CDROM_CONFIG_FLAGS(drive)->seeking = 0; } - if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) { + if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) { action = cdrom_start_seek(drive, block); } else { if (rq_data_dir(rq) == READ) @@ -2091,7 +2055,7 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense) struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *cdi = &info->devinfo; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; req.cmd[0] = GPCMD_TEST_UNIT_READY; @@ -2123,7 +2087,7 @@ cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense) if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) { stat = 0; } else { - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; req.cmd[4] = lockflag ? 1 : 0; @@ -2135,7 +2099,7 @@ cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense) if (stat != 0 && sense->sense_key == ILLEGAL_REQUEST && (sense->asc == 0x24 || sense->asc == 0x20)) { - printk ("%s: door locking not supported\n", + printk (KERN_ERR "%s: door locking not supported\n", drive->name); CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1; stat = 0; @@ -2167,7 +2131,7 @@ static int cdrom_eject(ide_drive_t *drive, int ejectflag, if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag) return 0; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); /* only tell drive to close tray if open, if it can do that */ if (ejectflag && !CDROM_CONFIG_FLAGS(drive)->close_tray) @@ -2191,7 +2155,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, int stat; struct request req; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; req.cmd[0] = GPCMD_READ_CDVD_CAPACITY; @@ -2214,7 +2178,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag, { struct request req; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; req.data = buf; @@ -2253,7 +2217,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) GFP_KERNEL); info->toc = toc; if (toc == NULL) { - printk ("%s: No cdrom TOC buffer!\n", drive->name); + printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name); return -ENOMEM; } } @@ -2271,7 +2235,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) if (stat) toc->capacity = 0x1fffff; - set_capacity(drive->disk, toc->capacity * sectors_per_frame); + set_capacity(info->disk, toc->capacity * sectors_per_frame); blk_queue_hardsect_size(drive->queue, sectors_per_frame << SECTOR_BITS); @@ -2360,32 +2324,38 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense) /* Read the multisession information. */ if (toc->hdr.first_track != CDROM_LEADOUT) { /* Read the multisession information. */ - stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, + stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp, sizeof(ms_tmp), sense); if (stat) return stat; + + toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba); } else { - ms_tmp.ent.addr.msf.minute = 0; - ms_tmp.ent.addr.msf.second = 2; - ms_tmp.ent.addr.msf.frame = 0; ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT; + toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */ } #if ! STANDARD_ATAPI - if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) + if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) { + /* Re-read multisession information using MSF format */ + stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp, + sizeof(ms_tmp), sense); + if (stat) + return stat; + msf_from_bcd (&ms_tmp.ent.addr.msf); + toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute, + ms_tmp.ent.addr.msf.second, + ms_tmp.ent.addr.msf.frame); + } #endif /* not STANDARD_ATAPI */ - toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute, - ms_tmp.ent.addr.msf.second, - ms_tmp.ent.addr.msf.frame); - toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track); /* Now try to get the total cdrom capacity. */ stat = cdrom_get_last_written(cdi, &last_written); if (!stat && (last_written > toc->capacity)) { toc->capacity = last_written; - set_capacity(drive->disk, toc->capacity * sectors_per_frame); + set_capacity(info->disk, toc->capacity * sectors_per_frame); } /* Remember that we've read this stuff. */ @@ -2400,7 +2370,7 @@ static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf, { struct request req; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; req.data = buf; @@ -2420,7 +2390,7 @@ static int cdrom_select_speed(ide_drive_t *drive, int speed, struct request_sense *sense) { struct request req; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = sense; if (speed == 0) @@ -2450,7 +2420,7 @@ static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end) struct request_sense sense; struct request req; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.sense = &sense; req.cmd[0] = GPCMD_PLAY_AUDIO_MSF; @@ -2500,7 +2470,7 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi, /* here we queue the commands from the uniform CD-ROM layer. the packet must be complete, as we do not touch it at all. */ - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE); if (cgc->sense) memset(cgc->sense, 0, sizeof(struct request_sense)); @@ -2650,7 +2620,7 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi) struct request req; int ret; - cdrom_prepare_request(&req); + cdrom_prepare_request(drive, &req); req.flags = REQ_SPECIAL | REQ_QUIET; ret = ide_do_drive_cmd(drive, &req, ide_wait); @@ -2723,8 +2693,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) @@ -2736,10 +2708,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 == 1) + return CDS_NO_DISC; + else if (sense.ascq == 0 || sense.ascq == 2) + return CDS_TRAY_OPEN; + } } return CDS_DRIVE_NOT_READY; @@ -2816,7 +2790,6 @@ int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose) return 0; } - /* * Close down the device. Invalidate all cached blocks. */ @@ -2890,14 +2863,8 @@ 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; + + devinfo->disk = info->disk; return register_cdrom(devinfo); } @@ -2932,12 +2899,12 @@ 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; CDROM_CONFIG_FLAGS(drive)->ram = 1; - printk("%s: ATAPI magneto-optical drive\n", drive->name); + printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name); return nslots; } @@ -2961,25 +2928,16 @@ 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) CDROM_CONFIG_FLAGS(drive)->no_eject = 0; if (cap.cd_r_write) CDROM_CONFIG_FLAGS(drive)->cd_r = 1; - if (cap.cd_rw_write) + if (cap.cd_rw_write) { CDROM_CONFIG_FLAGS(drive)->cd_rw = 1; + CDROM_CONFIG_FLAGS(drive)->ram = 1; + } if (cap.test_write) CDROM_CONFIG_FLAGS(drive)->test_write = 1; if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom) @@ -3036,7 +2994,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) /* don't print speed if the drive reported 0. */ - printk("%s: ATAPI", drive->name); + printk(KERN_INFO "%s: ATAPI", drive->name); if (CDROM_CONFIG_FLAGS(drive)->max_speed) printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed); printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM"); @@ -3051,9 +3009,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 @@ -3061,10 +3016,9 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) printk(", %dkB Cache", be16_to_cpu(cap.buffer_size)); -#ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma) - (void) HWIF(drive)->ide_dma_verbose(drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ + ide_dma_verbose(drive); + printk("\n"); return nslots; @@ -3162,13 +3116,12 @@ 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; drive->special.all = 0; - drive->ready_stat = 0; CDROM_STATE_FLAGS(drive)->media_changed = 1; CDROM_STATE_FLAGS(drive)->toc_valid = 0; @@ -3269,11 +3222,13 @@ 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 (drive->autotune == IDE_TUNE_DEFAULT || + drive->autotune == IDE_TUNE_AUTO) + drive->dsc_overlap = (drive->next != drive); #if 0 drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1; if (HWIF(drive)->no_dsc) { @@ -3284,7 +3239,7 @@ int ide_cdrom_setup (ide_drive_t *drive) #endif if (ide_cdrom_register(drive, nslots)) { - printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); + printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); info->devinfo.handle = NULL; return 1; } @@ -3303,18 +3258,27 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive) return capacity * sectors_per_frame; } -static -int ide_cdrom_cleanup(ide_drive_t *drive) +static int ide_cd_remove(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); struct cdrom_info *info = drive->driver_data; + + ide_unregister_subdriver(drive, info->driver); + + del_gendisk(info->disk); + + ide_cd_put(info); + + return 0; +} + +static void ide_cd_release(struct kref *kref) +{ + struct cdrom_info *info = to_ide_cd(kref); struct cdrom_device_info *devinfo = &info->devinfo; - struct gendisk *g = drive->disk; + ide_drive_t *drive = info->drive; + struct gendisk *g = info->disk; - if (ide_unregister_subdriver(drive)) { - printk("%s: %s: failed to ide_unregister_subdriver\n", - __FUNCTION__, drive->name); - return 1; - } if (info->buffer != NULL) kfree(info->buffer); if (info->toc != NULL) @@ -3322,80 +3286,67 @@ int ide_cdrom_cleanup(ide_drive_t *drive) if (info->changer_info != NULL) kfree(info->changer_info); if (devinfo->handle == drive && unregister_cdrom(devinfo)) - printk("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); - kfree(info); + printk(KERN_ERR "%s: %s failed to unregister device from the cdrom " + "driver.\n", __FUNCTION__, drive->name); + drive->dsc_overlap = 0; drive->driver_data = NULL; blk_queue_prep_rq(drive->queue, NULL); - del_gendisk(g); - g->fops = ide_fops; - return 0; + g->private_data = NULL; + put_disk(g); + kfree(info); } -static int ide_cdrom_attach (ide_drive_t *drive); - -/* - * Power Management state machine. - * - * We don't do much for CDs right now. - */ +static int ide_cd_probe(struct device *); -static void ide_cdrom_complete_power_step (ide_drive_t *drive, struct request *rq, u8 stat, u8 error) +#ifdef CONFIG_PROC_FS +static int proc_idecd_read_capacity + (char *page, char **start, off_t off, int count, int *eof, void *data) { -} - -static ide_startstop_t ide_cdrom_start_power_step (ide_drive_t *drive, struct request *rq) -{ - ide_task_t *args = rq->special; - - memset(args, 0, sizeof(*args)); - - switch (rq->pm->pm_step) { - case ide_pm_state_start_suspend: - break; + ide_drive_t*drive = (ide_drive_t *)data; + int len; - case ide_pm_state_start_resume: /* Resume step 1 (restore DMA) */ - /* - * Right now, all we do is call hwif->ide_dma_check(drive), - * we could be smarter and check for current xfer_speed - * in struct drive etc... - * Also, this step could be implemented as a generic helper - * as most subdrivers will use it. - */ - if ((drive->id->capability & 1) == 0) - break; - if (HWIF(drive)->ide_dma_check == NULL) - break; - HWIF(drive)->ide_dma_check(drive); - break; - } - rq->pm->pm_step = ide_pm_state_completed; - return ide_stopped; + len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive)); + PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } +static ide_proc_entry_t idecd_proc[] = { + { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, + { NULL, 0, NULL, NULL } +}; +#else +# define idecd_proc NULL +#endif + static ide_driver_t ide_cdrom_driver = { .owner = THIS_MODULE, - .name = "ide-cdrom", + .gen_driver = { + .name = "ide-cdrom", + .bus = &ide_bus_type, + .probe = ide_cd_probe, + .remove = ide_cd_remove, + }, .version = IDECD_VERSION, .media = ide_cdrom, - .busy = 0, .supports_dsc_overlap = 1, - .cleanup = ide_cdrom_cleanup, .do_request = ide_do_rw_cdrom, - .sense = ide_dump_atapi_status, - .error = ide_cdrom_error, - .abort = ide_cdrom_abort, - .capacity = ide_cdrom_capacity, - .attach = ide_cdrom_attach, - .drives = LIST_HEAD_INIT(ide_cdrom_driver.drives), - .start_power_step = ide_cdrom_start_power_step, - .complete_power_step = ide_cdrom_complete_power_step, + .end_request = ide_end_request, + .error = __ide_error, + .abort = __ide_abort, + .proc = idecd_proc, }; static int idecd_open(struct inode * inode, struct file * file) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; - struct cdrom_info *info = drive->driver_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct cdrom_info *info; + ide_drive_t *drive; int rc = -ENOMEM; + + if (!(info = ide_cd_get(disk))) + return -ENXIO; + + drive = info->drive; + drive->usage++; if (!info->buffer) @@ -3403,16 +3354,24 @@ static int idecd_open(struct inode * inode, struct file * file) GFP_KERNEL|__GFP_REPEAT); if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file))) drive->usage--; + + if (rc < 0) + ide_cd_put(info); + return rc; } static int idecd_release(struct inode * inode, struct file * file) { - ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; - struct cdrom_info *info = drive->driver_data; + struct gendisk *disk = inode->i_bdev->bd_disk; + struct cdrom_info *info = ide_cd_g(disk); + ide_drive_t *drive = info->drive; cdrom_release (&info->devinfo, file); drive->usage--; + + ide_cd_put(info); + return 0; } @@ -3420,27 +3379,27 @@ static int idecd_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct block_device *bdev = inode->i_bdev; - ide_drive_t *drive = bdev->bd_disk->private_data; - int err = generic_ide_ioctl(bdev, cmd, arg); - if (err == -EINVAL) { - struct cdrom_info *info = drive->driver_data; - err = cdrom_ioctl(&info->devinfo, inode, cmd, arg); - } + struct cdrom_info *info = ide_cd_g(bdev->bd_disk); + int err; + + err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg); + if (err == -EINVAL) + err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg); + return err; } static int idecd_media_changed(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; - struct cdrom_info *info = drive->driver_data; + struct cdrom_info *info = ide_cd_g(disk); return cdrom_media_changed(&info->devinfo); } static int idecd_revalidate_disk(struct gendisk *disk) { - ide_drive_t *drive = disk->private_data; + struct cdrom_info *info = ide_cd_g(disk); struct request_sense sense; - cdrom_read_toc(drive, &sense); + cdrom_read_toc(info->drive, &sense); return 0; } @@ -3454,15 +3413,16 @@ static struct block_device_operations idecd_ops = { }; /* options */ -char *ignore = NULL; +static char *ignore = NULL; -MODULE_PARM(ignore, "s"); +module_param(ignore, charp, 0400); MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); -static int ide_cdrom_attach (ide_drive_t *drive) +static int ide_cd_probe(struct device *dev) { + ide_drive_t *drive = to_ide_device(dev); struct cdrom_info *info; - struct gendisk *g = drive->disk; + struct gendisk *g; struct request_sense sense; if (!strstr("ide-cdrom", drive->driver_req)) @@ -3474,28 +3434,40 @@ static int ide_cdrom_attach (ide_drive_t *drive) /* skip drives that we were told to ignore */ if (ignore != NULL) { if (strstr(ignore, drive->name)) { - printk("ide-cd: ignoring drive %s\n", drive->name); + printk(KERN_INFO "ide-cd: ignoring drive %s\n", drive->name); goto failed; } } if (drive->scsi) { - printk("ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name); + printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name); goto failed; } info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL); if (info == NULL) { - printk("%s: Can't allocate a cdrom structure\n", drive->name); - goto failed; - } - if (ide_register_subdriver(drive, &ide_cdrom_driver)) { - printk("%s: Failed to register the driver with ide.c\n", - drive->name); - kfree(info); + printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name); goto failed; } + + g = alloc_disk(1 << PARTN_BITS); + if (!g) + goto out_free_cd; + + ide_init_disk(g, drive); + + ide_register_subdriver(drive, &ide_cdrom_driver); + memset(info, 0, sizeof (struct cdrom_info)); + + kref_init(&info->kref); + + info->drive = drive; + info->driver = &ide_cdrom_driver; + info->disk = g; + + g->private_data = &info->driver; + drive->driver_data = info; - DRIVER(drive)->busy++; + g->minors = 1; snprintf(g->devfs_name, sizeof(g->devfs_name), "%s/cd", drive->devfs_name); @@ -3503,8 +3475,7 @@ static int ide_cdrom_attach (ide_drive_t *drive) g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; if (ide_cdrom_setup(drive)) { struct cdrom_device_info *devinfo = &info->devinfo; - DRIVER(drive)->busy--; - ide_unregister_subdriver(drive); + ide_unregister_subdriver(drive, &ide_cdrom_driver); if (info->buffer != NULL) kfree(info->buffer); if (info->toc != NULL) @@ -3512,31 +3483,32 @@ static int ide_cdrom_attach (ide_drive_t *drive) if (info->changer_info != NULL) kfree(info->changer_info); if (devinfo->handle == drive && unregister_cdrom(devinfo)) - printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); + printk (KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); kfree(info); drive->driver_data = NULL; goto failed; } - DRIVER(drive)->busy--; cdrom_read_toc(drive, &sense); g->fops = &idecd_ops; g->flags |= GENHD_FL_REMOVABLE; add_disk(g); return 0; + +out_free_cd: + kfree(info); failed: - return 1; + return -ENODEV; } static void __exit ide_cdrom_exit(void) { - ide_unregister_driver(&ide_cdrom_driver); + driver_unregister(&ide_cdrom_driver.gen_driver); } static int ide_cdrom_init(void) { - ide_register_driver(&ide_cdrom_driver); - return 0; + return driver_register(&ide_cdrom_driver.gen_driver); } module_init(ide_cdrom_init);