patch-2.1.90 linux/drivers/block/ide-cd.c
Next file: linux/drivers/block/ide-cd.h
Previous file: linux/drivers/block/floppy.c
Back to the patch index
Back to the overall index
- Lines: 208
- Date:
Tue Mar 17 21:39:11 1998
- Orig file:
v2.1.89/linux/drivers/block/ide-cd.c
- Orig date:
Mon Feb 23 18:12:04 1998
diff -u --recursive --new-file v2.1.89/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
@@ -26,7 +26,6 @@
* (If you are using a cd changer, you may get errors in the kernel
* logs that are completly expected. Don't complain to me about this,
* unless you have a patch to fix it. I am working on it...)
- * -Implement ide_cdrom_select_speed using the generic cdrom interface
* -Fix ide_cdrom_reset so that it works (it does nothing right now)
* -Query the drive to find what features are available before trying to
* use them (like trying to close the tray in drives that can't).
@@ -189,10 +188,19 @@
* malloc'ed but never free'd when closing the device.
* -- Cleaned up the global namespace a bit by making more
* functions static that should already have been.
+ * 4.11 Mar 12, 1998 -- Added support for the CDROM_SELECT_SPEED ioctl
+ * based on a patch for 2.0.33 by Jelle Foks
+ * <jelle@scintilla.utwente.nl>, a patch for 2.0.33
+ * by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI
+ * version, and my own efforts. -erik
+ * -- Fixed a stupid bug which egcs was kind enough to
+ * inform me of where "Illegal mode for this track"
+ * was never returned due to a comparison on data
+ * types of limited range.
*
*************************************************************************/
-#define IDECD_VERSION "4.10"
+#define IDECD_VERSION "4.11"
#include <linux/module.h>
#include <linux/types.h>
@@ -271,8 +279,7 @@
printk (" Error code: 0x%02x\n", reqbuf->error_code);
- if (reqbuf->sense_key >= 0 &&
- reqbuf->sense_key < ARY_LEN (sense_key_texts))
+ if ( reqbuf->sense_key < ARY_LEN (sense_key_texts))
s = sense_key_texts[reqbuf->sense_key];
else
s = "(bad sense key)";
@@ -285,7 +292,7 @@
s = buf;
} else {
int lo, hi;
- int key = (reqbuf->asc << 8);
+ unsigned short key = (reqbuf->asc << 8);
if ( ! (reqbuf->ascq >= 0x80 && reqbuf->ascq <= 0xdd) )
key |= reqbuf->ascq;
@@ -496,7 +503,7 @@
} else if (sense_key == UNIT_ATTENTION) {
/* Check for media change. */
cdrom_saw_media_change (drive);
- printk ("%s: media changed\n", drive->name);
+ /*printk("%s: media changed\n",drive->name);*/
return 0;
} else {
/* Otherwise, print an error. */
@@ -1518,7 +1525,6 @@
return cdrom_queue_packet_command (drive, &pc);
}
-
static int
cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity,
struct atapi_request_sense *reqbuf)
@@ -1721,7 +1727,6 @@
return cdrom_queue_packet_command (drive, &pc);
}
-
static int
cdrom_mode_select (ide_drive_t *drive, int pageno, char *buf, int buflen,
struct atapi_request_sense *reqbuf)
@@ -1742,6 +1747,43 @@
}
+/* Note that this takes speed in kbytes/second, so don't try requesting
+ silly speeds like 2 here. Common speeds include:
+ 176 kbytes/second -- 1x
+ 353 kbytes/second -- 2x
+ 387 kbytes/second -- 2.2x
+ 528 kbytes/second -- 3x
+ 706 kbytes/second -- 4x
+ 1400 kbytes/second -- 8x
+ 2800 kbytes/second -- 16x
+ ATAPI drives are free to select the speed you request or any slower
+ rate :-( Requesting too fast a speed will _not_ produce an error. */
+static int
+cdrom_select_speed (ide_drive_t *drive, int speed,
+ struct atapi_request_sense *reqbuf)
+{
+ struct packet_command pc;
+ memset (&pc, 0, sizeof (pc));
+ pc.sense_data = reqbuf;
+
+ if (speed < 1)
+ speed = 0xffff; /* set to max */
+ else
+ speed *= 177; /* Nx to kbytes/s */
+
+ pc.c[0] = SET_CD_SPEED;
+ /* Read Drive speed in kbytes/second MSB */
+ pc.c[2] = (speed >> 8) & 0xff;
+ /* Read Drive speed in kbytes/second LSB */
+ pc.c[3] = speed & 0xff;
+ /* Write Drive speed in kbytes/second MSB */
+ //pc.c[4] = (speed >> 8) & 0xff;
+ /* Write Drive speed in kbytes/second LSB */
+ //pc.c[5] = speed & 0xff;
+
+ 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)
@@ -2429,6 +2471,44 @@
return cdrom_lockdoor (drive, lock, NULL);
}
+static
+int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
+{
+ int stat, attempts = 3;
+ struct {
+ char pad[8];
+ struct atapi_capabilities_page cap;
+ } buf;
+ ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ struct atapi_request_sense reqbuf;
+ stat=cdrom_select_speed (drive, speed, &reqbuf);
+ if (stat<0)
+ return stat;
+
+ /* Now that that is done, update the speed fields */
+ 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,
+ (char *)&buf, sizeof (buf), NULL);
+ } while (stat);
+
+ /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
+ if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
+ CDROM_STATE_FLAGS (drive)->current_speed =
+ (((unsigned int)buf.cap.curspeed) + (176/2)) / 176;
+ CDROM_CONFIG_FLAGS (drive)->max_speed =
+ (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176;
+ } else {
+ CDROM_STATE_FLAGS (drive)->current_speed =
+ (ntohs(buf.cap.curspeed) + (176/2)) / 176;
+ CDROM_CONFIG_FLAGS (drive)->max_speed =
+ (ntohs(buf.cap.maxspeed) + (176/2)) / 176;
+ }
+ cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed;
+ return 0;
+}
+
static
int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
@@ -2668,14 +2748,14 @@
ide_cdrom_check_media_change_real, /* media_changed */
ide_cdrom_tray_move, /* tray_move */
ide_cdrom_lock_door, /* lock_door */
- NULL, /* select_speed */
+ ide_cdrom_select_speed, /* select_speed */
ide_cdrom_select_disc, /* select_disc */
ide_cdrom_get_last_session, /* get_last_session */
ide_cdrom_get_mcn, /* get_mcn */
ide_cdrom_reset, /* reset */
ide_cdrom_audio_ioctl, /* audio_ioctl */
ide_cdrom_dev_ioctl, /* dev_ioctl */
- CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK
+ 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 */
@@ -2691,7 +2771,7 @@
devinfo->dev = MKDEV (HWIF(drive)->major, minor);
devinfo->ops = &ide_cdrom_dops;
devinfo->mask = 0;
- *(int *)&devinfo->speed = CDROM_CONFIG_FLAGS (drive)->max_speed;
+ *(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed;
*(int *)&devinfo->capacity = nslots;
devinfo->handle = (void *) drive;
strcpy(devinfo->name, drive->name);
@@ -2750,11 +2830,15 @@
/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
- CDROM_STATE_FLAGS (drive)->current_speed = (((unsigned int)buf.cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS (drive)->max_speed = (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176;
+ CDROM_STATE_FLAGS (drive)->current_speed =
+ (((unsigned int)buf.cap.curspeed) + (176/2)) / 176;
+ CDROM_CONFIG_FLAGS (drive)->max_speed =
+ (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176;
} else {
- CDROM_STATE_FLAGS (drive)->current_speed = (ntohs(buf.cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS (drive)->max_speed = (ntohs(buf.cap.maxspeed) + (176/2)) / 176;
+ CDROM_STATE_FLAGS (drive)->current_speed =
+ (ntohs(buf.cap.curspeed) + (176/2)) / 176;
+ CDROM_CONFIG_FLAGS (drive)->max_speed =
+ (ntohs(buf.cap.maxspeed) + (176/2)) / 176;
}
printk ("%s: ATAPI %dX CDROM",
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov