patch-2.3.16 linux/drivers/block/ide-cd.c
Next file: linux/drivers/block/ide-cd.h
Previous file: linux/drivers/block/icside.c
Back to the patch index
Back to the overall index
- Lines: 928
- Date:
Tue Aug 31 16:05:22 1999
- Orig file:
v2.3.15/linux/drivers/block/ide-cd.c
- Orig date:
Mon Aug 9 12:34:22 1999
diff -u --recursive --new-file v2.3.15/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
@@ -12,11 +12,13 @@
*
* Suggestions are welcome. Patches that work are more welcome though. ;-)
* For those wishing to work on this driver, please be sure you download
- * and comply with the latest ATAPI standard. This document can be
- * obtained by anonymous ftp from:
- * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
+ * and comply with the latest Mt. Fuji (SFF8090 version 3) and ATAPI
+ * (SFF-8020i rev 2.6) standards. These documents can be obtained by
+ * anonymous ftp from:
+ * ftp://fission.dt.wdc.com/pub/standards/SFF/specs/INF-8020.PDF
+ * ftp://fission.dt.wdc.com/pub/standards/SFF/specs/INF-8090.PDF
*
- * Drives that deviate from the ATAPI standard will be accomodated as much
+ * Drives that deviate from these standards will be accomodated as much
* as possible via compile time or command-line options. Since I only have
* a few drives, you generally need to send me patches...
*
@@ -255,11 +257,26 @@
* cd-rom drivers. don't report select disc for
* non-changers as well.
* - mask out audio playing, if the device can't do it.
- *
+ *
+ * 4.55 Sep 1, 1999 - Eliminated the rest of the audio ioctls, except
+ * for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers
+ * use this independently of the actual audio handling.
+ * They will disappear later when I get the time to
+ * do it cleanly.
+ * - Minimize the TOC reading - only do it when we
+ * know a media change has occured.
+ * - Moved all the CDROMREADx ioctls to the Uniform layer.
+ * - Heiko Eissfeldt <heiko@colossus.escape.de> supplied
+ * some fixes for CDI.
+ * - CD-ROM leaving door locked fix from Andries
+ * Brouwer <Andries.Brouwer@cwi.nl>
+ * - Erik Andersen <andersen@xmission.com> unified
+ * commands across the various drivers and how
+ * sense errors are handled.
*
*************************************************************************/
-#define IDECD_VERSION "4.54"
+#define IDECD_VERSION "4.55"
#include <linux/config.h>
#include <linux/module.h>
@@ -316,12 +333,12 @@
uses this command to poll the drive, and we don't want
to fill the syslog with useless errors. */
if (failed_command &&
- failed_command->c[0] == SCMD_READ_SUBCHANNEL)
+ failed_command->c[0] == GPCMD_READ_SUBCHANNEL)
return;
}
if (reqbuf->error_code == 0x70 && reqbuf->sense_key == 0x02
- && ((reqbuf->asc == 0x3a && reqbuf->ascq == 0x00) ||
- (reqbuf->asc == 0x04 && reqbuf->ascq == 0x01)))
+ && ((reqbuf->asc == 0x3a && reqbuf->ascq == 0x00) ||
+ (reqbuf->asc == 0x04 && reqbuf->ascq == 0x01)))
{
/*
* Suppress the following errors:
@@ -358,15 +375,16 @@
s = buf;
} else {
int lo=0, mid, hi=ARY_LEN (sense_data_texts);
- unsigned short key = (reqbuf->asc << 8);
+ unsigned long key = (reqbuf->sense_key << 16);
+ key |= (reqbuf->asc << 8);
if ( ! (reqbuf->ascq >= 0x80 && reqbuf->ascq <= 0xdd) )
key |= reqbuf->ascq;
-
s = NULL;
while (hi > lo) {
mid = (lo + hi) / 2;
- if (sense_data_texts[mid].asc_ascq == key) {
+ if (sense_data_texts[mid].asc_ascq == key ||
+ sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
s = sense_data_texts[mid].text;
break;
}
@@ -487,7 +505,7 @@
len = sizeof (*reqbuf) / 4;
len *= 4;
- pc->c[0] = REQUEST_SENSE;
+ pc->c[0] = GPCMD_REQUEST_SENSE;
pc->c[4] = (unsigned char) len;
pc->buffer = (char *)reqbuf;
pc->buflen = len;
@@ -577,7 +595,7 @@
because workman constantly polls the drive
with this command, and we don't want
to uselessly fill up the syslog. */
- if (pc->c[0] != SCMD_READ_SUBCHANNEL)
+ if (pc->c[0] != GPCMD_READ_SUBCHANNEL)
printk ("%s: tray open or drive not ready\n", drive->name);
#endif
} else if (sense_key == UNIT_ATTENTION) {
@@ -1073,7 +1091,7 @@
/* Set up the command */
memset (&pc.c, 0, sizeof (pc.c));
- pc.c[0] = READ_10;
+ pc.c[0] = GPCMD_READ_10;
pc.c[7] = (nframes >> 8);
pc.c[8] = (nframes & 0xff);
put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
@@ -1118,7 +1136,7 @@
frame = sector / SECTORS_PER_FRAME;
memset (&pc.c, 0, sizeof (pc.c));
- pc.c[0] = SEEK;
+ pc.c[0] = GPCMD_SEEK;
put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
(void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr);
}
@@ -1202,7 +1220,7 @@
if ((stat & DRQ_STAT) == 0) {
/* Some of the trailing request sense fields are optional, and
some drives don't send them. Sigh. */
- if (pc->c[0] == REQUEST_SENSE &&
+ if (pc->c[0] == GPCMD_REQUEST_SENSE &&
pc->buflen > 0 &&
pc->buflen <= 5) {
while (pc->buflen > 0) {
@@ -1372,10 +1390,10 @@
a disk. Retry, but wait a little to give
the drive time to complete the load. */
cdrom_sleep (HZ);
- } else
+ } else {
/* Otherwise, don't retry. */
retries = 0;
-
+ }
--retries;
}
@@ -1392,12 +1410,13 @@
and we think that the door is presently, lock it again.
(The door was probably unlocked via an explicit
CDROMEJECT ioctl.) */
- if (CDROM_STATE_FLAGS (drive)->door_locked == 0 && drive->usage &&
- (pc->c[0] != REQUEST_SENSE &&
- pc->c[0] != ALLOW_MEDIUM_REMOVAL &&
- pc->c[0] != START_STOP &&
- pc->c[0] != MODE_SENSE_10 &&
- pc->c[0] != MODE_SELECT_10)) {
+ if (CDROM_STATE_FLAGS (drive)->door_locked == 0 &&
+ (pc->c[0] != GPCMD_TEST_UNIT_READY &&
+ pc->c[0] != GPCMD_REQUEST_SENSE &&
+ pc->c[0] != GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL &&
+ pc->c[0] != GPCMD_START_STOP_UNIT &&
+ pc->c[0] != GPCMD_MODE_SENSE_10 &&
+ pc->c[0] != GPCMD_MODE_SELECT_10)) {
(void) cdrom_lockdoor (drive, 1, NULL);
}
return 0;
@@ -1508,7 +1527,7 @@
memset (&pc, 0, sizeof (pc));
pc.sense_data = reqbuf;
- pc.c[0] = TEST_UNIT_READY;
+ pc.c[0] = GPCMD_TEST_UNIT_READY;
#if ! STANDARD_ATAPI
/* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
@@ -1540,7 +1559,7 @@
memset (&pc, 0, sizeof (pc));
pc.sense_data = reqbuf;
- pc.c[0] = ALLOW_MEDIUM_REMOVAL;
+ pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
pc.c[4] = (lockflag != 0);
stat = cdrom_queue_packet_command (drive, &pc);
}
@@ -1585,7 +1604,7 @@
memset (&pc, 0, sizeof (pc));
pc.sense_data = reqbuf;
- pc.c[0] = START_STOP;
+ pc.c[0] = GPCMD_START_STOP_UNIT;
pc.c[4] = 0x02 + (ejectflag != 0);
return cdrom_queue_packet_command (drive, &pc);
}
@@ -1605,7 +1624,7 @@
memset (&pc, 0, sizeof (pc));
pc.sense_data = reqbuf;
- pc.c[0] = READ_CAPACITY;
+ pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
pc.buffer = (char *)&capbuf;
pc.buflen = sizeof (capbuf);
@@ -1629,7 +1648,7 @@
pc.buffer = buf;
pc.buflen = buflen;
- pc.c[0] = SCMD_READ_TOC;
+ pc.c[0] = GPCMD_READ_TOC_PMA_ATIP;
pc.c[6] = trackno;
pc.c[7] = (buflen >> 8);
pc.c[8] = (buflen & 0xff);
@@ -1657,11 +1676,10 @@
toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc),
GFP_KERNEL);
info->toc = toc;
- }
-
- if (toc == NULL) {
- printk ("%s: No cdrom TOC buffer!\n", drive->name);
- return -EIO;
+ if (toc == NULL) {
+ printk ("%s: No cdrom TOC buffer!\n", drive->name);
+ return -ENOMEM;
+ }
}
/* Check to see if the existing data is still valid.
@@ -1673,9 +1691,7 @@
/* First read just the header, so we know how long the TOC is. */
stat = cdrom_read_tocentry (drive, 0, 1, 0, (char *)&toc->hdr,
- sizeof (struct atapi_toc_header) +
- sizeof (struct atapi_toc_entry),
- reqbuf);
+ sizeof (struct atapi_toc_header), reqbuf);
if (stat) return stat;
#if ! STANDARD_ATAPI
@@ -1690,12 +1706,46 @@
if (ntracks > MAX_TRACKS) ntracks = MAX_TRACKS;
/* Now read the whole schmeer. */
- stat = cdrom_read_tocentry (drive, 0, 1, 0, (char *)&toc->hdr,
+ stat = cdrom_read_tocentry (drive, toc->hdr.first_track-1, 1, 0,
+ (char *)&toc->hdr,
sizeof (struct atapi_toc_header) +
(ntracks+1) *
- sizeof (struct atapi_toc_entry),
- reqbuf);
- if (stat) return stat;
+ sizeof (struct atapi_toc_entry), reqbuf);
+
+ if (stat && toc->hdr.first_track > 1) {
+ /* Cds with CDI tracks only don't have any TOC entries,
+ despite of this the returned values are
+ first_track == last_track = number of CDI tracks + 1,
+ so that this case is indistinguishable from the same
+ layout plus an additional audio track.
+ If we get an error for the regular case, we assume
+ a CDI without additional audio tracks. In this case
+ the readable TOC is empty (CDI tracks are not included)
+ and only holds the Leadout entry. Heiko Eißfeldt */
+ ntracks = 0;
+ stat = cdrom_read_tocentry (drive, CDROM_LEADOUT, 1,
+ 0, (char *)&toc->hdr,
+ sizeof (struct atapi_toc_header) +
+ (ntracks+1) *
+ sizeof (struct atapi_toc_entry),
+ reqbuf);
+ if (stat) {
+ return stat;
+ }
+#if ! STANDARD_ATAPI
+ if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {
+ toc->hdr.first_track = bin2bcd(CDROM_LEADOUT);
+ toc->hdr.last_track = bin2bcd(CDROM_LEADOUT);
+ } else
+#endif /* not STANDARD_ATAPI */
+ {
+ toc->hdr.first_track = CDROM_LEADOUT;
+ toc->hdr.last_track = CDROM_LEADOUT;
+ }
+ } else if (stat) {
+ return stat;
+ }
+
toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
#if ! STANDARD_ATAPI
@@ -1719,10 +1769,18 @@
}
/* Read the multisession information. */
- stat = cdrom_read_tocentry (drive, 0, 1, 1,
- (char *)&ms_tmp, sizeof (ms_tmp),
- reqbuf);
- if (stat) return stat;
+ if (toc->hdr.first_track != CDROM_LEADOUT) {
+ /* Read the multisession information. */
+ stat = cdrom_read_tocentry (drive, toc->hdr.first_track-1, 1, 1,
+ (char *)&ms_tmp, sizeof (ms_tmp),
+ reqbuf);
+ if (stat) return stat;
+ } else {
+ ms_tmp.ent.addr.msf.minute = 0;
+ ms_tmp.ent.addr.msf.second = 2;
+ ms_tmp.ent.addr.msf.frame = 0;
+ ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
+ }
#if ! STANDARD_ATAPI
if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd)
@@ -1736,7 +1794,10 @@
toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
/* Now try to get the total cdrom capacity. */
- stat = cdrom_read_capacity (drive, &toc->capacity, reqbuf);
+ stat = cdrom_get_last_written(MKDEV(HWIF(drive)->major,
+ drive->select.b.unit << PARTN_BITS),
+ (long *)&toc->capacity);
+ if (stat) stat = cdrom_read_capacity (drive, &toc->capacity, reqbuf);
if (stat) toc->capacity = 0x1fffff;
HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS]
@@ -1762,7 +1823,7 @@
pc.buffer = buf;
pc.buflen = buflen;
- pc.c[0] = SCMD_READ_SUBCHANNEL;
+ pc.c[0] = GPCMD_READ_SUBCHANNEL;
pc.c[1] = 2; /* MSF addressing */
pc.c[2] = 0x40; /* request subQ data */
pc.c[3] = format;
@@ -1785,7 +1846,7 @@
pc.buffer = buf;
pc.buflen = buflen;
- pc.c[0] = MODE_SENSE_10;
+ pc.c[0] = GPCMD_MODE_SENSE_10;
pc.c[2] = pageno | (modeflag << 6);
pc.c[7] = (buflen >> 8);
pc.c[8] = (buflen & 0xff);
@@ -1803,7 +1864,7 @@
pc.buffer = buf;
pc.buflen = - buflen;
- pc.c[0] = MODE_SELECT_10;
+ pc.c[0] = GPCMD_MODE_SELECT_10;
pc.c[1] = 0x10;
pc.c[2] = pageno;
pc.c[7] = (buflen >> 8);
@@ -1826,7 +1887,7 @@
else
speed *= 177; /* Nx to kbytes/s */
- pc.c[0] = SET_CD_SPEED;
+ pc.c[0] = GPCMD_SET_SPEED;
/* Read Drive speed in kbytes/second MSB */
pc.c[2] = (speed >> 8) & 0xff;
/* Read Drive speed in kbytes/second LSB */
@@ -1842,67 +1903,6 @@
return cdrom_queue_packet_command (drive, &pc);
}
-static int
-cdrom_play_lba_range_1 (ide_drive_t *drive, int lba_start, int lba_end,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = SCMD_PLAYAUDIO_MSF;
- lba_to_msf (lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
- lba_to_msf (lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd) {
- pc.c[3] = bin2bcd (pc.c[3]);
- pc.c[4] = bin2bcd (pc.c[4]);
- pc.c[5] = bin2bcd (pc.c[5]);
- pc.c[6] = bin2bcd (pc.c[6]);
- pc.c[7] = bin2bcd (pc.c[7]);
- pc.c[8] = bin2bcd (pc.c[8]);
- }
-#endif /* not STANDARD_ATAPI */
-
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-/* Play audio starting at LBA LBA_START and finishing with the
- LBA before LBA_END. */
-static int
-cdrom_play_lba_range (ide_drive_t *drive, int lba_start, int lba_end,
- struct atapi_request_sense *reqbuf)
-{
- int i, stat = 0;
- struct atapi_request_sense my_reqbuf;
-
- if (reqbuf == NULL)
- reqbuf = &my_reqbuf;
-
- /* Some drives, will, for certain audio cds,
- give an error if you ask them to play the entire cd using the
- values which are returned in the TOC. The play will succeed,
- however, if the ending address is adjusted downwards
- by a few frames. */
- for (i=0; i<75; i++) {
- stat = cdrom_play_lba_range_1 (drive, lba_start, lba_end,
- reqbuf);
-
- if (stat == 0 ||
- !(reqbuf->sense_key == ILLEGAL_REQUEST &&
- reqbuf->asc == 0x24))
- return stat;
-
- --lba_end;
- if (lba_end <= lba_start) break;
- }
-
- return stat;
-}
-
static
int cdrom_get_toc_entry (ide_drive_t *drive, int track,
@@ -1910,17 +1910,12 @@
struct atapi_request_sense *reqbuf)
{
struct cdrom_info *info = drive->driver_data;
- int stat, ntracks;
- struct atapi_toc *toc;
-
- /* Make sure our saved TOC is valid. */
- stat = cdrom_read_toc (drive, reqbuf);
- if (stat) return stat;
-
- toc = info->toc;
+ struct atapi_toc *toc = info->toc;
+ int ntracks;
/* Check validity of requested track number. */
ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
+ if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0;
if (track == CDROM_LEADOUT)
*ent = &toc->ent[ntracks];
else if (track < toc->hdr.first_track ||
@@ -1933,44 +1928,6 @@
}
-static int
-cdrom_read_block (ide_drive_t *drive, int format, int lba, int nblocks,
- char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
- struct atapi_request_sense my_reqbuf;
-
- if (reqbuf == NULL)
- reqbuf = &my_reqbuf;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.buffer = buf;
- pc.buflen = buflen;
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->nec260)
- pc.c[0] = 0xd4;
- else
-#endif /* not STANDARD_ATAPI */
- pc.c[0] = READ_CD;
-
- pc.c[1] = (format << 2);
- put_unaligned(htonl(lba), (unsigned int *) &pc.c[2]);
- pc.c[8] = (nblocks & 0xff);
- pc.c[7] = ((nblocks>>8) & 0xff);
- pc.c[6] = ((nblocks>>16) & 0xff);
- if (format <= 1)
- pc.c[9] = 0xf8; /* returns 2352 for any format */
- else
- pc.c[9] = 0x10;
-
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
/* If SLOT<0, unload the current slot. Otherwise, try to load SLOT. */
static int
cdrom_load_unload (ide_drive_t *drive, int slot,
@@ -2005,7 +1962,7 @@
memset (&pc, 0, sizeof (pc));
pc.sense_data = reqbuf;
- pc.c[0] = LOAD_UNLOAD;
+ pc.c[0] = GPCMD_LOAD_UNLOAD;
pc.c[4] = 2 + (slot >= 0);
pc.c[8] = slot;
return cdrom_queue_packet_command (drive, &pc);
@@ -2026,7 +1983,7 @@
pc.buffer = buf;
pc.buflen = buflen;
- pc.c[0] = MECHANISM_STATUS;
+ pc.c[0] = GPCMD_MECHANISM_STATUS;
pc.c[8] = (buflen >> 8);
pc.c[9] = (buflen & 0xff);
return cdrom_queue_packet_command (drive, &pc);
@@ -2098,124 +2055,8 @@
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct cdrom_info *info = drive->driver_data;
-
switch (cmd) {
- case CDROMREADRAW:
- case CDROMREADMODE1:
- case CDROMREADMODE2: {
- struct cdrom_msf msf;
- int blocksize, format, stat, lba;
- struct atapi_toc *toc;
- char *buf;
-
- if (cmd == CDROMREADMODE1) {
- blocksize = CD_FRAMESIZE;
- format = 2;
- } else { /* for RAW and MODE2. */
- blocksize = CD_FRAMESIZE_RAW;
- format = 0;
- }
-
- copy_from_user_ret(&msf, (void *)arg, sizeof (msf), -EFAULT);
-
- lba = msf_to_lba(msf.cdmsf_min0,
- msf.cdmsf_sec0,
- msf.cdmsf_frame0);
-
- /* Make sure the TOC is up to date. */
- if (cmd != CDROMREADRAW) {
- stat = cdrom_read_toc (drive, NULL);
- if (stat)
- return stat;
-
- toc = info->toc;
-
- if (lba < 0 || lba >= toc->capacity)
- return -EINVAL;
- }
-
- buf = (char *) kmalloc (blocksize, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- stat = cdrom_read_block (drive, format, lba, 1, buf,
- blocksize, NULL);
-
- if (stat == 0) {
- if (cmd == CDROMREADMODE2) {
- /* For Mode2, skip the Sync, Header, and Subheader */
- copy_to_user_ret((char *)arg, buf+16, CD_FRAMESIZE_RAW0, -EFAULT);
- } else {
- copy_to_user_ret((char *)arg, buf, blocksize, -EFAULT);
- }
- }
-
- kfree (buf);
- return stat;
- }
-
- /* Read 2352 byte blocks from audio tracks. */
- case CDROMREADAUDIO: {
- int stat, lba;
- struct atapi_toc *toc;
- struct cdrom_read_audio ra;
- char *buf;
-
- /* Make sure the TOC is up to date. */
- stat = cdrom_read_toc (drive, NULL);
- if (stat) return stat;
-
- toc = info->toc;
-
- if (copy_from_user(&ra, (void *)arg, sizeof (ra)))
- return -EFAULT;
-
- if (ra.nframes < 0 || ra.nframes > toc->capacity)
- return -EINVAL;
- else if (ra.nframes == 0)
- return 0;
-
- if (!access_ok(VERIFY_WRITE, ra.buf, ra.nframes * CD_FRAMESIZE_RAW))
- return -EFAULT;
-
- 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;
-
- if (lba < 0 || lba >= toc->capacity)
- return -EINVAL;
-
- buf = (char *) kmalloc (CDROM_NBLOCKS_BUFFER*CD_FRAMESIZE_RAW,
- GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- while (ra.nframes > 0) {
- int this_nblocks = ra.nframes;
- if (this_nblocks > CDROM_NBLOCKS_BUFFER)
- this_nblocks = CDROM_NBLOCKS_BUFFER;
- stat = cdrom_read_block
- (drive, 1, lba, this_nblocks,
- buf, this_nblocks * CD_FRAMESIZE_RAW, NULL);
- if (stat) break;
-
- __copy_to_user(ra.buf, buf,this_nblocks * CD_FRAMESIZE_RAW);
- ra.buf += this_nblocks * CD_FRAMESIZE_RAW;
- ra.nframes -= this_nblocks;
- lba += this_nblocks;
- }
-
- kfree (buf);
- return stat;
- }
-
case CDROMSETSPINDOWN: {
char spindown;
char buffer[16];
@@ -2224,13 +2065,13 @@
if (copy_from_user(&spindown, (void *) arg, sizeof(char)))
return -EFAULT;
- stat = cdrom_mode_sense (drive, PAGE_CDROM, 0, buffer,
+ stat = cdrom_mode_sense (drive, GPMODE_CDROM_PAGE, 0, buffer,
sizeof (buffer), NULL);
if (stat) return stat;
buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
- return cdrom_mode_select (drive, PAGE_CDROM, buffer,
+ return cdrom_mode_select (drive, GPMODE_CDROM_PAGE, buffer,
sizeof (buffer), NULL);
}
@@ -2239,7 +2080,7 @@
char buffer[16];
int stat;
- stat = cdrom_mode_sense (drive, PAGE_CDROM, 0, buffer,
+ stat = cdrom_mode_sense (drive, GPMODE_CDROM_PAGE, 0, buffer,
sizeof (buffer), NULL);
if (stat) return stat;
@@ -2251,64 +2092,12 @@
return 0;
}
-#ifdef ALLOW_TEST_PACKETS
- case 0x1234: {
- int stat;
- struct packet_command pc;
- int len, lena;
-
- memset (&pc, 0, sizeof (pc));
-
- if (copy_from_user(&pc.c, (void *) arg, sizeof (pc.c)))
- return -EFAULT;
-
- arg += sizeof (pc.c);
-
- if (copy_from_user (&len, (void *) arg , sizeof (len)))
- return -EFAULT;
-
- arg += sizeof (len);
-
- lena = len;
- if (lena < 0) lena = -lena;
-
- {
- char buf[lena];
- if (len > 0) {
- stat = verify_area (VERIFY_WRITE,
- (void *) arg, len);
- if (stat) return stat;
- }
- else if (len < 0) {
- stat = verify_area (VERIFY_READ,
- (void *) arg, -len);
- if (stat) return stat;
- copy_from_user (buf, (void*)arg, -len);
- }
-
- if (len != 0) {
- pc.buflen = len;
- pc.buffer = buf;
- }
-
- stat = cdrom_queue_packet_command (drive, &pc);
-
- if (len > 0)
- copy_to_user ((void *)arg, buf, len);
- }
-
- return stat;
- }
-#endif
-
default:
return -EINVAL;
}
}
-
-
static
int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
unsigned int cmd, void *arg)
@@ -2318,47 +2107,6 @@
struct cdrom_info *info = drive->driver_data;
switch (cmd) {
- case CDROMSUBCHNL: {
- struct atapi_cdrom_subchnl scbuf;
- int stat;
- struct cdrom_subchnl *subchnl = (struct cdrom_subchnl *)arg;
-
- stat = cdrom_read_subchannel (drive, 1, /* current position */
- (char *)&scbuf, sizeof (scbuf),
- NULL);
- if (stat) return stat;
-
-#if ! STANDARD_ATAPI
- if (CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd) {
- msf_from_bcd (&scbuf.acdsc_absaddr.msf);
- msf_from_bcd (&scbuf.acdsc_reladdr.msf);
- }
- if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd)
- scbuf.acdsc_trk = bcd2bin (scbuf.acdsc_trk);
-#endif /* not STANDARD_ATAPI */
-
- subchnl->cdsc_absaddr.msf.minute =
- scbuf.acdsc_absaddr.msf.minute;
- subchnl->cdsc_absaddr.msf.second =
- scbuf.acdsc_absaddr.msf.second;
- subchnl->cdsc_absaddr.msf.frame =
- scbuf.acdsc_absaddr.msf.frame;
-
- subchnl->cdsc_reladdr.msf.minute =
- scbuf.acdsc_reladdr.msf.minute;
- subchnl->cdsc_reladdr.msf.second =
- scbuf.acdsc_reladdr.msf.second;
- subchnl->cdsc_reladdr.msf.frame =
- scbuf.acdsc_reladdr.msf.frame;
-
- subchnl->cdsc_audiostatus = scbuf.acdsc_audiostatus;
- subchnl->cdsc_ctrl = scbuf.acdsc_ctrl;
- subchnl->cdsc_trk = scbuf.acdsc_trk;
- subchnl->cdsc_ind = scbuf.acdsc_ind;
-
- return 0;
- }
-
case CDROMREADTOCHDR: {
int stat;
struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
@@ -2386,55 +2134,22 @@
tocentry->cdte_ctrl = toce->control;
tocentry->cdte_adr = toce->adr;
- tocentry->cdte_format = CDROM_LBA;
- tocentry->cdte_addr.lba = toce->addr.lba;
+ if (tocentry->cdte_format == CDROM_MSF) {
+ lba_to_msf (toce->addr.lba,
+ &tocentry->cdte_addr.msf.minute,
+ &tocentry->cdte_addr.msf.second,
+ &tocentry->cdte_addr.msf.frame);
+ } else
+ tocentry->cdte_addr.lba = toce->addr.lba;
return 0;
}
- case CDROMPLAYMSF: {
- struct cdrom_msf *msf = (struct cdrom_msf *) arg;
- int lba_start, lba_end;
-
- lba_start = msf_to_lba (msf->cdmsf_min0, msf->cdmsf_sec0,
- msf->cdmsf_frame0);
- lba_end = msf_to_lba (msf->cdmsf_min1, msf->cdmsf_sec1,
- msf->cdmsf_frame1) + 1;
-
- if (lba_end <= lba_start) return -EINVAL;
-
- return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
- }
-
- /* Like just about every other Linux cdrom driver, we ignore the
- index part of the request here. */
- case CDROMPLAYTRKIND: {
- int stat, lba_start, lba_end;
- struct cdrom_ti *ti = (struct cdrom_ti *)arg;
- struct atapi_toc_entry *first_toc, *last_toc;
-
- stat = cdrom_get_toc_entry (drive, ti->cdti_trk0, &first_toc,
- NULL);
- if (stat) return stat;
- stat = cdrom_get_toc_entry (drive, ti->cdti_trk1, &last_toc,
- NULL);
- if (stat) return stat;
-
- if (ti->cdti_trk1 != CDROM_LEADOUT) ++last_toc;
- lba_start = first_toc->addr.lba;
- lba_end = last_toc->addr.lba;
-
- if (lba_end <= lba_start) return -EINVAL;
-
- return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
- }
-
default:
return -EINVAL;
}
}
-
static
int ide_cdrom_reset (struct cdrom_device_info *cdi)
{
@@ -2486,7 +2201,7 @@
do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
if (attempts-- <= 0)
return 0;
- stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0,
+ stat = cdrom_mode_sense (drive, GPMODE_CAPABILITIES_PAGE, 0,
(char *)&buf, sizeof (buf), NULL);
} while (stat);
@@ -2579,12 +2294,6 @@
if (stat && my_reqbuf.sense_key == NOT_READY)
return -ENOENT;
- if (stat == 0 || my_reqbuf.sense_key == UNIT_ATTENTION) {
- stat = cdrom_read_toc (drive, &my_reqbuf);
- if (stat)
- return stat;
- }
-
if (was_locked)
(void) cdrom_lockdoor (drive, 1, NULL);
@@ -2639,15 +2348,10 @@
int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
struct cdrom_multisession *ms_info)
{
- int stat;
struct atapi_toc *toc;
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct cdrom_info *info = drive->driver_data;
- /* Make sure the TOC information is valid. */
- stat = cdrom_read_toc (drive, NULL);
- if (stat) return stat;
-
toc = info->toc;
ms_info->addr.lba = toc->last_session_lba;
ms_info->xa_flag = toc->xa_flag;
@@ -2655,7 +2359,6 @@
return 0;
}
-
static
int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
struct cdrom_mcn *mcn_info)
@@ -2689,9 +2392,9 @@
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct cdrom_info *info = drive->driver_data;
-
+ struct atapi_request_sense reqbuf;
int retval;
-
+
if (slot_nr == CDSL_CURRENT) {
(void) cdrom_check_status (drive, NULL);
retval = CDROM_STATE_FLAGS (drive)->media_changed;
@@ -2717,7 +2420,17 @@
retval = ci->slots[slot_nr].change;
}
-
+
+ /* if the media has changed, check if a disc is in the drive
+ and read the toc info. */
+ if (retval || !CDROM_STATE_FLAGS (drive)->toc_valid) {
+ /* if cdrom_read_toc fails, return 1 to indicate
+ that a disc change has occured. there might not
+ be a disc in the drive. */
+ if ((retval = cdrom_read_toc (drive, &reqbuf)))
+ return 1;
+ }
+
return retval;
}
@@ -2819,7 +2532,7 @@
do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
if (attempts-- <= 0)
return 0;
- stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0,
+ stat = cdrom_mode_sense (drive, GPMODE_CAPABILITIES_PAGE, 0,
(char *)&buf, sizeof (buf), NULL);
} while (stat);
@@ -2989,7 +2702,7 @@
drive->special.all = 0;
drive->ready_stat = 0;
- CDROM_STATE_FLAGS (drive)->media_changed = 0;
+ CDROM_STATE_FLAGS (drive)->media_changed = 1;
CDROM_STATE_FLAGS (drive)->toc_valid = 0;
CDROM_STATE_FLAGS (drive)->door_locked = 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)