dvd-2.2.13-5.diff
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:291k
- IDE_COMMAND_REG);
- case ide_dma_begin:
- diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.2.13/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
- --- linux-2.2.13/drivers/block/ide-tape.c Thu Sep 9 12:27:35 1999
- +++ linux/drivers/block/ide-tape.c Sun Nov 7 15:18:54 1999
- @@ -1829,7 +1829,7 @@
- if (temp > pc->buffer_size) {
- printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding datan");
- idetape_discard_data (drive,bcount.all);
- - ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD);
- + ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL);
- return;
- }
- #if IDETAPE_DEBUG_LOG
- @@ -1851,7 +1851,7 @@
- pc->actually_transferred+=bcount.all; /* Update the current position */
- pc->current_position+=bcount.all;
-
- - ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD); /* And set the interrupt handler again */
- + ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL); /* And set the interrupt handler again */
- }
-
- /*
- @@ -1924,7 +1924,7 @@
- ide_do_reset (drive);
- return;
- }
- - ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD); /* Set the interrupt routine */
- + ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */
- atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */
- }
-
- @@ -1990,7 +1990,7 @@
- }
- #endif /* CONFIG_BLK_DEV_IDEDMA */
- if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
- - ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD);
- + ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
- OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
- } else {
- OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
- diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.2.13/drivers/block/ide.c linux/drivers/block/ide.c
- --- linux-2.2.13/drivers/block/ide.c Fri Nov 5 15:15:33 1999
- +++ linux/drivers/block/ide.c Sun Nov 7 15:28:05 1999
- @@ -466,7 +466,8 @@
- * timer is started to prevent us from waiting forever in case
- * something goes wrong (see the ide_timer_expiry() handler later on).
- */
- -void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout)
- +void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
- + unsigned int timeout, ide_expiry_t *expiry)
- {
- unsigned long flags;
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- @@ -478,8 +479,9 @@
- drive->name, hwgroup->handler, handler);
- }
- #endif
- - hwgroup->handler = handler;
- - hwgroup->timer.expires = jiffies + timeout;
- + hwgroup->handler = handler;
- + hwgroup->expiry = expiry;
- + hwgroup->timer.expires = jiffies + timeout;
- add_timer(&(hwgroup->timer));
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
- }
- @@ -536,7 +538,7 @@
- printk("%s: ATAPI reset completen", drive->name);
- } else {
- if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
- - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20);
- + ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
- return; /* continue polling */
- }
- hwgroup->poll_timeout = 0; /* end of polling */
- @@ -561,7 +563,7 @@
-
- if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) {
- if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
- - ide_set_handler (drive, &reset_pollfunc, HZ/20);
- + ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
- return; /* continue polling */
- }
- printk("%s: reset timed-out, status=0x%02xn", hwif->name, tmp);
- @@ -640,7 +642,7 @@
- udelay (20);
- OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
- hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20);
- + ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
- __restore_flags (flags); /* local CPU only */
- return;
- }
- @@ -666,7 +668,7 @@
- OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */
- udelay(10); /* more than enough time */
- hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- - ide_set_handler (drive, &reset_pollfunc, HZ/20);
- + ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
- #endif /* OK_TO_RESET_CONTROLLER */
-
- __restore_flags (flags); /* local CPU only */
- @@ -857,7 +859,7 @@
- */
- void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
- {
- - ide_set_handler (drive, handler, WAIT_CMD);
- + ide_set_handler (drive, handler, WAIT_CMD, NULL);
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
- OUT_BYTE(nsect,IDE_NSECTOR_REG);
- OUT_BYTE(cmd,IDE_COMMAND_REG);
- @@ -1286,7 +1288,9 @@
- ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
- ide_drive_t *drive;
- ide_handler_t *handler;
- + ide_expiry_t *expiry;
- unsigned long flags;
- + unsigned long wait;
-
- spin_lock_irqsave(&hwgroup->spinlock, flags);
- drive = hwgroup->drive;
- @@ -1295,10 +1299,23 @@
- do_hwgroup_request(hwgroup);
- return;
- }
- +
- hwgroup->busy = 1; /* should already be "1" */
- +
- + if ((expiry = hwgroup->expiry) != NULL) {
- + /* continue */
- + if ((wait = expiry(drive)) != 0) {
- + /* reset timer */
- + hwgroup->timer.expires = jiffies + wait;
- + add_timer(&(hwgroup->timer));
- + spin_unlock_irqrestore(&hwgroup->spinlock, flags);
- + return;
- + }
- + }
- +
- hwgroup->handler = NULL;
- - del_timer(&hwgroup->timer); /* Is this needed?? */
- - if (hwgroup->poll_timeout != 0) { /* polling in progress? */
- + /* polling in progress or just don't timeout */
- + if (hwgroup->poll_timeout != 0) {
- spin_unlock_irqrestore(&hwgroup->spinlock, flags);
- handler(drive);
- } else if (drive_is_ready(drive)) {
- @@ -1539,13 +1556,10 @@
- }
- spin_unlock_irqrestore(&io_request_lock, flags);
- do_hwgroup_request(hwgroup);
- - save_flags(flags); /* all CPUs; overkill? */
- - cli(); /* all CPUs; overkill? */
- if (action == ide_wait)
- {
- down(&sem); /* wait for it to be serviced */
- }
- - restore_flags(flags); /* all CPUs; overkill? */
- return rq->errors ? -EIO : 0; /* return -EIO if errors */
- }
-
- diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.2.13/drivers/block/ide.h linux/drivers/block/ide.h
- --- linux-2.2.13/drivers/block/ide.h Sun Mar 28 20:03:35 1999
- +++ linux/drivers/block/ide.h Sun Nov 7 15:26:07 1999
- @@ -357,6 +357,12 @@
- */
- typedef void (ide_handler_t)(ide_drive_t *);
-
- +/*
- + * when ide_timer_expiry fires, invoke a handler of this type
- + * to decide what to do.
- + */
- +typedef int (ide_expiry_t)(ide_drive_t *);
- +
- typedef struct hwgroup_s {
- spinlock_t spinlock; /* protects "busy" and "handler" */
- ide_handler_t *handler;/* irq handler, if active */
- @@ -367,6 +373,7 @@
- struct timer_list timer; /* failsafe timer */
- struct request wrq; /* local copy of current write rq */
- unsigned long poll_timeout; /* timeout value during long polls */
- + ide_expiry_t *expiry; /* queried upon timeouts */
- } ide_hwgroup_t;
-
- /*
- @@ -536,7 +543,7 @@
- * This is used on exit from the driver, to designate the next irq handler
- * and also to start the safety timer.
- */
- -void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout);
- +void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry);
-
- /*
- * Error reporting, in human readable form (luxurious, but a memory hog).
- diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.2.13/drivers/block/paride/pcd.c linux/drivers/block/paride/pcd.c
- --- linux-2.2.13/drivers/block/paride/pcd.c Wed Nov 4 19:03:01 1998
- +++ linux/drivers/block/paride/pcd.c Sun Oct 31 13:23:55 1999
- @@ -143,8 +143,8 @@
- #include <linux/delay.h>
- #include <linux/cdrom.h>
-
- -#include <asm/uaccess.h>
- #include <asm/spinlock.h>
- +#include <asm/uaccess.h>
-
- #ifndef MODULE
-
- @@ -214,8 +214,11 @@
- static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
- static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg);
- +static int pcd_packet(struct cdrom_device_info *cdi,
- + struct cdrom_generic_command *cgc);
-
- static int pcd_detect(void);
- +static void pcd_probe_capabilities(void);
- static void do_pcd_read_drq(void);
- static void do_pcd_request(void);
- static void do_pcd_read(void);
- @@ -276,14 +279,18 @@
- pcd_drive_reset,
- pcd_audio_ioctl,
- 0, /* dev_ioctl */
- - CDC_CLOSE_TRAY |
- - CDC_OPEN_TRAY |
- - CDC_LOCK |
- - CDC_MCN |
- - CDC_MEDIA_CHANGED |
- - CDC_RESET |
- - CDC_PLAY_AUDIO,
- - 0
- + CDC_CLOSE_TRAY |
- + CDC_OPEN_TRAY |
- + CDC_LOCK |
- + CDC_MCN |
- + CDC_MEDIA_CHANGED |
- + CDC_RESET |
- + CDC_PLAY_AUDIO |
- + CDC_GENERIC_PACKET |
- + CDC_CD_R |
- + CDC_CD_RW,
- + 0,
- + pcd_packet,
- };
-
- static void pcd_init_units( void )
- @@ -325,6 +332,9 @@
-
- if (pcd_detect()) return -1;
-
- + /* get the atapi capabilities page */
- + pcd_probe_capabilities();
- +
- if (register_blkdev(MAJOR_NR,name,&cdrom_fops)) {
- printk("pcd: unable to get major number %dn",MAJOR_NR);
- return -1;
- @@ -525,6 +535,16 @@
- return r;
- }
-
- +static int pcd_packet(struct cdrom_device_info *cdi,
- + struct cdrom_generic_command *cgc)
- +{
- + char *un_cmd;
- + int unit = DEVICE_NR(cdi->dev);
- +
- + un_cmd = cgc->cmd;
- + return pcd_atapi(unit,un_cmd,cgc->buflen,cgc->buffer, "generic packet");
- +}
- +
- #define DBMSG(msg) ((verbose>1)?(msg):NULL)
-
- static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
- @@ -667,6 +687,32 @@
- return -1;
- }
-
- +static void pcd_probe_capabilities( void )
- +
- +{ int unit, r;
- + char buffer[32];
- + char cmd[12]={0x5a,1<<3,0x2a,0,0,0,0,18,0,0,0,0};
- +
- + for (unit=0;unit<PCD_UNITS;unit++) {
- + if (!PCD.present) continue;
- + r = pcd_atapi(unit,cmd,18, buffer,"mode sense capabilities");
- + if (r) continue;
- + /* we should now have the cap page */
- + if ((buffer[11] & 1) == 0)
- + PCD.info.mask |= CDC_CD_R;
- + if ((buffer[11] & 2) == 0)
- + PCD.info.mask |= CDC_CD_RW;
- + if ((buffer[12] & 1) == 0)
- + PCD.info.mask |= CDC_PLAY_AUDIO;
- + if ((buffer[14] & 1) == 0)
- + PCD.info.mask |= CDC_LOCK;
- + if ((buffer[14] & 8) == 0)
- + PCD.info.mask |= CDC_OPEN_TRAY;
- + if ((buffer[14] >> 6) == 0)
- + PCD.info.mask |= CDC_CLOSE_TRAY;
- + }
- +}
- +
- static int pcd_detect( void )
-
- { char id[18];
- @@ -836,66 +882,9 @@
-
- switch (cmd) {
-
- - case CDROMPAUSE:
- -
- - { char cmd[12]={SCMD_PAUSE_RESUME,0,0,0,0,0,0,0,0,0,0,0};
- -
- - return (pcd_atapi(unit,cmd,0,NULL,"pause")) * EIO;
- - }
- -
- - case CDROMRESUME:
- -
- - { char cmd[12]={SCMD_PAUSE_RESUME,0,0,0,0,0,0,0,1,0,0,0};
- -
- - return (pcd_atapi(unit,cmd,0,NULL,"resume")) * EIO;
- - }
- -
- - case CDROMPLAYMSF:
- -
- - { char cmd[12]={SCMD_PLAYAUDIO_MSF,0,0,0,0,0,0,0,0,0,0,0};
- - struct cdrom_msf* msf = (struct cdrom_msf*)arg;
- -
- - cmd[3] = msf->cdmsf_min0;
- - cmd[4] = msf->cdmsf_sec0;
- - cmd[5] = msf->cdmsf_frame0;
- - cmd[6] = msf->cdmsf_min1;
- - cmd[7] = msf->cdmsf_sec1;
- - cmd[8] = msf->cdmsf_frame1;
- -
- - return (pcd_atapi(unit,cmd,0,NULL,"play msf")) * EIO;
- - }
- -
- - case CDROMPLAYBLK:
- -
- - { char cmd[12]={SCMD_PLAYAUDIO10,0,0,0,0,0,0,0,0,0,0,0};
- - struct cdrom_blk* blk = (struct cdrom_blk*)arg;
- -
- - cmd[2] = blk->from >> 24;
- - cmd[3] = blk->from >> 16;
- - cmd[4] = blk->from >> 8;
- - cmd[5] = blk->from;
- - cmd[7] = blk->len >> 8;
- - cmd[8] = blk->len;
- -
- - return (pcd_atapi(unit,cmd,0,NULL,"play block")) * EIO;
- - }
- -
- - case CDROMPLAYTRKIND:
- -
- - { char cmd[12]={SCMD_PLAYAUDIO_TI,0,0,0,0,0,0,0,0,0,0,0};
- - struct cdrom_ti* ti = (struct cdrom_ti*)arg;
- -
- - cmd[4] = ti->cdti_trk0;
- - cmd[5] = ti->cdti_ind0;
- - cmd[7] = ti->cdti_trk1;
- - cmd[8] = ti->cdti_ind1;
- -
- - return (pcd_atapi(unit,cmd,0,NULL,"play track")) * EIO;
- - }
- -
- case CDROMREADTOCHDR:
-
- - { char cmd[12]={SCMD_READ_TOC,0,0,0,0,0,0,0,12,0,0,0};
- + { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
- struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg;
- char buffer[32];
- int r;
- @@ -910,7 +899,7 @@
-
- case CDROMREADTOCENTRY:
-
- - { char cmd[12]={SCMD_READ_TOC,0,0,0,0,0,0,0,12,0,0,0};
- + { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
-
- struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg;
- unsigned char buffer[32];
- @@ -936,97 +925,6 @@
- return r * EIO;
- }
-
- - case CDROMSTOP:
- -
- - { char cmd[12]={0x1b,1,0,0,0,0,0,0,0,0,0,0};
- -
- - return (pcd_atapi(unit,cmd,0,NULL,"stop")) * EIO;
- - }
- -
- - case CDROMSTART:
- -
- - { char cmd[12]={0x1b,1,0,0,1,0,0,0,0,0,0,0};
- -
- - return (pcd_atapi(unit,cmd,0,NULL,"start")) * EIO;
- - }
- -
- - case CDROMVOLCTRL:
- -
- - { char cmd[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0};
- - char buffer[32];
- - char mask[32];
- - struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
- -
- - cmd[2] = 0xe;
- - cmd[4] = 28;
- -
- - if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol"))
- - return -EIO;
- -
- - cmd[2] = 0x4e;
- -
- - if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol mask"))
- - return -EIO;
- -
- - buffer[0] = 0;
- -
- - buffer[21] = volctrl->channel0 & mask[21];
- - buffer[23] = volctrl->channel1 & mask[23];
- - buffer[25] = volctrl->channel2 & mask[25];
- - buffer[27] = volctrl->channel3 & mask[27];
- -
- - cmd[0] = 0x55;
- - cmd[1] = 0x10;
- -
- - return pcd_atapi(unit,cmd,28,buffer,"mode select vol") * EIO;
- - }
- -
- - case CDROMVOLREAD:
- -
- - { char cmd[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0};
- - char buffer[32];
- - struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
- - int r;
- -
- - cmd[2] = 0xe;
- - cmd[4] = 28;
- -
- - r = pcd_atapi(unit,cmd,28,buffer,"mode sense vol read");
- -
- - volctrl->channel0 = buffer[21];
- - volctrl->channel1 = buffer[23];
- - volctrl->channel2 = buffer[25];
- - volctrl->channel3 = buffer[27];
- -
- - return r * EIO;
- - }
- -
- -
- - case CDROMSUBCHNL:
- -
- - { char cmd[12]={SCMD_READ_SUBCHANNEL,2,0x40,1,0,0,0,0,16,0,0,0};
- - struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg;
- - char buffer[32];
- -
- - if (pcd_atapi(unit,cmd,16,buffer,"read subchannel"))
- - return -EIO;
- -
- - subchnl->cdsc_audiostatus = buffer[1];
- - subchnl->cdsc_format = CDROM_MSF;
- - subchnl->cdsc_ctrl = buffer[5] & 0xf;
- - subchnl->cdsc_trk = buffer[6];
- - subchnl->cdsc_ind = buffer[7];
- -
- - subchnl->cdsc_reladdr.msf.minute = buffer[13];
- - subchnl->cdsc_reladdr.msf.second = buffer[14];
- - subchnl->cdsc_reladdr.msf.frame = buffer[15];
- - subchnl->cdsc_absaddr.msf.minute = buffer[9];
- - subchnl->cdsc_absaddr.msf.second = buffer[10];
- - subchnl->cdsc_absaddr.msf.frame = buffer[11];
- -
- - return 0;
- - }
- -
- default:
-
- return -ENOSYS;
- @@ -1035,7 +933,7 @@
-
- static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-
- -{ char cmd[12]={SCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0};
- +{ char cmd[12]={GPCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0};
- char buffer[32];
- int k;
- int unit = DEVICE_NR(cdi->dev);
- diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.2.13/drivers/block/pdc4030.c linux/drivers/block/pdc4030.c
- --- linux-2.2.13/drivers/block/pdc4030.c Tue Dec 29 20:24:57 1998
- +++ linux/drivers/block/pdc4030.c Sun Nov 7 15:22:28 1999
- @@ -239,7 +239,7 @@
- if(stat & DRQ_STAT)
- goto read_again;
- if(stat & BUSY_STAT) {
- - ide_set_handler (drive, &promise_read_intr, WAIT_CMD);
- + ide_set_handler (drive, &promise_read_intr, WAIT_CMD, NULL);
- return;
- }
- printk("Ah! promise read intr: sectors left !DRQ !BUSYn");
- @@ -258,7 +258,7 @@
-
- if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
- if (time_before(jiffies, hwgroup->poll_timeout)) {
- - ide_set_handler (drive, &promise_write_pollfunc, 1);
- + ide_set_handler (drive, &promise_write_pollfunc, 1, NULL);
- return; /* continue polling... */
- }
- printk("%s: write timed-out!n",drive->name);
- @@ -292,7 +292,7 @@
- if (rq->nr_sectors > 4) {
- ide_multwrite(drive, rq->nr_sectors - 4);
- hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- - ide_set_handler (drive, &promise_write_pollfunc, 1);
- + ide_set_handler (drive, &promise_write_pollfunc, 1, NULL);
- return;
- } else {
- ide_multwrite(drive, rq->nr_sectors);
- @@ -315,7 +315,7 @@
- byte stat;
-
- if (rq->cmd == READ) {
- - ide_set_handler(drive, &promise_read_intr, WAIT_CMD);
- + ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL);
- OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
- /* The card's behaviour is odd at this point. If the data is
- available, DRQ will be true, and no interrupt will be
- diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.2.13/drivers/block/trm290.c linux/drivers/block/trm290.c
- --- linux-2.2.13/drivers/block/trm290.c Sat Aug 8 02:56:09 1998
- +++ linux/drivers/block/trm290.c Sun Nov 7 15:22:45 1999
- @@ -193,7 +193,7 @@
- outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */
- if (drive->media != ide_disk)
- return 0;
- - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD);
- + ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
- OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
- return 0;
- case ide_dma_begin:
- diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.2.13/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
- --- linux-2.2.13/drivers/cdrom/cdrom.c Fri Nov 5 15:15:34 1999
- +++ linux/drivers/cdrom/cdrom.c Thu Nov 4 13:20:03 1999
- @@ -1,7 +1,7 @@
- /* linux/drivers/cdrom/cdrom.c.
- Copyright (c) 1996, 1997 David A. van Leeuwen.
- Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org>
- - Copyright (c) 1998, 1999 Jens Axboe
- + Copyright (c) 1998, 1999 Jens Axboe <axboe@image.dk>
-
- May be copied or modified under the terms of the GNU General Public
- License. See linux/COPYING for more information.
- @@ -22,12 +22,6 @@
- based tunable parameters such as whether the tray should auto-close for
- that drive. Suggestions (or patches) for this welcome!
-
- - -- Change the CDROMREADMODE1, CDROMREADMODE2, CDROMREADAUDIO, and
- - CDROMREADRAW ioctls so they go through the Uniform CD-ROM driver.
- -
- - -- Sync options and capability flags.
- -
- -
-
- Revision History
- ----------------------------------
- @@ -126,14 +120,77 @@
- CDC_CLOSE_TRAY.
- -- proc info didn't mask against capabilities mask.
-
- - 2.56 Sep 9, 1999 - Jens Axboe <axboe@image.dk>
- - -- Define CDROM_CAN() for checking capabilities.
- - -- Fix up capability reporting, for proc and ioctl.
- -
- + 3.00 Aug 5, 1999 - Jens Axboe <axboe@image.dk>
- + -- Unified audio ioctl handling across CD-ROM drivers. A lot of the
- + code was duplicated before. Drives that support the generic packet
- + interface are now being fed packets from here instead.
- + -- First attempt at adding support for MMC2 commands - for DVD and
- + CD-R(W) drives. Only the DVD parts are in now - the interface used is
- + the same as for the audio ioctls.
- + -- ioctl cleanups. if a drive couldn't play audio, it didn't get
- + a change to perform device specific ioctls as well.
- + -- Defined CDROM_CAN(CDC_XXX) for checking the capabilities.
- + -- Put in sysctl files for autoclose, autoeject, check_media, debug,
- + and lock.
- + -- /proc/sys/dev/cdrom/info has been updated to also contain info about
- + CD-Rx and DVD capabilities.
- + -- Now default to checking media type.
- + -- CDROM_SEND_PACKET ioctl added. The infrastructure was in place for
- + doing this anyway, with the generic_packet addition.
- +
- + 3.01 Aug 6, 1999 - Jens Axboe <axboe@image.dk>
- + -- Fix up the sysctl handling so that the option flags get set
- + correctly.
- + -- Fix up ioctl handling so the device specific ones actually get
- + called :).
- +
- + 3.02 Aug 8, 1999 - Jens Axboe <axboe@image.dk>
- + -- Fixed volume control on SCSI drives (or others with longer audio
- + page).
- + -- Fixed a couple of DVD minors. Thanks to Andrew T. Veliath
- + <andrewtv@usa.net> for telling me and for having defined the various
- + DVD structures and ioctls in the first place! He designed the original
- + DVD patches for ide-cd and while I rearranged and unified them, the
- + interface is still the same.
- +
- + 3.03 Sep 1, 1999 - Jens Axboe <axboe@image.dk>
- + -- Moved the rest of the audio ioctls from the CD-ROM drivers here. Only
- + CDROMREADTOCENTRY and CDROMREADTOCHDR are left.
- + -- Moved the CDROMREADxxx ioctls in here.
- + -- Defined the cdrom_get_last_written and cdrom_get_next_block as ioctls
- + and exported functions.
- + -- Erik Andersen <andersen@xmission.com> modified all SCMD_ commands
- + to now read GPCMD_ for the new generic packet interface. All low level
- + drivers are updated as well.
- + -- Various other cleanups.
- +
- + 3.04 Sep 12, 1999 - Jens Axboe <axboe@image.dk>
- + -- Fixed a couple of possible memory leaks (if an operation failed and
- + we didn't free the buffer before returning the error).
- + -- Integrated Uniform CD Changer handling from Richard Sharman
- + <rsharman@pobox.com>.
- + -- Defined CD_DVD and CD_CHANGER log levels.
- + -- Fixed the CDROMREADxxx ioctls.
- + -- CDROMPLAYTRKIND uses the GPCMD_PLAY_AUDIO_MSF command - too few
- + drives supported it. We loose the index part, however.
- + -- Small modifications to accomodate opens of /dev/hdc1, required
- + for ide-cd to handle multisession discs.
- + -- Export cdrom_mode_sense and cdrom_mode_select.
- + -- init_cdrom_command() for setting up a cgc command.
- +
- + 3.05 Oct 24, 1999 - Jens Axboe <axboe@image.dk>
- + -- Changed the interface for CDROM_SEND_PACKET. Before it was virtually
- + impossible to send the drive data in a sensible way.
- + -- Lowered stack usage in mmc_ioctl(), dvd_read_disckey(), and
- + dvd_read_manufact.
- + -- Added setup of write mode for packet writing.
- + -- Fixed CDDA ripping with cdda2wav - accept much larger requests of
- + number of frames and split the reads in blocks of 8.
- +
- -------------------------------------------------------------------------*/
-
- -#define REVISION "Revision: 2.56"
- -#define VERSION "Id: cdrom.c 2.56 1999/09/09"
- +#define REVISION "Revision: 3.05"
- +#define VERSION "Id: cdrom.c 3.05 1999/10/24"
-
- /* I use an error-log mask to give fine grain control over the type of
- messages dumped to the system logs. The available masks include: */
- @@ -144,6 +201,8 @@
- #define CD_OPEN 0x8
- #define CD_CLOSE 0x10
- #define CD_COUNT_TRACKS 0x20
- +#define CD_CHANGER 0x40
- +#define CD_DVD 0x80
-
- /* Define this to remove _all_ the debugging messages */
- /* #define ERRLOGMASK CD_NOTHING */
- @@ -151,7 +210,6 @@
- /* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
- /* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */
-
- -
- #include <linux/config.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- @@ -164,6 +222,7 @@
- #include <linux/cdrom.h>
- #include <linux/sysctl.h>
- #include <linux/proc_fs.h>
- +#include <linux/init.h>
- #include <asm/fcntl.h>
- #include <asm/segment.h>
- #include <asm/uaccess.h>
- @@ -176,6 +235,7 @@
- static int autoclose=1;
- static int autoeject=0;
- static int lockdoor = 1;
- +/* will we ever get to use this... sigh. */
- static int check_media_type = 0;
- MODULE_PARM(debug, "i");
- MODULE_PARM(autoclose, "i");
- @@ -202,7 +262,8 @@
- a lot of places. This macro makes the code more clear. */
- #define CDROM_CAN(type) (cdi->ops->capability & ~cdi->mask & type)
-
- -#define FM_WRITE 0x2 /* file mode write bit */
- +/* used in the audio ioctls */
- +#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret
-
- /* Not-exported routines. */
- static int cdrom_open(struct inode *ip, struct file *fp);
- @@ -215,6 +276,12 @@
- struct cdrom_device_ops * cdo);
- static void sanitize_format(union cdrom_addr *addr,
- u_char * curr, u_char requested);
- +static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- + unsigned long arg);
- +
- +int cdrom_get_last_written(kdev_t dev, long *last_written);
- +int cdrom_get_next_writable(kdev_t dev, long *next_writable);
- +
- #ifdef CONFIG_SYSCTL
- static void cdrom_sysctl_register(void);
- #endif /* CONFIG_SYSCTL */
- @@ -248,7 +315,7 @@
- int register_cdrom(struct cdrom_device_info *cdi)
- {
- static char banner_printed = 0;
- - int major = MAJOR (cdi->dev);
- + int major = MAJOR(cdi->dev);
- struct cdrom_device_ops *cdo = cdi->ops;
- int *change_capability = (int *)&cdo->capability; /* hack */
-
- @@ -259,7 +326,7 @@
- if (cdo->open == NULL || cdo->release == NULL)
- return -2;
- if ( !banner_printed ) {
- - printk(KERN_INFO "Uniform CDROM driver " REVISION "n");
- + printk(KERN_INFO "Uniform CD-ROM driver " REVISION "n");
- banner_printed = 1;
- #ifdef CONFIG_SYSCTL
- cdrom_sysctl_register();
- @@ -270,12 +337,12 @@
- ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY);
- ENSURE(lock_door, CDC_LOCK);
- ENSURE(select_speed, CDC_SELECT_SPEED);
- - ENSURE(select_disc, CDC_SELECT_DISC);
- ENSURE(get_last_session, CDC_MULTI_SESSION);
- ENSURE(get_mcn, CDC_MCN);
- ENSURE(reset, CDC_RESET);
- ENSURE(audio_ioctl, CDC_PLAY_AUDIO);
- ENSURE(dev_ioctl, CDC_IOCTLS);
- + ENSURE(generic_packet, CDC_GENERIC_PACKET);
- cdi->mc_flags = 0;
- cdo->n_minors = 0;
- cdi->options = CDO_USE_FFLAGS;
- @@ -299,7 +366,7 @@
- int unregister_cdrom(struct cdrom_device_info *unreg)
- {
- struct cdrom_device_info *cdi, *prev;
- - int major = MAJOR (unreg->dev);
- + int major = MAJOR(unreg->dev);
-
- cdinfo(CD_OPEN, "entering unregister_cdromn");
-
- @@ -325,16 +392,30 @@
- }
-
- static
- -struct cdrom_device_info *cdrom_find_device (kdev_t dev)
- +struct cdrom_device_info *cdrom_find_device(kdev_t dev)
- {
- struct cdrom_device_info *cdi;
-
- cdi = topCdromPtr;
- while (cdi != NULL && cdi->dev != dev)
- cdi = cdi->next;
- +
- + /* we need to find the device this way when IDE devices such
- + * as /dev/hdc2 are opened. SCSI drives will be found above and
- + * so will /dev/hdc, for instance.
- + */
- + if (cdi == NULL) {
- + kdev_t cd_dev = MKDEV(MAJOR(dev), MINOR(dev) | CD_PART_MASK);
- + cdi = topCdromPtr;
- + while (cdi != NULL && cdi->dev != cd_dev)
- + cdi = cdi->next;
- + }
- +
- return cdi;
- }
-
- +static int cdrom_setup_writemode(struct cdrom_device_info *cdi);
- +
- /* We use the open-option O_NONBLOCK to indicate that the
- * purpose of opening is only for subsequent ioctl() calls; no device
- * integrity checks are performed.
- @@ -346,22 +427,31 @@
- static
- int cdrom_open(struct inode *ip, struct file *fp)
- {
- + struct cdrom_device_info *cdi;
- kdev_t dev = ip->i_rdev;
- - struct cdrom_device_info *cdi = cdrom_find_device(dev);
- - int purpose = !!(fp->f_flags & O_NONBLOCK);
- - int ret=0;
- + int ret;
-
- cdinfo(CD_OPEN, "entering cdrom_openn");
- - if (cdi == NULL)
- + if ((cdi = cdrom_find_device(dev)) == NULL)
- return -ENODEV;
- - if (fp->f_mode & FM_WRITE)
- - return -EROFS;
- - purpose = purpose || !(cdi->options & CDO_USE_FFLAGS);
- - if (purpose)
- - ret = cdi->ops->open(cdi, purpose);
- +
- + /* just CD-RW for now. DVD-RW will come soon, CD-R and DVD-R
- + * need to be handled differently. */
- + if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_CD_RW))
- + return -EROFS;
- +
- + /* if this was a O_NONBLOCK open and we should honor the flags,
- + * do a quick open without drive/disc integrity checks. */
- + if ((fp->f_flags & O_NONBLOCK) && (cdi->options & CDO_USE_FFLAGS))
- + ret = cdi->ops->open(cdi, 1);
- else
- ret = open_for_data(cdi);
- +
- if (!ret) cdi->use_count++;
- +
- + if (fp->f_mode & FMODE_WRITE && !cdi->write.writeable)
- + cdi->write.writeable = !cdrom_setup_writemode(cdi);
- +
- cdinfo(CD_OPEN, "Use count for "/dev/%s" now %dn", cdi->name, cdi->use_count);
- /* Do this on open. Don't wait for mount, because they might
- not be mounting, but opening with O_NONBLOCK */
- @@ -428,7 +518,11 @@
- * for example, need bit CDO_CHECK_TYPE cleared! */
- if (tracks.data==0) {
- if (cdi->options & CDO_CHECK_TYPE) {
- + /* give people a warning shot, now that CDO_CHECK_TYPE
- + is the default case! */
- cdinfo(CD_OPEN, "bummer. wrong media type.n");
- + cdinfo(CD_WARNING, "pid %d must open device O_NONBLOCK!n",
- + (unsigned int)current->pid);
- ret=-EMEDIUMTYPE;
- goto clean_up_and_return;
- }
- @@ -452,7 +546,7 @@
- if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
- cdo->lock_door(cdi, 1);
- cdinfo(CD_OPEN, "door locked.n");
- - }
- + }
- cdinfo(CD_OPEN, "device opened successfully.n");
- return ret;
-
- @@ -533,7 +627,7 @@
- int cdrom_release(struct inode *ip, struct file *fp)
- {
- kdev_t dev = ip->i_rdev;
- - struct cdrom_device_info *cdi = cdrom_find_device (dev);
- + struct cdrom_device_info *cdi = cdrom_find_device(dev);
- struct cdrom_device_ops *cdo = cdi->ops;
- int opened_for_data;
-
- @@ -543,7 +637,7 @@
- if (cdi->use_count > 0) cdi->use_count--;
- if (cdi->use_count == 0)
- cdinfo(CD_CLOSE, "Use count for "/dev/%s" now zeron", cdi->name);
- - if (cdi->use_count == 0 && /* last process that closes dev*/
- + if (cdi->use_count == 0 &&
- cdo->capability & CDC_LOCK && !keeplocked) {
- cdinfo(CD_CLOSE, "Unlocking door!n");
- cdo->lock_door(cdi, 0);
- @@ -557,13 +651,140 @@
- sb = get_super(dev);
- if (sb) invalidate_inodes(sb);
- invalidate_buffers(dev);
- - if (opened_for_data && (cdi->options & CDO_AUTO_EJECT) &&
- - CDROM_CAN(CDC_OPEN_TRAY))
- + if (opened_for_data &&
- + cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY))
- cdo->tray_move(cdi, 1);
- }
- return 0;
- }
-
- +static int cdrom_read_mech_status(struct cdrom_device_info *cdi,
- + struct cdrom_changer_info *buf)
- +{
- + struct cdrom_generic_command cgc;
- + struct cdrom_device_ops *cdo = cdi->ops;
- + int length;
- +
- + length = sizeof(struct cdrom_mechstat_header) +
- + cdi->capacity * sizeof(struct cdrom_slot);
- +
- + init_cdrom_command(&cgc, buf, length);
- + cgc.cmd[0] = GPCMD_MECHANISM_STATUS;
- + cgc.cmd[8] = (length >> 8) & 0xff;
- + cgc.cmd[9] = length & 0xff;
- + return cdo->generic_packet(cdi, &cgc);
- +}
- +
- +static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot)
- +{
- + struct cdrom_changer_info info;
- + int ret;
- +
- + cdinfo(CD_CHANGER, "entering cdrom_slot_status()n");
- + if (cdi->sanyo_slot)
- + return CDS_NO_INFO;
- +
- + if ((ret = cdrom_read_mech_status(cdi, &info)))
- + return ret;
- +
- + if (info.slots[slot].disc_present)
- + return CDS_DISC_OK;
- + else
- + return CDS_NO_DISC;
- +
- +}
- +
- +/* Return the number of slots for an ATAPI/SCSI cdrom,
- + * return 1 if not a changer.
- + */
- +int cdrom_number_of_slots(struct cdrom_device_info *cdi)
- +{
- + int status;
- + int nslots = 1;
- + struct cdrom_changer_info info;
- +
- + cdinfo(CD_CHANGER, "entering cdrom_number_of_slots()n");
- + /* cdrom_read_mech_status requires a valid value for capacity: */
- + cdi->capacity = 0;
- +
- + if ((status = cdrom_read_mech_status(cdi, &info)) == 0)
- + nslots = info.hdr.nslots;
- +
- + return nslots;
- +}
- +
- +
- +/* If SLOT < 0, unload the current slot. Otherwise, try to load SLOT. */
- +static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot)
- +{
- + struct cdrom_generic_command cgc;
- +
- + cdinfo(CD_CHANGER, "entering cdrom_load_unload()n");
- + if (cdi->sanyo_slot && slot < 0)
- + return 0;
- +
- + init_cdrom_command(&cgc, NULL, 0);
- + cgc.cmd[0] = GPCMD_LOAD_UNLOAD;
- + cgc.cmd[4] = 2 + (slot >= 0);
- + cgc.cmd[8] = slot;
- +
- + /* The Sanyo 3 CD changer uses byte 7 of the
- + GPCMD_TEST_UNIT_READY to command to switch CDs instead of
- + using the GPCMD_LOAD_UNLOAD opcode. */
- + if (cdi->sanyo_slot && slot) {
- + cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
- + cgc.cmd[7] = slot;
- + cdi->sanyo_slot = slot ? slot : 3;
- + }
- +
- + return cdi->ops->generic_packet(cdi, &cgc);
- +}
- +
- +int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
- +{
- + struct cdrom_changer_info info;
- + int curslot;
- + int ret;
- +
- + cdinfo(CD_CHANGER, "entering cdrom_select_disc()n");
- + if (!CDROM_CAN(CDC_SELECT_DISC))
- + return -EDRIVE_CANT_DO_THIS;
- +
- + if (slot == CDSL_NONE) {
- + /* set media changed bits, on both queues */
- + cdi->mc_flags = 0x3;
- + return cdrom_load_unload(cdi, -1);
- + }
- +
- + if ((ret = cdrom_read_mech_status(cdi, &info)))
- + return ret;
- +
- + curslot = info.hdr.curslot;
- +
- + if (cdi->use_count > 1 || keeplocked) {
- + if (slot == CDSL_CURRENT) {
- + return curslot;
- + } else {
- + return -EBUSY;
- + }
- + }
- +
- + /* Specifying CDSL_CURRENT will attempt to load the currnet slot,
- + which is useful if it had been previously unloaded.
- + Whether it can or not, it returns the current slot.
- + Similarly, if slot happens to be the current one, we still
- + try and load it. */
- + if (slot == CDSL_CURRENT)
- + slot = curslot;
- +
- + /* set media changed bits on both queues */
- + cdi->mc_flags = 0x3;
- + if ((ret = cdrom_load_unload(cdi, slot)))
- + return ret;
- +
- + return slot;
- +}
- +
- /* We want to make media_changed accessible to the user through an
- * ioctl. The main problem now is that we must double-buffer the
- * low-level implementation, to assure that the VFS and the user both
- @@ -590,7 +811,7 @@
- static
- int cdrom_media_changed(kdev_t dev)
- {
- - struct cdrom_device_info *cdi = cdrom_find_device (dev);
- + struct cdrom_device_info *cdi = cdrom_find_device(dev);
- /* This talks to the VFS, which doesn't like errors - just 1 or 0.
- * Returning "0" is always safe (media hasn't been changed). Do that
- * if the low-level cdrom driver dosn't support media changed. */
- @@ -614,7 +835,7 @@
- tracks->xa=0;
- tracks->error=0;
- cdinfo(CD_COUNT_TRACKS, "entering cdrom_count_tracksn");
- - if (!(cdi->ops->capability & ~cdi->mask & CDC_PLAY_AUDIO)) {
- + if (!CDROM_CAN(CDC_PLAY_AUDIO)) {
- tracks->error=CDS_NO_INFO;
- return;
- }
- @@ -688,6 +909,450 @@
- *curr = requested;
- }
-
- +void init_cdrom_command(struct cdrom_generic_command *cgc,
- + void *buffer, int len)
- +{
- + memset(cgc, 0, sizeof(struct cdrom_generic_command));
- + memset(buffer, 0, len);
- + cgc->buffer = (char *) buffer;
- + cgc->buflen = len;
- +}
- +
- +/* DVD handling */
- +
- +#define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key))
- +#define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge))
- +
- +static void setup_report_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
- +{
- + cgc->cmd[0] = GPCMD_REPORT_KEY;
- + cgc->cmd[10] = type | (agid << 6);
- + switch (type) {
- + case 0: case 8: case 5: {
- + cgc->buflen = 8;
- + break;
- + }
- + case 1: {
- + cgc->buflen = 16;
- + break;
- + }
- + case 2: case 4: {
- + cgc->buflen = 12;
- + break;
- + }
- + }
- + cgc->cmd[9] = cgc->buflen;
- +}
- +
- +static void setup_send_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
- +{
- + cgc->cmd[0] = GPCMD_SEND_KEY;
- + cgc->cmd[10] = type | (agid << 6);
- + switch (type) {
- + case 1: {
- + cgc->buflen = 16;
- + break;
- + }
- + case 3: {
- + cgc->buflen = 12;
- + break;
- + }
- + case 6: {
- + cgc->buflen = 8;
- + break;
- + }
- + }
- + cgc->cmd[9] = cgc->buflen;
- +}
- +
- +static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
- +{
- + int ret;
- + u_char buf[20];
- + struct cdrom_generic_command cgc;
- + struct cdrom_device_ops *cdo = cdi->ops;
- +
- + init_cdrom_command(&cgc, buf, 0);
- +
- + switch (ai->type) {
- + /* LU data send */
- + case DVD_LU_SEND_AGID:
- + cdinfo(CD_DVD, "entering DVD_LU_SEND_AGIDn");
- + setup_report_key(&cgc, ai->lsa.agid, 0);
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + ai->lsa.agid = buf[7] >> 6;
- + /* Returning data, let host change state */
- + break;
- +
- + case DVD_LU_SEND_KEY1:
- + cdinfo(CD_DVD, "entering DVD_LU_SEND_KEY1n");
- + setup_report_key(&cgc, ai->lsk.agid, 2);
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + copy_key(ai->lsk.key, &buf[4]);
- + /* Returning data, let host change state */
- + break;
- +
- + case DVD_LU_SEND_CHALLENGE:
- + cdinfo(CD_DVD, "entering DVD_LU_SEND_CHALLENGEn");
- + setup_report_key(&cgc, ai->lsc.agid, 1);
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + copy_chal(ai->lsc.chal, &buf[4]);
- + /* Returning data, let host change state */
- + break;
- +
- + /* Post-auth key */
- + case DVD_LU_SEND_TITLE_KEY:
- + cdinfo(CD_DVD, "entering DVD_LU_SEND_TITLE_KEYn");
- + setup_report_key(&cgc, ai->lstk.agid, 4);
- + cgc.cmd[5] = ai->lstk.lba;
- + cgc.cmd[4] = ai->lstk.lba >> 8;
- + cgc.cmd[3] = ai->lstk.lba >> 16;
- + cgc.cmd[2] = ai->lstk.lba >> 24;
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + ai->lstk.cpm = (buf[4] >> 7) & 1;
- + ai->lstk.cp_sec = (buf[4] >> 6) & 1;
- + ai->lstk.cgms = (buf[4] >> 4) & 3;
- + copy_key(ai->lstk.title_key, &buf[5]);
- + /* Returning data, let host change state */
- + break;
- +
- + case DVD_LU_SEND_ASF:
- + cdinfo(CD_DVD, "entering DVD_LU_SEND_ASFn");
- + setup_report_key(&cgc, ai->lsasf.asf, 5);
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + ai->lsasf.asf = buf[7] & 1;
- + break;
- +
- + /* LU data receive (LU changes state) */
- + case DVD_HOST_SEND_CHALLENGE:
- + cdinfo(CD_DVD, "entering DVD_HOST_SEND_CHALLENGEn");
- + setup_send_key(&cgc, ai->hsc.agid, 1);
- + buf[1] = 0xe;
- + copy_chal(&buf[4], ai->hsc.chal);
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + ai->type = DVD_LU_SEND_KEY1;
- + break;
- +
- + case DVD_HOST_SEND_KEY2:
- + cdinfo(CD_DVD, "entering DVD_HOST_SEND_KEY2n");
- + setup_send_key(&cgc, ai->hsk.agid, 3);
- + buf[1] = 0xa;
- + copy_key(&buf[4], ai->hsk.key);
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc))) {
- + ai->type = DVD_AUTH_FAILURE;
- + return ret;
- + }
- + ai->type = DVD_AUTH_ESTABLISHED;
- + break;
- +
- + /* Misc */
- + case DVD_INVALIDATE_AGID:
- + cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGIDn");
- + setup_report_key(&cgc, ai->lsa.agid, 0x3f);
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- + break;
- +
- + default:
- + cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)n", ai->type);
- + return -ENOTTY;
- + }
- +
- + return 0;
- +}
- +
- +static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
- +{
- + int ret, i;
- + u_char buf[4 + 4 * 20], *base;
- + struct dvd_layer *layer;
- + struct cdrom_generic_command cgc;
- + struct cdrom_device_ops *cdo = cdi->ops;
- +
- + init_cdrom_command(&cgc, buf, sizeof(buf));
- + cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
- + cgc.cmd[6] = s->physical.layer_num;
- + cgc.cmd[7] = s->type;
- + cgc.cmd[9] = cgc.buflen & 0xff;
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + base = &buf[4];
- + layer = &s->physical.layer[0];
- +
- + /* place the data... really ugly, but at least we won't have to
- + worry about endianess in userspace or here. */
- + for (i = 0; i < 4; ++i, base += 20, ++layer) {
- + memset(layer, 0, sizeof(*layer));
- + layer->book_version = base[0] & 0xf;
- + layer->book_type = base[0] >> 4;
- + layer->min_rate = base[1] & 0xf;
- + layer->disc_size = base[1] >> 4;
- + layer->layer_type = base[2] & 0xf;
- + layer->track_path = (base[2] >> 4) & 1;
- + layer->nlayers = (base[2] >> 5) & 3;
- + layer->track_density = base[3] & 0xf;
- + layer->linear_density = base[3] >> 4;
- + layer->start_sector = base[5] << 16 | base[6] << 8 | base[7];
- + layer->end_sector = base[9] << 16 | base[10] << 8 | base[11];
- + layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
- + layer->bca = base[16] >> 7;
- + }
- +
- + return 0;
- +}
- +
- +static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
- +{
- + int ret;
- + u_char buf[8];
- + struct cdrom_generic_command cgc;
- + struct cdrom_device_ops *cdo = cdi->ops;
- +
- + init_cdrom_command(&cgc, buf, sizeof(buf));
- + cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
- + cgc.cmd[6] = s->copyright.layer_num;
- + cgc.cmd[7] = s->type;
- + cgc.cmd[8] = cgc.buflen >> 8;
- + cgc.cmd[9] = cgc.buflen & 0xff;
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + s->copyright.cpst = buf[4];
- + s->copyright.rmi = buf[5];
- +
- + return 0;
- +}
- +
- +static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
- +{
- + int ret, size;
- + u_char *buf;
- + struct cdrom_generic_command cgc;
- + struct cdrom_device_ops *cdo = cdi->ops;
- +
- + size = sizeof(s->disckey.value) + 4;
- +
- + if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
- + return -ENOMEM;
- +
- + init_cdrom_command(&cgc, buf, size);
- + cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
- + cgc.cmd[7] = s->type;
- + cgc.cmd[8] = size >> 8;
- + cgc.cmd[9] = size & 0xff;
- + cgc.cmd[10] = s->disckey.agid << 6;
- +
- + if (!(ret = cdo->generic_packet(cdi, &cgc)))
- + memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value));
- +
- + kfree(buf);
- + return ret;
- +}
- +
- +static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
- +{
- + int ret;
- + u_char buf[4 + 188];
- + struct cdrom_generic_command cgc;
- + struct cdrom_device_ops *cdo = cdi->ops;
- +
- + init_cdrom_command(&cgc, buf, sizeof(buf));
- + cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
- + cgc.cmd[7] = s->type;
- + cgc.cmd[9] = cgc.buflen = 0xff;
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + s->bca.len = buf[0] << 8 | buf[1];
- + if (s->bca.len < 12 || s->bca.len > 188) {
- + cdinfo(CD_WARNING, "Received invalid BCA length (%d)n", s->bca.len);
- + return -EIO;
- + }
- + memcpy(s->bca.value, &buf[4], s->bca.len);
- +
- + return 0;
- +}
- +
- +static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
- +{
- + int ret = 0, size;
- + u_char *buf;
- + struct cdrom_generic_command cgc;
- + struct cdrom_device_ops *cdo = cdi->ops;
- +
- + size = sizeof(s->manufact.value) + 4;
- +
- + if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
- + return -ENOMEM;
- +
- + init_cdrom_command(&cgc, buf, size);
- + cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
- + cgc.cmd[7] = s->type;
- + cgc.cmd[8] = size >> 8;
- + cgc.cmd[9] = size & 0xff;
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc))) {
- + kfree(buf);
- + return ret;
- + }
- +
- + s->manufact.len = buf[0] << 8 | buf[1];
- + if (s->manufact.len < 0 || s->manufact.len > 2048) {
- + cdinfo(CD_WARNING, "Received invalid manufacture info length"
- + " (%d)n", s->bca.len);
- + ret = -EIO;
- + } else {
- + memcpy(s->manufact.value, &buf[4], s->manufact.len);
- + }
- +
- + kfree(buf);
- + return ret;
- +}
- +
- +static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s)
- +{
- + switch (s->type) {
- + case DVD_STRUCT_PHYSICAL:
- + return dvd_read_physical(cdi, s);
- +
- + case DVD_STRUCT_COPYRIGHT:
- + return dvd_read_copyright(cdi, s);
- +
- + case DVD_STRUCT_DISCKEY:
- + return dvd_read_disckey(cdi, s);
- +
- + case DVD_STRUCT_BCA:
- + return dvd_read_bca(cdi, s);
- +
- + case DVD_STRUCT_MANUFACT:
- + return dvd_read_manufact(cdi, s);
- +
- + default:
- + cdinfo(CD_WARNING, ": Invalid DVD structure read requested (%d)n",
- + s->type);
- + return -EINVAL;
- + }
- +}
- +
- +int cdrom_mode_sense(struct cdrom_device_info *cdi,
- + struct cdrom_generic_command *cgc,
- + int page_code, int page_control)
- +{
- + struct cdrom_device_ops *cdo = cdi->ops;
- +
- + memset(cgc->cmd, 0, sizeof(cgc->cmd));
- +
- + cgc->cmd[0] = GPCMD_MODE_SENSE_10;
- + cgc->cmd[2] = page_code | (page_control << 6);
- + cgc->cmd[7] = cgc->buflen >> 8;
- + cgc->cmd[8] = cgc->buflen & 0xff;
- + return cdo->generic_packet(cdi, cgc);
- +}
- +
- +int cdrom_mode_select(struct cdrom_device_info *cdi,
- + struct cdrom_generic_command *cgc)
- +{
- + struct cdrom_device_ops *cdo = cdi->ops;
- +
- + memset(cgc->cmd, 0, sizeof(cgc->cmd));
- +
- + cgc->cmd[0] = GPCMD_MODE_SELECT_10;
- + cgc->cmd[1] = 0x10; /* PF */
- + cgc->cmd[7] = cgc->buflen >> 8;
- + cgc->cmd[8] = cgc->buflen & 0xff;
- + return cdo->generic_packet(cdi, cgc);
- +}
- +
- +static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
- + struct cdrom_subchnl *subchnl, int mcn)
- +{
- + struct cdrom_device_ops *cdo = cdi->ops;
- + struct cdrom_generic_command cgc;
- + char buffer[32];
- + int ret;
- +
- + init_cdrom_command(&cgc, buffer, 16);
- + cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
- + cgc.cmd[1] = 2; /* MSF addressing */
- + cgc.cmd[2] = 0x40; /* request subQ data */
- + cgc.cmd[3] = mcn ? 2 : 1;
- + cgc.cmd[8] = 16;
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + subchnl->cdsc_audiostatus = cgc.buffer[1];
- + subchnl->cdsc_format = CDROM_MSF;
- + subchnl->cdsc_ctrl = cgc.buffer[5] & 0xf;
- + subchnl->cdsc_trk = cgc.buffer[6];
- + subchnl->cdsc_ind = cgc.buffer[7];
- +
- + subchnl->cdsc_reladdr.msf.minute = cgc.buffer[13];
- + subchnl->cdsc_reladdr.msf.second = cgc.buffer[14];
- + subchnl->cdsc_reladdr.msf.frame = cgc.buffer[15];
- + subchnl->cdsc_absaddr.msf.minute = cgc.buffer[9];
- + subchnl->cdsc_absaddr.msf.second = cgc.buffer[10];
- + subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11];
- +
- + return 0;
- +}
- +
- +/* very generic interface for reading the various types of blocks */
- +static int cdrom_read_block(struct cdrom_device_info *cdi,
- + struct cdrom_generic_command *cgc,
- + int lba, int nblocks, int format, int blksize)
- +{
- + struct cdrom_device_ops *cdo = cdi->ops;
- +
- + memset(&cgc->cmd, 0, sizeof(cgc->cmd));
- + cgc->cmd[0] = GPCMD_READ_CD;
- + /* expected sector size - cdda,mode1,etc. */
- + cgc->cmd[1] = format << 2;
- + /* starting address */
- + cgc->cmd[2] = (lba >> 24) & 0xff;
- + cgc->cmd[3] = (lba >> 16) & 0xff;
- + cgc->cmd[4] = (lba >> 8) & 0xff;
- + cgc->cmd[5] = lba & 0xff;
- + /* number of blocks */
- + cgc->cmd[6] = (nblocks >> 16) & 0xff;
- + cgc->cmd[7] = (nblocks >> 8) & 0xff;
- + cgc->cmd[8] = nblocks & 0xff;
- + cgc->buflen = blksize * nblocks;
- +
- + /* set the header info returned */
- + switch (blksize) {
- + case CD_FRAMESIZE_RAW0 : cgc->cmd[9] = 0x58; break;
- + case CD_FRAMESIZE_RAW1 : cgc->cmd[9] = 0x78; break;
- + case CD_FRAMESIZE_RAW : cgc->cmd[9] = 0xf8; break;
- + default : cgc->cmd[9] = 0x10;
- + }
- +
- + return cdo->generic_packet(cdi, cgc);
- +}
- +
- /* Some of the cdrom ioctls are not implemented here, because these
- * appear to be either too device-specific, or it is not clear to me
- * what use they are. These are (number of drivers that support them
- @@ -706,8 +1371,9 @@
- unsigned int cmd, unsigned long arg)
- {
- kdev_t dev = ip->i_rdev;
- - struct cdrom_device_info *cdi = cdrom_find_device (dev);
- + struct cdrom_device_info *cdi = cdrom_find_device(dev);
- struct cdrom_device_ops *cdo;
- + int ret;
-
- if (cdi == NULL)
- return -ENODEV;
- @@ -719,7 +1385,6 @@
- /* maybe we should order cases after statistics of use? */
-
- case CDROMMULTISESSION: {
- - int ret;
- struct cdrom_multisession ms_info;
- u_char requested_format;
- cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSIONn");
- @@ -741,7 +1406,6 @@
- }
-
- case CDROMEJECT: {
- - int ret;
- cdinfo(CD_DO_IOCTL, "entering CDROMEJECTn");
- if (!CDROM_CAN(CDC_OPEN_TRAY))
- return -ENOSYS;
- @@ -774,16 +1438,22 @@
- }
-
- case CDROM_MEDIA_CHANGED: {
- + struct cdrom_changer_info info;
- +
- cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGEDn");
- if (!CDROM_CAN(CDC_MEDIA_CHANGED))
- return -ENOSYS;
- - if (!CDROM_CAN(CDC_SELECT_DISC)
- - || arg == CDSL_CURRENT)
- + if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT)
- /* cannot select disc or select current disc */
- return media_changed(cdi, 1);
- - if ((unsigned int)arg >= cdi->capacity)
- + if ((unsigned int)arg >= cdi->capacity) {
- return -EINVAL;
- - return cdo->media_changed (cdi, arg);
- + }
- +
- + if ((ret = cdrom_read_mech_status(cdi, &info)))
- + return ret;
- +
- + return info.slots[arg].change;
- }
-
- case CDROM_SET_OPTIONS: {
- @@ -824,16 +1494,29 @@
-
- case CDROM_SELECT_DISC: {
- cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISCn");
- - if (!(cdo->capability & ~cdi->mask & CDC_SELECT_DISC))
- + if (!CDROM_CAN(CDC_SELECT_DISC))
- return -ENOSYS;
- - if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE))
- +
- + if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE)) {
- + if ((int)arg >= cdi->capacity)
- + return -EINVAL;
- + }
- + /* cdo->select_disc is a hook to allow a driver-specific
- + * way of seleting disc. However, since there is no
- + * equiv hook for cdrom_slot_status this may not
- + * actually be useful...
- + */
- + if (cdo->select_disc != NULL)
- return cdo->select_disc(cdi, arg);
- - if ((int)arg >= cdi->capacity)
- - return -EDRIVE_CANT_DO_THIS;
- - return cdo->select_disc(cdi, arg);
- +
- + /* no driver specific select_disc(), call our own */
- + cdinfo(CD_CHANGER, "Using generic cdrom_select_disc()n");
- + return cdrom_select_disc(cdi, arg);
- }
-
- case CDROMRESET: {
- + if (!capable(CAP_SYS_ADMIN))
- + return -EACCES;
- cdinfo(CD_DO_IOCTL, "entering CDROM_RESETn");
- if (!CDROM_CAN(CDC_RESET))
- return -ENOSYS;
- @@ -841,19 +1524,17 @@
- }
-
- case CDROM_LOCKDOOR: {
- - cdinfo(CD_DO_IOCTL, "%socking door.n",arg?"L":"Unl");
- - if (!CDROM_CAN(CDC_LOCK)) {
- + cdinfo(CD_DO_IOCTL, "%socking door.n", arg ? "L" : "Unl");
- + if (!CDROM_CAN(CDC_LOCK))
- return -EDRIVE_CANT_DO_THIS;
- - } else {
- - keeplocked = arg ? 1 : 0;
- - return cdo->lock_door(cdi, arg);
- - }
- + keeplocked = arg ? 1 : 0;
- + return cdo->lock_door(cdi, arg);
- }
-
- case CDROM_DEBUG: {
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- - cdinfo(CD_DO_IOCTL, "%sabling debug.n",arg?"En":"Dis");
- + cdinfo(CD_DO_IOCTL, "%sabling debug.n", arg ? "En" : "Dis");
- debug = arg ? 1 : 0;
- return debug;
- }
- @@ -869,10 +1550,9 @@
- * is written on the CD is /not/ uniform across all discs!
- */
- case CDROM_GET_MCN: {
- - int ret;
- struct cdrom_mcn mcn;
- cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCNn");
- - if (!CDROM_CAN(CDC_MCN))
- + if (!(cdo->capability & CDC_MCN))
- return -ENOSYS;
- if ((ret=cdo->get_mcn(cdi, &mcn)))
- return ret;
- @@ -883,13 +1563,15 @@
-
- case CDROM_DRIVE_STATUS: {
- cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUSn");
- - if (!CDROM_CAN(CDC_DRIVE_STATUS))
- + if (!(cdo->capability & CDC_DRIVE_STATUS))
- return -ENOSYS;
- + if (!CDROM_CAN(CDC_SELECT_DISC))
- + return cdo->drive_status(cdi, CDSL_CURRENT);
- if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE))
- - return cdo->drive_status(cdi, arg);
- - if (((int)arg > cdi->capacity))
- + return cdo->drive_status(cdi, CDSL_CURRENT);
- + if (((int)arg >= cdi->capacity))
- return -EINVAL;
- - return cdo->drive_status(cdi, arg);
- + return cdrom_slot_status(cdi, arg);
- }
-
- /* Ok, this is where problems start. The current interface for the
- @@ -920,7 +1602,8 @@
- if (tracks.audio > 0) {
- if (tracks.data==0 && tracks.cdi==0 && tracks.xa==0)
- return CDS_AUDIO;
- - else return CDS_MIXED;
- + else
- + return CDS_MIXED;
- }
- if (tracks.cdi > 0) return CDS_XA_2_2;
- if (tracks.xa > 0) return CDS_XA_2_1;
- @@ -931,231 +1614,907 @@
- return CDS_NO_INFO;
- }
-
- - case CDROM_CHANGER_NSLOTS:
- + case CDROM_CHANGER_NSLOTS: {
- cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTSn");
- - return cdi->capacity;
- + return cdi->capacity;
- + }
- + }
-
- -/* The following is not implemented, because there are too many
- - * different data types. We could support /1/ raw mode, that is large
- - * enough to hold everything.
- - */
- + /* use the ioctls that are implemented through the generic_packet()
- + interface. this may look at bit funny, but if -ENOTTY is
- + returned that particular ioctl is not implemented and we
- + let it go through the device specific ones. */
- + if (CDROM_CAN(CDC_GENERIC_PACKET)) {
- + ret = mmc_ioctl(cdi, cmd, arg);
- + if (ret != -ENOTTY) {
- + return ret;
- + }
- + }
-
- -#if 0
- - case CDROMREADMODE1: {
- - int ret;
- + /* note: most of the cdinfo() calls are commented out here,
- + because they fill up the sys log when CD players poll
- + the drive. */
- + switch (cmd) {
- + case CDROMSUBCHNL: {
- + struct cdrom_subchnl q;
- + u_char requested, back;
- + if (!CDROM_CAN(CDC_PLAY_AUDIO))
- + return -ENOSYS;
- + /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNLn");*/
- + IOCTL_IN(arg, struct cdrom_subchnl, q);
- + requested = q.cdsc_format;
- + if (!((requested == CDROM_MSF) ||
- + (requested == CDROM_LBA)))
- + return -EINVAL;
- + q.cdsc_format = CDROM_MSF;
- + if ((ret=cdo->audio_ioctl(cdi, cmd, &q)))
- + return ret;
- + back = q.cdsc_format; /* local copy */
- + sanitize_format(&q.cdsc_absaddr, &back, requested);
- + sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
- + IOCTL_OUT(arg, struct cdrom_subchnl, q);
- + /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successfuln"); */
- + return 0;
- + }
- + case CDROMREADTOCHDR: {
- + struct cdrom_tochdr header;
- + if (!CDROM_CAN(CDC_PLAY_AUDIO))
- + return -ENOSYS;
- + /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDRn"); */
- + IOCTL_IN(arg, struct cdrom_tochdr, header);
- + if ((ret=cdo->audio_ioctl(cdi, cmd, &header)))
- + return ret;
- + IOCTL_OUT(arg, struct cdrom_tochdr, header);
- + /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successfuln"); */
- + return 0;
- + }
- + case CDROMREADTOCENTRY: {
- + struct cdrom_tocentry entry;
- + u_char requested_format;
- + if (!CDROM_CAN(CDC_PLAY_AUDIO))
- + return -ENOSYS;
- + /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRYn"); */
- + IOCTL_IN(arg, struct cdrom_tocentry, entry);
- + requested_format = entry.cdte_format;
- + if (!((requested_format == CDROM_MSF) ||
- + (requested_format == CDROM_LBA)))
- + return -EINVAL;
- + /* make interface to low-level uniform */
- + entry.cdte_format = CDROM_MSF;
- + if ((ret=cdo->audio_ioctl(cdi, cmd, &entry)))
- + return ret;
- + sanitize_format(&entry.cdte_addr,
- + &entry.cdte_format, requested_format);
- + IOCTL_OUT(arg, struct cdrom_tocentry, entry);
- + /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successfuln"); */
- + return 0;
- + }
- + case CDROMPLAYMSF: {
- struct cdrom_msf msf;
- - char buf[CD_FRAMESIZE];
- - cdinfo(CD_DO_IOCTL, "entering CDROMREADMODE1n");
- + if (!CDROM_CAN(CDC_PLAY_AUDIO))
- + return -ENOSYS;
- + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSFn");
- IOCTL_IN(arg, struct cdrom_msf, msf);
- - if (ret=cdo->read_audio(dev, cmd, &msf, &buf, cdi))
- + return cdo->audio_ioctl(cdi, cmd, &msf);
- + }
- + case CDROMPLAYTRKIND: {
- + struct cdrom_ti ti;
- + if (!CDROM_CAN(CDC_PLAY_AUDIO))
- + return -ENOSYS;
- + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKINDn");
- + IOCTL_IN(arg, struct cdrom_ti, ti);
- + CHECKAUDIO;
- + return cdo->audio_ioctl(cdi, cmd, &ti);
- + }
- + case CDROMVOLCTRL: {
- + struct cdrom_volctrl volume;
- + if (!CDROM_CAN(CDC_PLAY_AUDIO))
- + return -ENOSYS;
- + cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRLn");
- + IOCTL_IN(arg, struct cdrom_volctrl, volume);
- + return cdo->audio_ioctl(cdi, cmd, &volume);
- + }
- + case CDROMVOLREAD: {
- + struct cdrom_volctrl volume;
- + if (!CDROM_CAN(CDC_PLAY_AUDIO))
- + return -ENOSYS;
- + cdinfo(CD_DO_IOCTL, "entering CDROMVOLREADn");
- + if ((ret=cdo->audio_ioctl(cdi, cmd, &volume)))
- return ret;
- - IOCTL_OUT(arg, __typeof__(buf), buf);
- + IOCTL_OUT(arg, struct cdrom_volctrl, volume);
- return 0;
- }
- -#endif
- + case CDROMSTART:
- + case CDROMSTOP:
- + case CDROMPAUSE:
- + case CDROMRESUME: {
- + if (!CDROM_CAN(CDC_PLAY_AUDIO))
- + return -ENOSYS;
- + cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)n");
- + CHECKAUDIO;
- + return cdo->audio_ioctl(cdi, cmd, NULL);
- + }
- } /* switch */
-
- -/* Now all the audio-ioctls follow, they are all routed through the
- - same call audio_ioctl(). */
- + /* do the device specific ioctls */
- + if (CDROM_CAN(CDC_IOCTLS))
- + return cdo->dev_ioctl(cdi, cmd, arg);
- +
- + return -ENOSYS;
- +}
- +
- +static inline
- +int msf_to_lba(char m, char s, char f)
- +{
- + return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
- +}
-
- -#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret
- +static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- + unsigned long arg)
- +{
- + struct cdrom_device_ops *cdo = cdi->ops;
- + struct cdrom_generic_command cgc;
- + kdev_t dev = cdi->dev;
- + char buffer[32];
- + int ret = 0;
- +
- + memset(&cgc, 0, sizeof(cgc));
-
- - if (!CDROM_CAN(CDC_PLAY_AUDIO))
- - return -ENOSYS;
- - else {
- + /* build a unified command and queue it through
- + cdo->generic_packet() */
- + switch (cmd) {
- + case CDROMREADRAW:
- + case CDROMREADMODE1:
- + case CDROMREADMODE2: {
- + struct cdrom_msf msf;
- + int blocksize = 0, format = 0, lba;
- +
- switch (cmd) {
- - case CDROMSUBCHNL: {
- - int ret;
- - struct cdrom_subchnl q;
- - u_char requested, back;
- - /* comment out the cdinfo calls here because they
- - fill up the sys logs when CD players poll the drive*/
- - /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNLn");*/
- - IOCTL_IN(arg, struct cdrom_subchnl, q);
- - requested = q.cdsc_format;
- - if (!((requested == CDROM_MSF) ||
- - (requested == CDROM_LBA)))
- - return -EINVAL;
- - q.cdsc_format = CDROM_MSF;
- - if ((ret=cdo->audio_ioctl(cdi, cmd, &q)))
- - return ret;
- - back = q.cdsc_format; /* local copy */
- - sanitize_format(&q.cdsc_absaddr, &back, requested);
- - sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
- - IOCTL_OUT(arg, struct cdrom_subchnl, q);
- - /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successfuln"); */
- - return 0;
- - }
- - case CDROMREADTOCHDR: {
- - int ret;
- - struct cdrom_tochdr header;
- - /* comment out the cdinfo calls here because they
- - fill up the sys logs when CD players poll the drive*/
- - /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDRn"); */
- - IOCTL_IN(arg, struct cdrom_tochdr, header);
- - if ((ret=cdo->audio_ioctl(cdi, cmd, &header)))
- - return ret;
- - IOCTL_OUT(arg, struct cdrom_tochdr, header);
- - /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successfuln"); */
- - return 0;
- - }
- - case CDROMREADTOCENTRY: {
- - int ret;
- - struct cdrom_tocentry entry;
- - u_char requested_format;
- - /* comment out the cdinfo calls here because they
- - fill up the sys logs when CD players poll the drive*/
- - /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRYn"); */
- - IOCTL_IN(arg, struct cdrom_tocentry, entry);
- - requested_format = entry.cdte_format;
- - if (!((requested_format == CDROM_MSF) ||
- - (requested_format == CDROM_LBA)))
- - return -EINVAL;
- - /* make interface to low-level uniform */
- - entry.cdte_format = CDROM_MSF;
- - if ((ret=cdo->audio_ioctl(cdi, cmd, &entry)))
- - return ret;
- - sanitize_format(&entry.cdte_addr,
- - &entry.cdte_format, requested_format);
- - IOCTL_OUT(arg, struct cdrom_tocentry, entry);
- - /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successfuln"); */
- - return 0;
- - }
- - case CDROMPLAYMSF: {
- - int ret;
- - struct cdrom_msf msf;
- - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSFn");
- - IOCTL_IN(arg, struct cdrom_msf, msf);
- - CHECKAUDIO;
- - return cdo->audio_ioctl(cdi, cmd, &msf);
- - }
- - case CDROMPLAYTRKIND: {
- - int ret;
- - struct cdrom_ti ti;
- - cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKINDn");
- - IOCTL_IN(arg, struct cdrom_ti, ti);
- - CHECKAUDIO;
- - return cdo->audio_ioctl(cdi, cmd, &ti);
- - }
- - case CDROMVOLCTRL: {
- - struct cdrom_volctrl volume;
- - cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRLn");
- - IOCTL_IN(arg, struct cdrom_volctrl, volume);
- - return cdo->audio_ioctl(cdi, cmd, &volume);
- - }
- - case CDROMVOLREAD: {
- - int ret;
- - struct cdrom_volctrl volume;
- - cdinfo(CD_DO_IOCTL, "entering CDROMVOLREADn");
- - if ((ret=cdo->audio_ioctl(cdi, cmd, &volume)))
- - return ret;
- - IOCTL_OUT(arg, struct cdrom_volctrl, volume);
- + case CDROMREADRAW:
- + blocksize = CD_FRAMESIZE_RAW;
- + break;
- + case CDROMREADMODE1:
- + blocksize = CD_FRAMESIZE;
- + format = 2;
- + break;
- + case CDROMREADMODE2:
- + blocksize = CD_FRAMESIZE_RAW0;
- + break;
- + }
- + IOCTL_IN(arg, struct cdrom_msf, msf);
- + lba = msf_to_lba(msf.cdmsf_min0,msf.cdmsf_sec0,msf.cdmsf_frame0);
- + /* FIXME: we need upper bound checking, too!! */
- + if (lba < 0)
- + return -EINVAL;
- + cgc.buffer = (char *) kmalloc(blocksize, GFP_KERNEL);
- + if (cgc.buffer == NULL)
- + return -ENOMEM;
- + ret = cdrom_read_block(cdi, &cgc, lba, 1, format, blocksize);
- + if (!ret)
- + if (copy_to_user((char *)arg, cgc.buffer, blocksize))
- + ret = -EFAULT;
- + kfree(cgc.buffer);
- + return ret;
- + }
- + case CDROMREADAUDIO: {
- + struct cdrom_read_audio ra;
- + int lba, frames;
- +
- + IOCTL_IN(arg, struct cdrom_read_audio, ra);
- +
- + if (ra.addr_format == CDROM_MSF)
- + lba = msf_to_lba(ra.addr.msf.minute,
- + ra.addr.msf.second,
- + ra.addr.msf.frame);
- + else if (ra.addr_format == CDROM_LBA)
- + lba = ra.addr.lba;
- + else
- + return -EINVAL;
- +
- + /* FIXME: we need upper bound checking, too!! */
- + if (lba < 0)
- + return -EINVAL;
- +
- + /* do max 8 frames at the time */
- + frames = ra.nframes > 8 ? 8 : ra.nframes;
- +
- + if ((cgc.buffer = (char *) kmalloc(CD_FRAMESIZE_RAW * frames,
- + GFP_KERNEL)) == NULL)
- + return -ENOMEM;
- +
- + if (!access_ok(VERIFY_WRITE, ra.buf, ra.nframes*CD_FRAMESIZE_RAW)) {
- + kfree(cgc.buffer);
- + return -EFAULT;
- + }
- +
- + while (ra.nframes > 0) {
- + ret = cdrom_read_block(cdi, &cgc, lba, frames, 1,
- + CD_FRAMESIZE_RAW);
- + if (ret) break;
- + __copy_to_user(ra.buf, cgc.buffer,
- + CD_FRAMESIZE_RAW * frames);
- + ra.buf += (CD_FRAMESIZE_RAW * frames);
- + ra.nframes -= frames;
- + lba += frames;
- + }
- + kfree(cgc.buffer);
- + return ret;
- + }
- + case CDROMSUBCHNL: {
- + struct cdrom_subchnl q;
- + u_char requested, back;
- + IOCTL_IN(arg, struct cdrom_subchnl, q);
- + requested = q.cdsc_format;
- + if (!((requested == CDROM_MSF) ||
- + (requested == CDROM_LBA)))
- + return -EINVAL;
- + q.cdsc_format = CDROM_MSF;
- + if ((ret = cdrom_read_subchannel(cdi, &q, 0)))
- + return ret;
- + back = q.cdsc_format; /* local copy */
- + sanitize_format(&q.cdsc_absaddr, &back, requested);
- + sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
- + IOCTL_OUT(arg, struct cdrom_subchnl, q);
- + /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successfuln"); */
- + return 0;
- + }
- + case CDROMPLAYTRKIND: {
- + struct cdrom_ti ti;
- + struct cdrom_tocentry entry;
- +
- + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKINDn");
- + IOCTL_IN(arg, struct cdrom_ti, ti);
- + entry.cdte_format = CDROM_MSF;
- +
- + /* get toc entry for start and end track */
- + entry.cdte_track = ti.cdti_trk0;
- + if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry))
- + return -EINVAL;
- +
- + cgc.cmd[3] = entry.cdte_addr.msf.minute;
- + cgc.cmd[4] = entry.cdte_addr.msf.second;
- + cgc.cmd[5] = entry.cdte_addr.msf.frame;
- +
- + entry.cdte_track = ti.cdti_trk1;
- + if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry))
- + return -EINVAL;
- +
- + cgc.cmd[6] = entry.cdte_addr.msf.minute;
- + cgc.cmd[7] = entry.cdte_addr.msf.second;
- + cgc.cmd[8] = entry.cdte_addr.msf.frame;
- + cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
- + return cdo->generic_packet(cdi, &cgc);
- + }
- + case CDROMPLAYMSF: {
- + struct cdrom_msf msf;
- + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSFn");
- + IOCTL_IN(arg, struct cdrom_msf, msf);
- + cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
- + cgc.cmd[3] = msf.cdmsf_min0;
- + cgc.cmd[4] = msf.cdmsf_sec0;
- + cgc.cmd[5] = msf.cdmsf_frame0;
- + cgc.cmd[6] = msf.cdmsf_min1;
- + cgc.cmd[7] = msf.cdmsf_sec1;
- + cgc.cmd[8] = msf.cdmsf_frame1;
- + return cdo->generic_packet(cdi, &cgc);
- + }
- + case CDROMPLAYBLK: {
- + struct cdrom_blk blk;
- + cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLKn");
- + IOCTL_IN(arg, struct cdrom_blk, blk);
- + cgc.cmd[0] = GPCMD_PLAY_AUDIO_10;
- + cgc.cmd[2] = (blk.from >> 24) & 0xff;
- + cgc.cmd[3] = (blk.from >> 16) & 0xff;
- + cgc.cmd[4] = (blk.from >> 8) & 0xff;
- + cgc.cmd[5] = blk.from & 0xff;
- + cgc.cmd[7] = (blk.len >> 8) & 0xff;
- + cgc.cmd[8] = blk.len & 0xff;
- + return cdo->generic_packet(cdi, &cgc);
- + }
- + case CDROMVOLCTRL:
- + case CDROMVOLREAD: {
- + struct cdrom_volctrl volctrl;
- + char mask[32];
- + unsigned short offset;
- + cdinfo(CD_DO_IOCTL, "entering CDROMVOLUMEn");
- +
- + IOCTL_IN(arg, struct cdrom_volctrl, volctrl);
- +
- + cgc.buffer = buffer;
- + cgc.buflen = 24;
- + if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_AUDIO_CTL_PAGE, 0)))
- + return ret;
- +
- + /* some drives have longer pages, adjust and reread. */
- + if (buffer[1] > cgc.buflen) {
- + cgc.buflen = buffer[1] + 2;
- + if ((ret = cdrom_mode_sense(cdi, &cgc,
- + GPMODE_AUDIO_CTL_PAGE, 0)))
- + return ret;
- + }
- +
- + /* get the offset from the length of the page. length
- + is measure from byte 2 an on, thus the 14. */
- + offset = buffer[1] - 14;
- +
- + /* now we have the current volume settings. if it was only
- + a CDROMVOLREAD, return these values */
- + if (cmd == CDROMVOLREAD) {
- + volctrl.channel0 = buffer[offset+9];
- + volctrl.channel1 = buffer[offset+11];
- + volctrl.channel2 = buffer[offset+13];
- + volctrl.channel3 = buffer[offset+15];
- + IOCTL_OUT(arg, struct cdrom_volctrl, volctrl);
- return 0;
- + }
- +
- + /* get the volume mask */
- + cgc.buffer = mask;
- + if ((ret = cdrom_mode_sense(cdi, &cgc,
- + GPMODE_AUDIO_CTL_PAGE, 1)))
- + return ret;
- +
- + buffer[offset+9] = volctrl.channel0 & mask[offset+9];
- + buffer[offset+11] = volctrl.channel1 & mask[offset+11];
- + buffer[offset+13] = volctrl.channel2 & mask[offset+13];
- + buffer[offset+15] = volctrl.channel3 & mask[offset+15];
- +
- + /* clear the first three */
- + memset(buffer, 0, 3);
- +
- + /* set volume */
- + cgc.buffer = buffer;
- + return cdrom_mode_select(cdi, &cgc);
- + }
- +
- + case CDROMSTART:
- + case CDROMSTOP: {
- + cdinfo(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOPn");
- + cgc.cmd[0] = GPCMD_START_STOP_UNIT;
- + cgc.cmd[1] = 1;
- + cgc.cmd[4] = (cmd == CDROMSTART) ? 1 : 0;
- + return cdo->generic_packet(cdi, &cgc);
- + }
- +
- + case CDROMPAUSE:
- + case CDROMRESUME: {
- + cdinfo(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUMEn");
- + cgc.cmd[0] = GPCMD_PAUSE_RESUME;
- + cgc.cmd[8] = (cmd == CDROMRESUME) ? 1 : 0;
- + return cdo->generic_packet(cdi, &cgc);
- + }
- +
- + case DVD_READ_STRUCT: {
- + dvd_struct *s;
- + int size = sizeof(dvd_struct);
- + if (!CDROM_CAN(CDC_DVD))
- + return -ENOSYS;
- + if ((s = (dvd_struct *) kmalloc(size, GFP_KERNEL)) == NULL)
- + return -ENOMEM;
- + cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCTn");
- + if (copy_from_user(s, (dvd_struct *)arg, size)) {
- + kfree(s);
- + return -EFAULT;
- + }
- + if ((ret = dvd_read_struct(cdi, s))) {
- + kfree(s);
- + return ret;
- + }
- + if (copy_to_user((dvd_struct *)arg, s, size))
- + ret = -EFAULT;
- + kfree(s);
- + return ret;
- + }
- +
- + case DVD_AUTH: {
- + dvd_authinfo ai;
- + if (!CDROM_CAN(CDC_DVD))
- + return -ENOSYS;
- + cdinfo(CD_DO_IOCTL, "entering DVD_AUTHn");
- + IOCTL_IN(arg, dvd_authinfo, ai);
- + if ((ret = dvd_do_auth (cdi, &ai)))
- + return ret;
- + IOCTL_OUT(arg, dvd_authinfo, ai);
- + return 0;
- + }
- +
- + case CDROM_SEND_PACKET: {
- + __u8 *userbuf, copy = 0;
- + if (!CDROM_CAN(CDC_GENERIC_PACKET))
- + return -ENOSYS;
- + cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKETn");
- + IOCTL_IN(arg, struct cdrom_generic_command, cgc);
- + copy = !!cgc.buflen;
- + userbuf = cgc.buffer;
- + cgc.buffer = NULL;
- + if (userbuf != NULL && copy) {
- + /* usually commands just copy data one way, i.e.
- + * we send a buffer to the drive and the command
- + * specifies whether the drive will read or
- + * write to that buffer. usually the buffers
- + * are very small, so we don't loose that much
- + * by doing a redundant copy each time. */
- + if (!access_ok(VERIFY_WRITE, userbuf, cgc.buflen)) {
- + printk("can't get write permsn");
- + return -EFAULT;
- }
- - case CDROMSTART:
- - case CDROMSTOP:
- - case CDROMPAUSE:
- - case CDROMRESUME: {
- - int ret;
- - cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)n");
- - CHECKAUDIO;
- - return cdo->audio_ioctl(cdi, cmd, NULL);
- + if (!access_ok(VERIFY_READ, userbuf, cgc.buflen)) {
- + printk("can't get read permsn");
- + return -EFAULT;
- }
- - } /* switch */
- + }
- + /* reasonable limits */
- + if (cgc.buflen < 0 || cgc.buflen > 131072) {
- + printk("invalid size givenn");
- + return -EINVAL;
- + }
- + if (copy) {
- + cgc.buffer = kmalloc(cgc.buflen, GFP_KERNEL);
- + if (cgc.buffer == NULL)
- + return -ENOMEM;
- + __copy_from_user(cgc.buffer, userbuf, cgc.buflen);
- + }
- + ret = cdo->generic_packet(cdi, &cgc);
- + if (copy && !ret)
- + __copy_to_user(userbuf, cgc.buffer, cgc.buflen);
- + kfree(cgc.buffer);
- + return ret;
- + }
- + case CDROM_NEXT_WRITABLE: {
- + long next = 0;
- + cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLEn");
- + if ((ret = cdrom_get_next_writable(dev, &next)))
- + return ret;
- + IOCTL_OUT(arg, long, next);
- + return 0;
- + }
- + case CDROM_LAST_WRITTEN: {
- + long last = 0;
- + cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTENn");
- + if ((ret = cdrom_get_last_written(dev, &last)))
- + return ret;
- + IOCTL_OUT(arg, long, last);
- + return 0;
- + }
- + } /* switch */
- +
- + return -ENOTTY;
- +}
- +
- +static int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type,
- + track_information *ti)
- +{
- + struct cdrom_device_info *cdi = cdrom_find_device(dev);
- + struct cdrom_device_ops *cdo = cdi->ops;
- + struct cdrom_generic_command cgc;
- + int ret;
- +
- + init_cdrom_command(&cgc, ti, 8);
- + cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO;
- + cgc.cmd[1] = type & 3;
- + cgc.cmd[4] = (track & 0xff00) >> 8;
- + cgc.cmd[5] = track & 0xff;
- + cgc.cmd[8] = 8;
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + cgc.cmd[8] = cgc.buflen = be16_to_cpu(ti->track_information_length) +
- + sizeof(ti->track_information_length);
- + return cdo->generic_packet(cdi, &cgc);
- +}
- +
- +static int cdrom_get_disc_info(kdev_t dev, disc_information *di)
- +{
- + struct cdrom_device_info *cdi = cdrom_find_device(dev);
- + struct cdrom_device_ops *cdo = cdi->ops;
- + struct cdrom_generic_command cgc;
- +
- + /* set up command and get the disc info */
- + init_cdrom_command(&cgc, di, sizeof(*di));
- + cgc.cmd[0] = GPCMD_READ_DISC_INFO;
- + cgc.cmd[8] = cgc.buflen;
- +
- + return cdo->generic_packet(cdi, &cgc);
- +}
- +
- +
- +/* return the last written block on the CD-R media. this is for the udf
- + file system. */
- +int cdrom_get_last_written(kdev_t dev, long *last_written)
- +{
- + struct cdrom_device_info *cdi = cdrom_find_device(dev);
- + struct cdrom_tocentry toc;
- + disc_information di;
- + track_information ti;
- + __u32 last_track;
- + int ret = -1;
- +
- + if (!CDROM_CAN(CDC_GENERIC_PACKET))
- + goto use_toc;
- +
- + if ((ret = cdrom_get_disc_info(dev, &di)))
- + goto use_toc;
- +
- + last_track = (di.last_track_msb << 8) | di.last_track_lsb;
- + if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
- + goto use_toc;
- +
- + /* if this track is blank, try the previous. */
- + if (ti.blank) {
- + last_track--;
- + if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
- + goto use_toc;
- }
-
- - /* device specific ioctls? */
- - if (!(cdo->capability & CDC_IOCTLS))
- - return -ENOSYS;
- - else
- - return cdo->dev_ioctl(cdi, cmd, arg);
- + /* if last recorded field is valid, return it. */
- + if (ti.lra_v) {
- + *last_written = be32_to_cpu(ti.last_rec_address);
- + } else {
- + /* make it up instead */
- + *last_written = be32_to_cpu(ti.track_start) +
- + be32_to_cpu(ti.track_size);
- + if (ti.free_blocks)
- + *last_written -= (be32_to_cpu(ti.free_blocks) + 7);
- + }
- + return 0;
- +
- + /* this is where we end up if the drive either can't do a
- + GPCMD_READ_DISC_INFO or GPCMD_READ_TRACK_RZONE_INFO or if
- + it fails. then we return the toc contents. */
- +use_toc:
- + toc.cdte_format = CDROM_MSF;
- + toc.cdte_track = CDROM_LEADOUT;
- + if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc))
- + return ret;
- + sanitize_format(&toc.cdte_addr, &toc.cdte_format, CDROM_LBA);
- + *last_written = toc.cdte_addr.lba;
- + return 0;
- +}
- +
- +/* return the next writable block. also for udf file system. */
- +int cdrom_get_next_writable(kdev_t dev, long *next_writable)
- +{
- + struct cdrom_device_info *cdi = cdrom_find_device(dev);
- + disc_information di;
- + track_information ti;
- + __u16 last_track;
- + int ret = -1;
- +
- + if (!CDROM_CAN(CDC_GENERIC_PACKET))
- + goto use_last_written;
- +
- + if ((ret = cdrom_get_disc_info(dev, &di)))
- + goto use_last_written;
- +
- + last_track = (di.last_track_msb << 8) | di.last_track_lsb;
- + if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
- + goto use_last_written;
- +
- + /* if this track is blank, try the previous. */
- + if (ti.blank) {
- + last_track--;
- + if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
- + goto use_last_written;
- + }
- +
- + /* if next recordable address field is valid, use it. */
- + if (ti.nwa_v)
- + *next_writable = be32_to_cpu(ti.next_writable);
- + else
- + goto use_last_written;
- +
- + return 0;
- +
- +use_last_written:
- + if ((ret = cdrom_get_last_written(dev, next_writable))) {
- + *next_writable = 0;
- + return ret;
- + } else {
- + *next_writable += 7;
- + return 0;
- + }
- +}
- +
- +/* return the buffer size of writeable drives */
- +static int cdrom_read_buffer_capacity(struct cdrom_device_info *cdi)
- +{
- + struct cdrom_device_ops *cdo = cdi->ops;
- + struct cdrom_generic_command cgc;
- + struct {
- + unsigned int pad;
- + unsigned int buffer_size;
- + unsigned int buffer_free;
- + } buf;
- + int ret;
- +
- + init_cdrom_command(&cgc, &buf, 12);
- + cgc.cmd[0] = 0x5c;
- + cgc.cmd[8] = 12;
- +
- + if ((ret = cdo->generic_packet(cdi, &cgc)))
- + return ret;
- +
- + return be32_to_cpu(buf.buffer_size);
- +}
- +
- +/* return 0 if succesful and the disc can be considered writeable. */
- +static int cdrom_setup_writemode(struct cdrom_device_info *cdi)
- +{
- + struct cdrom_generic_command cgc;
- + write_param_page wp;
- + disc_information di;
- + track_information ti;
- + int ret, last_track;
- +
- + memset(&di, 0, sizeof(disc_information));
- + memset(&ti, 0, sizeof(track_information));
- + memset(&cdi->write, 0, sizeof(struct cdrom_write_settings));
- +
- + if ((ret = cdrom_get_disc_info(cdi->dev, &di)))
- + return ret;
- +
- + last_track = (di.last_track_msb << 8) | di.last_track_lsb;
- + if ((ret = cdrom_get_track_info(cdi->dev, last_track, 1, &ti)))
- + return ret;
- +
- + /* if the media is erasable, then it is either CD-RW or
- + * DVD-RW - use fixed packets for those. non-erasable media
- + * indicated CD-R or DVD-R media, use varible sized packets for
- + * those (where the packet size is a bit less than the buffer
- + * capacity of the drive. */
- + if (di.erasable) {
- + cdi->write.fpacket = 1;
- + /* FIXME: DVD-RW is 16, should get the packet size instead */
- + cdi->write.packet_size = 32;
- + } else {
- + int buf_size;
- + cdi->write.fpacket = 0;
- + buf_size = cdrom_read_buffer_capacity(cdi);
- + buf_size -= 100*1024;
- + cdi->write.packet_size = buf_size / CD_FRAMESIZE;
- + }
- +
- + init_cdrom_command(&cgc, &wp, 0x3c);
- + if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_WRITE_PARMS_PAGE, 0)))
- + return ret;
- +
- + /* sanity checks */
- + if ((ti.damage && !ti.nwa_v) || ti.blank) {
- + cdinfo(CD_WARNING, "can't write to this discn");
- + return 1;
- + }
- +
- + /* NWA is only for CD-R and DVD-R. -RW media is randomly
- + * writeable once it has been formatted. */
- + cdi->write.nwa = ti.nwa_v ? be32_to_cpu(ti.next_writable) : 0;
- +
- + wp.fp = cdi->write.fpacket ? 1 : 0;
- + wp.track_mode = 0;
- + wp.write_type = 0;
- + wp.data_block_type = 8;
- + wp.session_format = 0;
- + wp.multi_session = 3;
- + wp.audio_pause = cpu_to_be16(0x96);
- + wp.packet_size = cdi->write.fpacket ? cpu_to_be32(cdi->write.packet_size) : 0;
- + wp.track_mode = 5; /* should be ok with both CD and DVD */
- +
- + if ((ret = cdrom_mode_select(cdi, &cgc)))
- + return ret;
- +
- + cdinfo(CD_WARNING, "%s: writeable with %lu block %s packetsn",
- + cdi->name, cdi->write.packet_size,
- + cdi->write.fpacket ? "fixed" : "variable");
- + return 0;
- }
-
- +EXPORT_SYMBOL(cdrom_get_next_writable);
- +EXPORT_SYMBOL(cdrom_get_last_written);
- EXPORT_SYMBOL(cdrom_count_tracks);
- EXPORT_SYMBOL(register_cdrom);
- EXPORT_SYMBOL(unregister_cdrom);
- EXPORT_SYMBOL(cdrom_fops);
- +EXPORT_SYMBOL(cdrom_number_of_slots);
- +EXPORT_SYMBOL(cdrom_select_disc);
- +EXPORT_SYMBOL(cdrom_mode_select);
- +EXPORT_SYMBOL(cdrom_mode_sense);
- +EXPORT_SYMBOL(init_cdrom_command);
-
- #ifdef CONFIG_SYSCTL
-
- #define CDROM_STR_SIZE 1000
-
- -static char cdrom_drive_info[CDROM_STR_SIZE]="infon";
- +struct cdrom_sysctl_settings {
- + char info[CDROM_STR_SIZE]; /* general info */
- + int autoclose; /* close tray upon mount, etc */
- + int autoeject; /* eject on umount */
- + int debug; /* turn on debugging messages */
- + int lock; /* lock the door on device open */
- + int check; /* check media type */
- +} cdrom_sysctl_settings;
-
- int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
- void *buffer, size_t *lenp)
- {
- int pos;
- struct cdrom_device_info *cdi;
- - char *info = cdrom_drive_info;
- + char *info = cdrom_sysctl_settings.info;
-
- if (!*lenp || (filp->f_pos && !write)) {
- *lenp = 0;
- return 0;
- }
-
- - pos = sprintf(cdrom_drive_info, "CD-ROM information, " VERSION "n");
- + pos = sprintf(info, "CD-ROM information, " VERSION "n");
-
- - pos += sprintf(cdrom_drive_info+pos, "ndrive name:t");
- + pos += sprintf(info+pos, "ndrive name:t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "t%s", cdi->name);
-
- - pos += sprintf(cdrom_drive_info+pos, "ndrive speed:t");
- + pos += sprintf(info+pos, "ndrive speed:t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "t%d", cdi->speed);
-
- - pos += sprintf(cdrom_drive_info+pos, "ndrive # of slots:");
- + pos += sprintf(info+pos, "ndrive # of slots:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "t%d", cdi->capacity);
-
- - pos += sprintf(cdrom_drive_info+pos, "nCan close tray:t");
- + pos += sprintf(info+pos, "nCan close tray:t");
- + for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0);
- +
- + pos += sprintf(info+pos, "nCan open tray:t");
- + for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0);
- +
- + pos += sprintf(info+pos, "nCan lock tray:t");
- + for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_LOCK) != 0);
- +
- + pos += sprintf(info+pos, "nCan change speed:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- - pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_CLOSE_TRAY)!=0);
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0);
-
- - pos += sprintf(cdrom_drive_info+pos, "nCan open tray:t");
- + pos += sprintf(info+pos, "nCan select disk:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- - pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_OPEN_TRAY)!=0);
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_SELECT_DISC) != 0);
-
- - pos += sprintf(cdrom_drive_info+pos, "nCan lock tray:t");
- + pos += sprintf(info+pos, "nCan read multisession:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- - pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_LOCK)!=0);
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0);
-
- - pos += sprintf(cdrom_drive_info+pos, "nCan change speed:");
- + pos += sprintf(info+pos, "nCan read MCN:t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- - pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_SELECT_SPEED)!=0);
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_MCN) != 0);
-
- - pos += sprintf(cdrom_drive_info+pos, "nCan select disk:");
- + pos += sprintf(info+pos, "nReports media changed:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- - pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_SELECT_DISC)!=0);
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0);
-
- - pos += sprintf(cdrom_drive_info+pos, "nCan read multisession:");
- + pos += sprintf(info+pos, "nCan play audio:t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- - pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_MULTI_SESSION)!=0);
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0);
-
- - pos += sprintf(cdrom_drive_info+pos, "nCan read MCN:t");
- + pos += sprintf(info+pos, "nCan write CD-R:t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- - pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_MCN)!=0);
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_CD_R) != 0);
-
- - pos += sprintf(cdrom_drive_info+pos, "nReports media changed:");
- + pos += sprintf(info+pos, "nCan write CD-RW:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- - pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_MEDIA_CHANGED)!=0);
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_CD_RW) != 0);
-
- - pos += sprintf(cdrom_drive_info+pos, "nCan play audio:t");
- + pos += sprintf(info+pos, "nCan read DVD:t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- - pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_PLAY_AUDIO)!=0);
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_DVD) != 0);
-
- - strcpy(info+pos,"nn");
- - pos += 3;
- - if (*lenp > pos)
- - *lenp = pos;
- + pos += sprintf(info+pos, "nCan write DVD-R:");
- + for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_DVD_R) != 0);
- +
- + pos += sprintf(info+pos, "nCan write DVD-RAM:");
- + for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- + pos += sprintf(info+pos, "t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
- +
- + strcpy(info+pos,"nn");
-
- return proc_dostring(ctl, write, filp, buffer, lenp);
- }
-
- +/* Unfortunately, per device settings are not implemented through
- + procfs/sysctl yet. When they are, this will naturally disappear. For now
- + just update all drives. Later this will become the template on which
- + new registered drives will be based. */
- +void cdrom_update_settings(void)
- +{
- + struct cdrom_device_info *cdi;
- +
- + for (cdi = topCdromPtr; cdi != NULL; cdi = cdi->next) {
- + if (autoclose && CDROM_CAN(CDC_CLOSE_TRAY))
- + cdi->options |= CDO_AUTO_CLOSE;
- + else if (!autoclose)
- + cdi->options &= ~CDO_AUTO_CLOSE;
- + if (autoeject && CDROM_CAN(CDC_OPEN_TRAY))
- + cdi->options |= CDO_AUTO_EJECT;
- + else if (!autoeject)
- + cdi->options &= ~CDO_AUTO_EJECT;
- + if (lockdoor && CDROM_CAN(CDC_LOCK))
- + cdi->options |= CDO_LOCK;
- + else if (!lockdoor)
- + cdi->options &= ~CDO_LOCK;
- + if (check_media_type)
- + cdi->options |= CDO_CHECK_TYPE;
- + else
- + cdi->options &= ~CDO_CHECK_TYPE;
- + }
- +}
- +
- +static int cdrom_sysctl_handler(ctl_table *ctl, int write, struct file * filp,
- + void *buffer, size_t *lenp)
- +{
- + int *valp = ctl->data;
- + int val = *valp;
- + int ret;
- +
- + ret = proc_dointvec(ctl, write, filp, buffer, lenp);
- +
- + if (write && *valp != val) {
- +
- + /* we only care for 1 or 0. */
- + if (*valp)
- + *valp = 1;
- + else
- + *valp = 0;
- +
- + switch (ctl->ctl_name) {
- + case DEV_CDROM_AUTOCLOSE: {
- + if (valp == &cdrom_sysctl_settings.autoclose)
- + autoclose = cdrom_sysctl_settings.autoclose;
- + break;
- + }
- + case DEV_CDROM_AUTOEJECT: {
- + if (valp == &cdrom_sysctl_settings.autoeject)
- + autoeject = cdrom_sysctl_settings.autoeject;
- + break;
- + }
- + case DEV_CDROM_DEBUG: {
- + if (valp == &cdrom_sysctl_settings.debug)
- + debug = cdrom_sysctl_settings.debug;
- + break;
- + }
- + case DEV_CDROM_LOCK: {
- + if (valp == &cdrom_sysctl_settings.lock)
- + lockdoor = cdrom_sysctl_settings.lock;
- + break;
- + }
- + case DEV_CDROM_CHECK_MEDIA: {
- + if (valp == &cdrom_sysctl_settings.check)
- + check_media_type = cdrom_sysctl_settings.check;
- + break;
- + }
- + }
- + /* update the option flags according to the changes. we
- + don't have per device options through sysctl yet,
- + but we will have and then this will disappear. */
- + cdrom_update_settings();
- + }
- +
- + return ret;
- +}
- +
- /* Place files in /proc/sys/dev/cdrom */
- ctl_table cdrom_table[] = {
- - {DEV_CDROM_INFO, "info", &cdrom_drive_info,
- + {DEV_CDROM_INFO, "info", &cdrom_sysctl_settings.info,
- CDROM_STR_SIZE, 0444, NULL, &cdrom_sysctl_info},
- + {DEV_CDROM_AUTOCLOSE, "autoclose", &cdrom_sysctl_settings.autoclose,
- + sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
- + {DEV_CDROM_AUTOEJECT, "autoeject", &cdrom_sysctl_settings.autoeject,
- + sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
- + {DEV_CDROM_DEBUG, "debug", &cdrom_sysctl_settings.debug,
- + sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
- + {DEV_CDROM_LOCK, "lock", &cdrom_sysctl_settings.lock,
- + sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
- + {DEV_CDROM_CHECK_MEDIA, "check_media", &cdrom_sysctl_settings.check,
- + sizeof(int), 0644, NULL, &cdrom_sysctl_handler },
- {0}
- };
-
- @@ -1199,24 +2558,31 @@
- cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
- cdrom_root_table->child->de->fill_inode = &cdrom_procfs_modcount;
-
- + /* set the defaults */
- + cdrom_sysctl_settings.autoclose = autoclose;
- + cdrom_sysctl_settings.autoeject = autoeject;
- + cdrom_sysctl_settings.debug = debug;
- + cdrom_sysctl_settings.lock = lockdoor;
- + cdrom_sysctl_settings.check = check_media_type;
- +
- initialized = 1;
- }
- +#endif /* endif CONFIG_SYSCTL */
- +
-
- #ifdef MODULE
- static void cdrom_sysctl_unregister(void)
- {
- +#ifdef CONFIG_SYSCTL
- unregister_sysctl_table(cdrom_sysctl_header);
- +#endif
- }
- -#endif /* endif MODULE */
- -#endif /* endif CONFIG_SYSCTL */
- -
- -#ifdef MODULE
-
- int init_module(void)
- {
- #ifdef CONFIG_SYSCTL
- cdrom_sysctl_register();
- -#endif /* CONFIG_SYSCTL */
- +#endif
- return 0;
- }
-
- @@ -1227,14 +2593,5 @@
- cdrom_sysctl_unregister();
- #endif /* CONFIG_SYSCTL */
- }
- -
- #endif /* endif MODULE */
-
- -
- -
- -/*
- - * Local variables:
- - * comment-column: 40
- - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -m486 -DCPU=486 -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -c -o cdrom.o cdrom.c"
- - * End:
- - */
- diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.2.13/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
- --- linux-2.2.13/drivers/scsi/ide-scsi.c Thu Sep 9 12:27:37 1999
- +++ linux/drivers/scsi/ide-scsi.c Sun Nov 7 15:23:25 1999
- @@ -365,7 +365,7 @@
- pc->actually_transferred += temp;
- pc->current_position += temp;
- idescsi_discard_data (drive,bcount - temp);
- - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc));
- + ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);
- return;
- }
- #if IDESCSI_DEBUG_LOG
- @@ -389,7 +389,7 @@
- pc->actually_transferred+=bcount; /* Update the current position */
- pc->current_position+=bcount;
-
- - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc)); /* And set the interrupt handler again */
- + ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* And set the interrupt handler again */
- }
-
- static void idescsi_transfer_pc (ide_drive_t *drive)
- @@ -408,7 +408,7 @@
- ide_do_reset (drive);
- return;
- }
- - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc)); /* Set the interrupt routine */
- + ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* Set the interrupt routine */
- atapi_output_bytes (drive, scsi->pc->c, 12); /* Send the actual packet */
- }
-
- @@ -441,7 +441,7 @@
- (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
- }
- if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
- - ide_set_handler (drive, &idescsi_transfer_pc, get_timeout(pc));
- + ide_set_handler (drive, &idescsi_transfer_pc, get_timeout(pc), NULL);
- OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */
- } else {
- OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);
- diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.2.13/drivers/scsi/sr.c linux/drivers/scsi/sr.c
- --- linux-2.2.13/drivers/scsi/sr.c Fri Jan 15 23:41:04 1999
- +++ linux/drivers/scsi/sr.c Sun Oct 31 13:37:07 1999
- @@ -1,25 +1,28 @@
- /*
- * sr.c Copyright (C) 1992 David Giller
- - * Copyright (C) 1993, 1994, 1995 Eric Youngdale
- + * Copyright (C) 1993, 1994, 1995 Eric Youngdale
- *
- * adapted from:
- - * sd.c Copyright (C) 1992 Drew Eckhardt
- - * Linux scsi disk driver by
- - * Drew Eckhardt <drew@colorado.edu>
- + * sd.c Copyright (C) 1992 Drew Eckhardt
- + * Linux scsi disk driver by
- + * Drew Eckhardt <drew@colorado.edu>
- *
- * Modified by Eric Youngdale ericy@cais.com to
- * add scatter-gather, multiple outstanding request, and other
- * enhancements.
- *
- - * Modified by Eric Youngdale eric@aib.com to support loadable
- - * low-level scsi drivers.
- + * Modified by Eric Youngdale eric@aib.com to support loadable
- + * low-level scsi drivers.
- *
- - * Modified by Thomas Quinot thomas@melchior.cuivre.fdn.fr to
- - * provide auto-eject.
- + * Modified by Thomas Quinot thomas@melchior.cuivre.fdn.fr to
- + * provide auto-eject.
- *
- * Modified by Gerd Knorr <kraxel@cs.tu-berlin.de> to support the
- * generic cdrom interface
- *
- + * Modified by Jens Axboe <axboe@image.dk> - Uniform sr_packet()
- + * interface, capabilities probe additions, ioctl cleanups, etc.
- + *
- */
-
- #include <linux/module.h>
- @@ -34,19 +37,22 @@
- #include <linux/interrupt.h>
- #include <asm/system.h>
- #include <asm/io.h>
- +#include <asm/uaccess.h>
-
- #define MAJOR_NR SCSI_CDROM_MAJOR
- #include <linux/blk.h>
- #include "scsi.h"
- #include "hosts.h"
- #include "sr.h"
- -#include <scsi/scsi_ioctl.h> /* For the door lock/unlock commands */
- +#include <scsi/scsi_ioctl.h> /* For the door lock/unlock commands */
- #include "constants.h"
-
- -MODULE_PARM(xa_test,"i"); /* see sr_ioctl.c */
- +#ifdef MODULE
- +MODULE_PARM(xa_test, "i"); /* see sr_ioctl.c */
- +#endif
-
- -#define MAX_RETRIES 3
- -#define SR_TIMEOUT (30 * HZ)
- +#define MAX_RETRIES 3
- +#define SR_TIMEOUT (30 * HZ)
-
- static int sr_init(void);
- static void sr_finish(void);
- @@ -54,53 +60,60 @@
- static int sr_detect(Scsi_Device *);
- static void sr_detach(Scsi_Device *);
-
- -struct Scsi_Device_Template sr_template = {NULL, "cdrom", "sr", NULL, TYPE_ROM,
- - SCSI_CDROM_MAJOR, 0, 0, 0, 1,
- - sr_detect, sr_init,
- - sr_finish, sr_attach, sr_detach};
- +struct Scsi_Device_Template sr_template = {
- + NULL, "cdrom", "sr", NULL, TYPE_ROM,
- + SCSI_CDROM_MAJOR, 0, 0, 0, 1,
- + sr_detect, sr_init,
- + sr_finish, sr_attach, sr_detach
- +};
-
- -Scsi_CD * scsi_CDs = NULL;
- -static int * sr_sizes = NULL;
- +Scsi_CD *scsi_CDs = NULL;
- +static int *sr_sizes = NULL;
-
- -static int * sr_blocksizes = NULL;
- +static int *sr_blocksizes = NULL;
-
- -static int sr_open(struct cdrom_device_info*, int);
- +static int sr_open(struct cdrom_device_info *, int);
- void get_sectorsize(int);
- void get_capabilities(int);
-
- -void requeue_sr_request (Scsi_Cmnd * SCpnt);
- -static int sr_media_change(struct cdrom_device_info*, int);
- +void requeue_sr_request(Scsi_Cmnd * SCpnt);
- +static int sr_media_change(struct cdrom_device_info *, int);
- +static int sr_packet(struct cdrom_device_info *, struct cdrom_generic_command *);
-
- static void sr_release(struct cdrom_device_info *cdi)
- {
- if (scsi_CDs[MINOR(cdi->dev)].sector_size > 2048)
- - sr_set_blocklength(MINOR(cdi->dev),2048);
- + sr_set_blocklength(MINOR(cdi->dev), 2048);
- sync_dev(cdi->dev);
- scsi_CDs[MINOR(cdi->dev)].device->access_count--;
- if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module)
- __MOD_DEC_USE_COUNT(scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module);
- - if(sr_template.module)
- - __MOD_DEC_USE_COUNT(sr_template.module);
- + if (sr_template.module)
- + __MOD_DEC_USE_COUNT(sr_template.module);
- }
-
- -static struct cdrom_device_ops sr_dops = {
- - sr_open, /* open */
- - sr_release, /* release */
- - sr_drive_status, /* drive status */
- - sr_media_change, /* media changed */
- - sr_tray_move, /* tray move */
- - sr_lock_door, /* lock door */
- - sr_select_speed, /* select speed */
- - NULL, /* select disc */
- - sr_get_last_session, /* get last session */
- - sr_get_mcn, /* get universal product code */
- - sr_reset, /* hard reset */
- - sr_audio_ioctl, /* audio ioctl */
- - sr_dev_ioctl, /* device-specific ioctl */
- - CDC_CLOSE_TRAY | CDC_OPEN_TRAY| CDC_LOCK | CDC_SELECT_SPEED |
- - CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
- - CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS,
- - 0
- +static struct cdrom_device_ops sr_dops =
- +{
- + sr_open, /* open */
- + sr_release, /* release */
- + sr_drive_status, /* drive status */
- + sr_media_change, /* media changed */
- + sr_tray_move, /* tray move */
- + sr_lock_door, /* lock door */
- + sr_select_speed, /* select speed */
- + NULL, /* select disc */
- + sr_get_last_session, /* get last session */
- + sr_get_mcn, /* get universal product code */
- + sr_reset, /* hard reset */
- + sr_audio_ioctl, /* audio ioctl */
- + sr_dev_ioctl, /* device-specific ioctl */
- + 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_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM |
- + CDC_GENERIC_PACKET,
- + 0,
- + sr_packet
- };
-
- /*
- @@ -113,48 +126,47 @@
- * an inode for that to work, and we do not always have one.
- */
-
- -int sr_media_change(struct cdrom_device_info *cdi, int slot){
- +int sr_media_change(struct cdrom_device_info *cdi, int slot)
- +{
- int retval;
-
- - if (CDSL_CURRENT != slot) {
- - /* no changer support */
- - return -EINVAL;
- - }
- -
- + if (CDSL_CURRENT != slot) {
- + /* no changer support */
- + return -EINVAL;
- + }
- retval = scsi_ioctl(scsi_CDs[MINOR(cdi->dev)].device,
- - SCSI_IOCTL_TEST_UNIT_READY, 0);
- + SCSI_IOCTL_TEST_UNIT_READY, 0);
-
- - if(retval)
- - {
- - /* Unable to test, unit probably not ready. This usually
- + if (retval) {
- + /* Unable to test, unit probably not ready. This usually
- * means there is no disc in the drive. Mark as changed,
- * and we will figure it out later once the drive is
- * available again. */
-
- - scsi_CDs[MINOR(cdi->dev)].device->changed = 1;
- - return 1; /* This will force a flush, if called from
- - * check_disk_change */
- + scsi_CDs[MINOR(cdi->dev)].device->changed = 1;
- + return 1; /* This will force a flush, if called from
- + * check_disk_change */
- };
-
- retval = scsi_CDs[MINOR(cdi->dev)].device->changed;
- - scsi_CDs[MINOR(cdi->dev)].device->changed = 0;
- - /* If the disk changed, the capacity will now be different,
- - * so we force a re-read of this information */
- - if (retval) {
- + scsi_CDs[MINOR(cdi->dev)].device->changed = 0;
- + /* If the disk changed, the capacity will now be different,
- + * so we force a re-read of this information */
- + if (retval) {
- /* 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.
- - */
- - scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
- + 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.
- + */
- + scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
-
- - scsi_CDs[MINOR(cdi->dev)].sector_size = 2048;
- - }
- + scsi_CDs[MINOR(cdi->dev)].sector_size = 2048;
- + }
- return retval;
- }
-
- @@ -163,7 +175,7 @@
- * end of a SCSI read / write, and will take on of several actions based on success or failure.
- */
-
- -static void rw_intr (Scsi_Cmnd * SCpnt)
- +static void rw_intr(Scsi_Cmnd * SCpnt)
- {
- int result = SCpnt->result;
- int this_count = SCpnt->this_count;
- @@ -171,137 +183,130 @@
- int block_sectors = 0;
-
- #ifdef DEBUG
- - printk("sr.c done: %x %xn",result, SCpnt->request.bh->b_data);
- + printk("sr.c done: %x %xn", result, SCpnt->request.bh->b_data);
- #endif
- - /*
- - Handle MEDIUM ERRORs or VOLUME OVERFLOWs that indicate partial success.
- - Since this is a relatively rare error condition, no care is taken to
- - avoid unnecessary additional work such as memcpy's that could be avoided.
- - */
- + /*
- + Handle MEDIUM ERRORs or VOLUME OVERFLOWs that indicate partial success.
- + Since this is a relatively rare error condition, no care is taken to
- + avoid unnecessary additional work such as memcpy's that could be avoided.
- + */
-
- - if (driver_byte(result) != 0 && /* An error occurred */
- - SCpnt->sense_buffer[0] == 0xF0 && /* Sense data is valid */
- + if (driver_byte(result) != 0 && /* An error occurred */
- + SCpnt->sense_buffer[0] == 0xF0 && /* Sense data is valid */
- (SCpnt->sense_buffer[2] == MEDIUM_ERROR ||
- SCpnt->sense_buffer[2] == VOLUME_OVERFLOW ||
- - SCpnt->sense_buffer[2] == ILLEGAL_REQUEST))
- - {
- - long error_sector = (SCpnt->sense_buffer[3] << 24) |
- - (SCpnt->sense_buffer[4] << 16) |
- - (SCpnt->sense_buffer[5] << 8) |
- - SCpnt->sense_buffer[6];
- - int device_nr = DEVICE_NR(SCpnt->request.rq_dev);
- - if (SCpnt->request.bh != NULL)
- - block_sectors = SCpnt->request.bh->b_size >> 9;
- - if (block_sectors < 4) block_sectors = 4;
- - if (scsi_CDs[device_nr].sector_size == 2048)
- - error_sector <<= 2;
- - error_sector &= ~ (block_sectors - 1);
- - good_sectors = error_sector - SCpnt->request.sector;
- - if (good_sectors < 0 || good_sectors >= this_count)
- - good_sectors = 0;
- - /*
- - The SCSI specification allows for the value returned by READ
- - CAPACITY to be up to 75 2K sectors past the last readable
- - block. Therefore, if we hit a medium error within the last
- - 75 2K sectors, we decrease the saved size value.
- - */
- - if ((error_sector >> 1) < sr_sizes[device_nr] &&
- - scsi_CDs[device_nr].capacity - error_sector < 4*75)
- - sr_sizes[device_nr] = error_sector >> 1;
- - }
- -
- - if (good_sectors > 0)
- - { /* Some sectors were read successfully. */
- - if (SCpnt->use_sg == 0) {
- - if (SCpnt->buffer != SCpnt->request.buffer)
- - {
- - int offset;
- - offset = (SCpnt->request.sector % 4) << 9;
- - memcpy((char *)SCpnt->request.buffer,
- - (char *)SCpnt->buffer + offset,
- - good_sectors << 9);
- - /* Even though we are not using scatter-gather, we look
- - * ahead and see if there is a linked request for the
- - * other half of this buffer. If there is, then satisfy
- - * it. */
- - if((offset == 0) && good_sectors == 2 &&
- - SCpnt->request.nr_sectors > good_sectors &&
- - SCpnt->request.bh &&
- - SCpnt->request.bh->b_reqnext &&
- - SCpnt->request.bh->b_reqnext->b_size == 1024) {
- - memcpy((char *)SCpnt->request.bh->b_reqnext->b_data,
- - (char *)SCpnt->buffer + 1024,
- - 1024);
- - good_sectors += 2;
- - };
- + SCpnt->sense_buffer[2] == ILLEGAL_REQUEST)) {
- + long error_sector = (SCpnt->sense_buffer[3] << 24) |
- + (SCpnt->sense_buffer[4] << 16) |
- + (SCpnt->sense_buffer[5] << 8) |
- + SCpnt->sense_buffer[6];
- + int device_nr = DEVICE_NR(SCpnt->request.rq_dev);
- + if (SCpnt->request.bh != NULL)
- + block_sectors = SCpnt->request.bh->b_size >> 9;
- + if (block_sectors < 4)
- + block_sectors = 4;
- + if (scsi_CDs[device_nr].sector_size == 2048)
- + error_sector <<= 2;
- + error_sector &= ~(block_sectors - 1);
- + good_sectors = error_sector - SCpnt->request.sector;
- + if (good_sectors < 0 || good_sectors >= this_count)
- + good_sectors = 0;
- + /*
- + The SCSI specification allows for the value returned by READ
- + CAPACITY to be up to 75 2K sectors past the last readable
- + block. Therefore, if we hit a medium error within the last
- + 75 2K sectors, we decrease the saved size value.
- + */
- + if ((error_sector >> 1) < sr_sizes[device_nr] &&
- + scsi_CDs[device_nr].capacity - error_sector < 4 * 75)
- + sr_sizes[device_nr] = error_sector >> 1;
- + }
- + if (good_sectors > 0) { /* Some sectors were read successfully. */
- + if (SCpnt->use_sg == 0) {
- + if (SCpnt->buffer != SCpnt->request.buffer) {
- + int offset;
- + offset = (SCpnt->request.sector % 4) << 9;
- + memcpy((char *) SCpnt->request.buffer,
- + (char *) SCpnt->buffer + offset,
- + good_sectors << 9);
- + /* Even though we are not using scatter-gather, we look
- + * ahead and see if there is a linked request for the
- + * other half of this buffer. If there is, then satisfy
- + * it. */
- + if ((offset == 0) && good_sectors == 2 &&
- + SCpnt->request.nr_sectors > good_sectors &&
- + SCpnt->request.bh &&
- + SCpnt->request.bh->b_reqnext &&
- + SCpnt->request.bh->b_reqnext->b_size == 1024) {
- + memcpy((char *) SCpnt->request.bh->b_reqnext->b_data,
- + (char *) SCpnt->buffer + 1024,
- + 1024);
- + good_sectors += 2;
- + };
-
- - scsi_free(SCpnt->buffer, 2048);
- - }
- - } else {
- - struct scatterlist * sgpnt;
- - int i;
- - sgpnt = (struct scatterlist *) SCpnt->buffer;
- - for(i=0; i<SCpnt->use_sg; i++) {
- - if (sgpnt[i].alt_address) {
- - if (sgpnt[i].alt_address != sgpnt[i].address) {
- - memcpy(sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
- - };
- - scsi_free(sgpnt[i].address, sgpnt[i].length);
- + scsi_free(SCpnt->buffer, 2048);
- + }
- + } else {
- + struct scatterlist *sgpnt;
- + int i;
- + sgpnt = (struct scatterlist *) SCpnt->buffer;
- + for (i = 0; i < SCpnt->use_sg; i++) {
- + if (sgpnt[i].alt_address) {
- + if (sgpnt[i].alt_address != sgpnt[i].address) {
- + memcpy(sgpnt[i].alt_address, sgpnt[i].address, sgpnt[i].length);
- + };
- + scsi_free(sgpnt[i].address, sgpnt[i].length);
- + };
- + };
- + scsi_free(SCpnt->buffer, SCpnt->sglist_len); /* Free list of scatter-gather pointers */
- + if (SCpnt->request.sector % 4)
- + good_sectors -= 2;