[patch] ide-cd update

Erik Andersen (andersee@debian.org)
Fri, 13 Mar 1998 09:45:33 -0700


The following patch should go into 2.1.90 (or .91 if I've missed it).
It fixes a bug that showed up when I switched to egcs, and adds support
for the CDROM_SELECT_SPEED ioctl to ide-cd. I also update the ide-cd docs
so people won't have to pester me about the Panasonic 24 speed drives.
It works for me, so I wan't to get this into the kernel to make sure it
works for everybody else. Simply doing a 'cat /proc/sys/dev/cdrom/info'
will show you the current speed of your cdrom drive...

-Erik

--
Erik B. Andersen   Web:    http://www.inconnect.com/~andersen/ 
                   email:  andersee@debian.org
--This message was written using 73% post-consumer electrons--

[------patch ide-cd-update---------]

diff -u --recursive --new-file linux-2.1.89.virgin/Documentation/cdrom/ide-cd linux/Documentation/cdrom/ide-cd --- linux-2.1.89.virgin/Documentation/cdrom/ide-cd Sat Feb 28 09:19:36 1998 +++ linux/Documentation/cdrom/ide-cd Thu Mar 12 17:42:37 1998 @@ -224,10 +224,8 @@ - If the autoprobing is not finding your drive, you can tell the driver to assume that one exists by using a lilo option of the form `hdX=cdrom', where X is the drive letter corresponding to - where your drive is installed (see section 2). This is required - for CDROM drives such as the Pioneer DR-A24X, which do not properly - identify themselves as ATAPI CDROM drives. Note that if you - do this and you see a boot message like + where your drive is installed. Note that if you do this and you + see a boot message like hdX: ATAPI cdrom (?) @@ -281,7 +279,16 @@ there are hardware problems with the interrupt setup; they apparently don't use interrupts. - + - If you own a Pioneer DR-A24X, you _will_ get nasty error messages + on boot such as "irq timeout: status=0x50 { DriveReady SeekComplete }" + The Pioneer DR-A24X cdrom drives are fairly popular these days. + Unfortunatly, these drives seem to become very confused when we perform + the standard Linux ATA disk drive probe. If you own one of these drives, + you can bypass the ATA probing which confuses these cdrom drives, by + adding `append="hdX=noprobe hdX=cdrom"' to your lilo.conf file and runing + lilo (again where X is the drive letter corresponding to where your drive + is installed.) + c. System hangups. - If the system locks up when you try to access the cdrom, the most diff -u --recursive --new-file linux-2.1.89.virgin/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c --- linux-2.1.89.virgin/drivers/block/ide-cd.c Sat Feb 28 09:20:16 1998 +++ linux/drivers/block/ide-cd.c Fri Mar 13 08:35:03 1998 @@ -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", diff -u --recursive --new-file linux-2.1.89.virgin/drivers/block/ide-cd.h linux/drivers/block/ide-cd.h --- linux-2.1.89.virgin/drivers/block/ide-cd.h Wed Dec 17 12:11:51 1997 +++ linux/drivers/block/ide-cd.h Fri Mar 13 07:57:58 1998 @@ -71,7 +71,7 @@ #define MODE_SENSE_10 0x5a #define MODE_SELECT_10 0x55 #define READ_CD 0xbe - +#define SET_CD_SPEED 0xbb #define LOAD_UNLOAD 0xa6 #define MECHANISM_STATUS 0xbd @@ -431,7 +431,7 @@ with additions from Tables 141 and 142 of the ATAPI 2.6 draft standard. */ struct { - short asc_ascq; + unsigned short asc_ascq; char *text; } sense_data_texts[] = { { 0x0000, "No additional sense information" },

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu