patch-2.3.13 linux/drivers/block/ide-cd.c
Next file: linux/drivers/block/ide-cd.h
Previous file: linux/drivers/block/hpt366.c
Back to the patch index
Back to the overall index
- Lines: 464
- Date:
Mon Aug 9 12:34:22 1999
- Orig file:
v2.3.12/linux/drivers/block/ide-cd.c
- Orig date:
Wed Jul 21 15:46:48 1999
diff -u --recursive --new-file v2.3.12/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
@@ -2,7 +2,7 @@
* linux/drivers/block/ide-cd.c
* Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
* Copyright (C) 1996-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.
@@ -243,11 +243,23 @@
* Useful when using ide-cd in conjunction with
* ide-scsi. TODO: non-modular way of doing the
* same.
+ *
+ * 4.54 Aug 5, 1999 - Support for MMC2 class commands through the generic
+ * packet interface to cdrom.c.
+ * - Unified audio ioctl support, most of it.
+ * - cleaned up various deprecated verify_area().
+ * - Added ide_cdrom_packet() as the interface for
+ * the Uniform generic_packet().
+ * - bunch of other stuff, will fill in logs later.
+ * - report 1 slot for non-changers, like the other
+ * cd-rom drivers. don't report select disc for
+ * non-changers as well.
+ * - mask out audio playing, if the device can't do it.
*
*
*************************************************************************/
-
-#define IDECD_VERSION "4.53"
+
+#define IDECD_VERSION "4.54"
#include <linux/config.h>
#include <linux/module.h>
@@ -517,8 +529,8 @@
int *stat_ret)
{
struct request *rq = HWGROUP(drive)->rq;
- int stat, err, sense_key, cmd;
-
+ int stat, cmd, err, sense_key;
+
/* Check for errors. */
stat = GET_STAT();
*stat_ret = stat;
@@ -526,8 +538,8 @@
if (OK_STAT (stat, good_stat, BAD_R_STAT))
return 0;
- /* Got an error. */
- err = IN_BYTE (IDE_ERROR_REG);
+ /* Get the IDE error register. */
+ err = GET_ERR();
sense_key = err >> 4;
if (rq == NULL)
@@ -1170,8 +1182,6 @@
cdrom_lockdoor (ide_drive_t *drive, int lockflag,
struct atapi_request_sense *reqbuf);
-
-
/* Interrupt routine for packet command completion. */
static void cdrom_pc_intr (ide_drive_t *drive)
{
@@ -1385,14 +1395,15 @@
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] != START_STOP &&
+ pc->c[0] != MODE_SENSE_10 &&
+ pc->c[0] != MODE_SELECT_10)) {
(void) cdrom_lockdoor (drive, 1, NULL);
}
return 0;
}
}
-
/****************************************************************************
* cdrom driver request routine.
*/
@@ -1518,7 +1529,7 @@
struct atapi_request_sense my_reqbuf;
int stat;
struct packet_command pc;
-
+
if (reqbuf == NULL)
reqbuf = &my_reqbuf;
@@ -1564,45 +1575,18 @@
{
struct packet_command pc;
- if (CDROM_CONFIG_FLAGS (drive)->no_eject==1 && ejectflag==0)
+ if (CDROM_CONFIG_FLAGS (drive)->no_eject && !ejectflag)
return -EDRIVE_CANT_DO_THIS;
+
+ /* reload fails on some drives, if the tray is locked */
+ if (CDROM_STATE_FLAGS (drive)->door_locked && ejectflag)
+ return 0;
memset (&pc, 0, sizeof (pc));
pc.sense_data = reqbuf;
pc.c[0] = START_STOP;
- pc.c[4] = 2 + (ejectflag != 0);
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-static int
-cdrom_pause (ide_drive_t *drive, int pauseflag,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = SCMD_PAUSE_RESUME;
- pc.c[8] = !pauseflag;
- return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-static int
-cdrom_startstop (ide_drive_t *drive, int startflag,
- struct atapi_request_sense *reqbuf)
-{
- struct packet_command pc;
-
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
- pc.c[0] = START_STOP;
- pc.c[1] = 1;
- pc.c[4] = startflag;
+ pc.c[4] = 0x02 + (ejectflag != 0);
return cdrom_queue_packet_command (drive, &pc);
}
@@ -1611,8 +1595,8 @@
struct atapi_request_sense *reqbuf)
{
struct {
- unsigned lba;
- unsigned blocklen;
+ __u32 lba;
+ __u32 blocklen;
} capbuf;
int stat;
@@ -1892,7 +1876,7 @@
cdrom_play_lba_range (ide_drive_t *drive, int lba_start, int lba_end,
struct atapi_request_sense *reqbuf)
{
- int i, stat;
+ int i, stat = 0;
struct atapi_request_sense my_reqbuf;
if (reqbuf == NULL)
@@ -2048,7 +2032,6 @@
return cdrom_queue_packet_command (drive, &pc);
}
-
/* Read the drive mechanism status and slot table into our internal buffer.
If the buffer does not yet exist, allocate it. */
static int
@@ -2090,6 +2073,24 @@
NULL);
}
+/* the generic packet interface to cdrom.c */
+static int ide_cdrom_packet(struct cdrom_device_info *cdi,
+ struct cdrom_generic_command *cgc)
+{
+ struct packet_command pc;
+ ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+
+ /* here we queue the commands from the uniform CD-ROM
+ layer. the packet must be complete, as we do not
+ touch it at all. */
+ memset(&pc, 0, sizeof(pc));
+ memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE);
+ pc.buffer = cgc->buffer;
+ pc.buflen = cgc->buflen;
+ cgc->stat = cdrom_queue_packet_command(drive, &pc);
+ return cgc->stat;
+}
+
static
int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
@@ -2168,19 +2169,16 @@
toc = info->toc;
- stat = verify_area (VERIFY_READ, (char *)arg, sizeof (ra));
- if (stat) return stat;
-
- copy_from_user (&ra, (void *)arg, sizeof (ra));
+ 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;
- stat = verify_area (VERIFY_WRITE, (char *)ra.buf,
- ra.nframes * CD_FRAMESIZE_RAW);
- if (stat) return stat;
+ 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,
@@ -2208,8 +2206,7 @@
buf, this_nblocks * CD_FRAMESIZE_RAW, NULL);
if (stat) break;
- copy_to_user (ra.buf, buf,
- this_nblocks * CD_FRAMESIZE_RAW);
+ __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;
@@ -2224,11 +2221,8 @@
char buffer[16];
int stat;
- stat = verify_area (VERIFY_READ, (void *) arg,
- sizeof (char));
- if (stat) return stat;
-
- copy_from_user (&spindown, (void *) arg, sizeof(char));
+ if (copy_from_user(&spindown, (void *) arg, sizeof(char)))
+ return -EFAULT;
stat = cdrom_mode_sense (drive, PAGE_CDROM, 0, buffer,
sizeof (buffer), NULL);
@@ -2245,17 +2239,14 @@
char buffer[16];
int stat;
- stat = verify_area (VERIFY_WRITE, (void *) arg,
- sizeof (char));
- if (stat) return stat;
-
stat = cdrom_mode_sense (drive, PAGE_CDROM, 0, buffer,
sizeof (buffer), NULL);
if (stat) return stat;
spindown = buffer[11] & 0x0f;
- copy_to_user ((void *) arg, &spindown, sizeof (char));
+ if (copy_to_user((void *) arg, &spindown, sizeof (char)))
+ return -EFAULT;
return 0;
}
@@ -2268,14 +2259,14 @@
memset (&pc, 0, sizeof (pc));
- stat = verify_area (VERIFY_READ, (void *) arg, sizeof (pc.c));
- if (stat) return stat;
- copy_from_user (&pc.c, (void *) arg, sizeof (pc.c));
+ if (copy_from_user(&pc.c, (void *) arg, sizeof (pc.c)))
+ return -EFAULT;
+
arg += sizeof (pc.c);
- stat = verify_area (VERIFY_READ, (void *) arg, sizeof (len));
- if (stat) return stat;
- copy_from_user (&len, (void *) arg , sizeof (len));
+ if (copy_from_user (&len, (void *) arg , sizeof (len)))
+ return -EFAULT;
+
arg += sizeof (len);
lena = len;
@@ -2438,70 +2429,6 @@
return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
}
- case CDROMVOLCTRL: {
- struct cdrom_volctrl *volctrl = (struct cdrom_volctrl *) arg;
- char buffer[24], mask[24];
- int stat;
-
- stat = cdrom_mode_sense (drive, PAGE_AUDIO, 0, buffer,
- sizeof (buffer), NULL);
- if (stat) return stat;
- stat = cdrom_mode_sense (drive, PAGE_AUDIO, 1, mask,
- sizeof (buffer), NULL);
- if (stat) return stat;
-
- buffer[1] = buffer[2] = 0;
-
- buffer[17] = volctrl->channel0 & mask[17];
- buffer[19] = volctrl->channel1 & mask[19];
- buffer[21] = volctrl->channel2 & mask[21];
- buffer[23] = volctrl->channel3 & mask[23];
-
- return cdrom_mode_select (drive, PAGE_AUDIO, buffer,
- sizeof (buffer), NULL);
- }
-
- case CDROMVOLREAD: {
- struct cdrom_volctrl *volctrl = (struct cdrom_volctrl *) arg;
- char buffer[24];
- int stat;
-
- stat = cdrom_mode_sense (drive, PAGE_AUDIO, 0, buffer,
- sizeof (buffer), NULL);
- if (stat) return stat;
-
- volctrl->channel0 = buffer[17];
- volctrl->channel1 = buffer[19];
- volctrl->channel2 = buffer[21];
- volctrl->channel3 = buffer[23];
-
- return 0;
- }
-
- case CDROMSTART:
- return cdrom_startstop (drive, 1, NULL);
-
- case CDROMSTOP: {
-#ifdef IHAVEADOLPHIN
- /* Certain Drives require this. Most don't
- and will produce errors upon CDROMSTOP
- pit says the Dolphin needs this. If you
- own a dolphin, just define IHAVEADOLPHIN somewhere */
- int stat;
- stat = cdrom_startstop (drive, 0, NULL);
- if (stat) return stat;
- return cdrom_eject (drive, 1, NULL);
-#endif /* end of IHAVEADOLPHIN */
- return cdrom_startstop (drive, 0, NULL);
- }
-
- case CDROMPAUSE:
- return cdrom_pause (drive, 1, NULL);
-
- case CDROMRESUME:
- return cdrom_pause (drive, 0, NULL);
-
-
default:
return -EINVAL;
}
@@ -2534,7 +2461,6 @@
return cdrom_eject (drive, !position, NULL);
}
-
static
int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
{
@@ -2835,9 +2761,11 @@
ide_cdrom_dev_ioctl, /* dev_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, /* capability */
- 0 /* n_minors */
+ | 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, /* capability */
+ 0, /* n_minors */
+ ide_cdrom_packet
};
static int ide_cdrom_register (ide_drive_t *drive, int nslots)
@@ -2853,6 +2781,25 @@
*(int *)&devinfo->capacity = nslots;
devinfo->handle = (void *) drive;
strcpy(devinfo->name, drive->name);
+
+ /* set capability mask to match the probe. */
+ if (!CDROM_CONFIG_FLAGS (drive)->cd_r)
+ devinfo->mask |= CDC_CD_R;
+ if (!CDROM_CONFIG_FLAGS (drive)->cd_rw)
+ devinfo->mask |= CDC_CD_RW;
+ if (!CDROM_CONFIG_FLAGS (drive)->dvd)
+ devinfo->mask |= CDC_DVD;
+ if (!CDROM_CONFIG_FLAGS (drive)->dvd_r)
+ devinfo->mask |= CDC_DVD_R;
+ if (!CDROM_CONFIG_FLAGS (drive)->dvd_ram)
+ devinfo->mask |= CDC_DVD_RAM;
+ if (!CDROM_CONFIG_FLAGS (drive)->is_changer)
+ devinfo->mask |= CDC_SELECT_DISC;
+ if (!CDROM_CONFIG_FLAGS (drive)->audio_play)
+ devinfo->mask |= CDC_PLAY_AUDIO;
+ if (!CDROM_CONFIG_FLAGS (drive)->close_tray)
+ devinfo->mask |= CDC_CLOSE_TRAY;
+
return register_cdrom (devinfo);
}
@@ -2860,7 +2807,7 @@
static
int ide_cdrom_probe_capabilities (ide_drive_t *drive)
{
- int stat, nslots = 0, attempts = 3;
+ int stat, nslots = 1, attempts = 3;
struct {
char pad[8];
struct atapi_capabilities_page cap;
@@ -2891,7 +2838,11 @@
if (buf.cap.dvd_ram_write)
CDROM_CONFIG_FLAGS (drive)->dvd_r = 1;
if (buf.cap.dvd_r_write)
- CDROM_CONFIG_FLAGS (drive)->dvd_rw = 1;
+ CDROM_CONFIG_FLAGS (drive)->dvd_ram = 1;
+ if (buf.cap.audio_play)
+ CDROM_CONFIG_FLAGS (drive)->audio_play = 1;
+ if (buf.cap.mechtype == 0)
+ CDROM_CONFIG_FLAGS (drive)->close_tray = 0;
#if ! STANDARD_ATAPI
if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) {
@@ -2931,10 +2882,10 @@
drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed,
(CDROM_CONFIG_FLAGS (drive)->dvd) ? "DVD-ROM" : "CD-ROM");
- if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_rw)
+ if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram)
printk (" DVD%s%s",
- (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-RAM" : "",
- (CDROM_CONFIG_FLAGS (drive)->dvd_rw)? "/RW" : "");
+ (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-R" : "",
+ (CDROM_CONFIG_FLAGS (drive)->dvd_ram)? "AM" : "");
if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw)
printk (" CD%s%s",
@@ -3060,9 +3011,11 @@
CDROM_CONFIG_FLAGS (drive)->test_write = 0;
CDROM_CONFIG_FLAGS (drive)->dvd = 0;
CDROM_CONFIG_FLAGS (drive)->dvd_r = 0;
- CDROM_CONFIG_FLAGS (drive)->dvd_rw = 0;
+ CDROM_CONFIG_FLAGS (drive)->dvd_ram = 0;
CDROM_CONFIG_FLAGS (drive)->no_eject = 1;
CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0;
+ CDROM_CONFIG_FLAGS (drive)->audio_play = 0;
+ CDROM_CONFIG_FLAGS (drive)->close_tray = 1;
/* limit transfer size per interrupt. */
CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0;
@@ -3195,7 +3148,6 @@
(MKDEV (HWIF (drive)->major,
(drive->select.b.unit)<<PARTN_BITS));
}
-
static
int ide_cdrom_cleanup(ide_drive_t *drive)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)