patch-2.1.62 linux/drivers/scsi/sr_vendor.c
Next file: linux/fs/dquot.c
Previous file: linux/drivers/scsi/sr_ioctl.c
Back to the patch index
Back to the overall index
- Lines: 386
- Date:
Mon Nov 3 09:50:20 1997
- Orig file:
v2.1.61/linux/drivers/scsi/sr_vendor.c
- Orig date:
Tue Sep 23 16:48:48 1997
diff -u --recursive --new-file v2.1.61/linux/drivers/scsi/sr_vendor.c linux/drivers/scsi/sr_vendor.c
@@ -6,6 +6,12 @@
* the like) are to new to be included into the SCSI-II standard (to
* be exact: there is'nt anything in my draft copy).
*
+ * Aug 1997: Ha! Got a SCSI-3 cdrom spec across my fingers. SCSI-3 does
+ * multisession using the READ TOC command (like SONY).
+ *
+ * Rearranged stuff here: SCSI-3 is included allways, support
+ * for NEC/TOSHIBA/HP commands is optional.
+ *
* Gerd Knorr <kraxel@cs.tu-berlin.de>
*
* --------------------------------------------------------------------------
@@ -20,14 +26,15 @@
* - SONY: Detection and support of multisession CD's.
* added by Thomas Quinot <thomas@cuivre.freenix.fr>
*
- * - PIONEER, HITACHI, PLEXTOR, MATSHITA, TEAC, PHILIPS:
- * Known to work with SONY code.
+ * - PIONEER, HITACHI, PLEXTOR, MATSHITA, TEAC, PHILIPS: known to
+ * work with SONY (SCSI3 now) code.
*
* - HP: Much like SONY, but a little different... (Thomas)
* HP-Writers only ??? Maybe other CD-Writers work with this too ?
* HP 6020 writers now supported.
*/
+#include <linux/config.h>
#include <linux/errno.h>
#include <linux/string.h>
@@ -40,27 +47,33 @@
#include <linux/ucdrom.h>
#include "sr.h"
+#if 0
+# define DEBUG
+#endif
+
/* here are some constants to sort the vendors into groups */
-#define VENDOR_CAN_NOT_HANDLE 1 /* don't know how to handle */
+#define VENDOR_SCSI3 1 /* default: scsi-3 mmc */
+
#define VENDOR_NEC 2
#define VENDOR_TOSHIBA 3
-#define VENDOR_SONY_LIKE 4 /* much drives are Sony compatible */
-#define VENDOR_HP_4020 5 /* HP 4xxx writers, others too ?? */
-#define VENDOR_HP_6020 6 /* HP 6020 writers */
+#define VENDOR_HP_4020 4 /* HP 4xxx writers, others too ?? */
+#define VENDOR_HP_6020 5 /* HP 6020 writers */
#define VENDOR_ID (scsi_CDs[minor].vendor)
-#if 0
-#define DEBUG
-#endif
-
void
sr_vendor_init(int minor)
{
+#ifndef CONFIG_BLK_DEV_SR_VENDOR
+ VENDOR_ID = VENDOR_SCSI3;
+#else
char *vendor = scsi_CDs[minor].device->vendor;
char *model = scsi_CDs[minor].device->model;
-
+
+ /* default */
+ VENDOR_ID = VENDOR_SCSI3;
+
if ((!strncmp(vendor,"HP",2) || !strncmp(vendor,"PHILIPS",7)) &&
scsi_CDs[minor].device->type == TYPE_WORM) {
if (!strncmp(model,"CD-Writer 6020",14))
@@ -80,29 +93,33 @@
} else if (!strncmp (vendor, "TOSHIBA", 7)) {
VENDOR_ID = VENDOR_TOSHIBA;
- } else {
- /* most drives can handled like Sony ones, so we take
- * it as default */
- VENDOR_ID = VENDOR_SONY_LIKE;
-#ifdef DEBUG
- printk(KERN_DEBUG
- "sr: using \"Sony group\" multisession code\n");
-#endif
}
+#endif
}
/* small handy function for switching block length using MODE SELECT,
* used by sr_read_sector() */
-static int
-set_density_and_blocklength(int minor, unsigned char *buffer,
- int density, int blocklength)
+int
+sr_set_blocklength(int minor, int blocklength)
{
+ unsigned char *buffer; /* the buffer for the ioctl */
unsigned char cmd[12]; /* the scsi-command */
struct ccs_modesel_head *modesel;
- int rc;
+ int rc,density = 0;
+
+#ifdef CONFIG_BLK_DEV_SR_VENDOR
+ if (VENDOR_ID == VENDOR_TOSHIBA)
+ density = (blocklength > 2048) ? 0x81 : 0x83;
+#endif
+
+ buffer = (unsigned char *) scsi_malloc(512);
+ if (!buffer) return -ENOMEM;
+#ifdef DEBUG
+ printk("sr%d: MODE SELECT 0x%x/%d\n",minor,density,blocklength);
+#endif
memset(cmd,0,12);
cmd[0] = MODE_SELECT;
cmd[1] = (scsi_CDs[minor].device->lun << 5) | (1 << 4);
@@ -113,53 +130,17 @@
modesel->density = density;
modesel->block_length_med = (blocklength >> 8 ) & 0xff;
modesel->block_length_lo = blocklength & 0xff;
- rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel));
+ if (0 == (rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel), 0)))
+ scsi_CDs[minor].sector_size = blocklength;
#ifdef DEBUG
- if (rc)
- printk("sr: switching blocklength to %d bytes failed\n",
- blocklength);
+ else
+ printk("sr%d: switching blocklength to %d bytes failed\n",
+ minor,blocklength);
#endif
- return rc;
-}
-
-
-/* read a sector with other than 2048 bytes length
- * dest is assumed to be allocated with scsi_malloc
- *
- * XXX maybe we have to do some locking here.
- */
-
-int
-sr_read_sector(int minor, int lba, int blksize, unsigned char *dest)
-{
- unsigned char *buffer; /* the buffer for the ioctl */
- unsigned char cmd[12]; /* the scsi-command */
- int rc, density;
-
- density = (VENDOR_ID == VENDOR_TOSHIBA) ? 0x83 : 0;
-
- buffer = (unsigned char *) scsi_malloc(512);
- if (!buffer) return -ENOMEM;
-
- rc = set_density_and_blocklength(minor, buffer, density, blksize);
- if (!rc) {
- memset(cmd,0,12);
- cmd[0] = READ_10;
- cmd[1] = (scsi_CDs[minor].device->lun << 5);
- cmd[2] = (unsigned char)(lba >> 24) & 0xff;
- cmd[3] = (unsigned char)(lba >> 16) & 0xff;
- cmd[4] = (unsigned char)(lba >> 8) & 0xff;
- cmd[5] = (unsigned char) lba & 0xff;
- cmd[8] = 1;
- rc = sr_do_ioctl(minor, cmd, dest, blksize);
- set_density_and_blocklength(minor, buffer, density, 2048);
- }
-
scsi_free(buffer, 512);
return rc;
}
-
/* This function gets called after a media change. Checks if the CD is
multisession, asks for offset etc. */
@@ -169,7 +150,6 @@
{
unsigned long sector,min,sec,frame;
unsigned char *buffer; /* the buffer for the ioctl */
- unsigned char *raw_sector;
unsigned char cmd[12]; /* the scsi-command */
int rc,is_xa,no_multi,minor;
@@ -187,16 +167,41 @@
switch(VENDOR_ID) {
+ case VENDOR_SCSI3:
+ memset(cmd,0,12);
+ cmd[0] = READ_TOC;
+ cmd[1] = (scsi_CDs[minor].device->lun << 5);
+ cmd[8] = 12;
+ cmd[9] = 0x40;
+ rc = sr_do_ioctl(minor, cmd, buffer, 12, 0);
+ if (rc != 0)
+ break;
+ if ((buffer[0] << 8) + buffer[1] < 0x0a) {
+ printk(KERN_INFO "sr%d: Hmm, seems the drive "
+ "doesn't support multisession CD's\n",minor);
+ no_multi = 1;
+ break;
+ }
+ sector = buffer[11] + (buffer[10] << 8) +
+ (buffer[9] << 16) + (buffer[8] << 24);
+ if (buffer[6] <= 1) {
+ /* ignore sector offsets from first track */
+ sector = 0;
+ }
+ break;
+
+#ifdef CONFIG_BLK_DEV_SR_VENDOR
case VENDOR_NEC:
memset(cmd,0,12);
cmd[0] = 0xde;
cmd[1] = (scsi_CDs[minor].device->lun << 5) | 0x03;
cmd[2] = 0xb0;
- rc = sr_do_ioctl(minor, cmd, buffer, 0x16);
+ rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 0);
if (rc != 0)
break;
if (buffer[14] != 0 && buffer[14] != 0xb0) {
- printk(KERN_INFO "sr (nec): Hmm, seems the cdrom doesn't support multisession CD's\n");
+ printk(KERN_INFO "sr%d: Hmm, seems the cdrom "
+ "doesn't support multisession CD's\n",minor);
no_multi = 1;
break;
}
@@ -205,20 +210,19 @@
frame = BCD_TO_BIN(buffer[17]);
sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
break;
-
+
case VENDOR_TOSHIBA:
/* we request some disc information (is it a XA-CD ?,
* where starts the last session ?) */
memset(cmd,0,12);
cmd[0] = 0xc7;
cmd[1] = (scsi_CDs[minor].device->lun << 5) | 3;
- rc = sr_do_ioctl(minor, cmd, buffer, 4);
- if (rc == 0x28000002 &&
- !scsi_ioctl(scsi_CDs[minor].device,
- SCSI_IOCTL_TEST_UNIT_READY, NULL)) {
- printk(KERN_INFO "sr (toshiba): Hmm, seems the drive doesn't support multisession CD's\n");
- no_multi = 1;
- break;
+ rc = sr_do_ioctl(minor, cmd, buffer, 4, 0);
+ if (rc == -EINVAL) {
+ printk(KERN_INFO "sr%d: Hmm, seems the drive "
+ "doesn't support multisession CD's\n",minor);
+ no_multi = 1;
+ break;
}
if (rc != 0)
break;
@@ -239,102 +243,57 @@
0x04 : 0x0c;
cmd[9] = 0x40;
rc = sr_do_ioctl(minor, cmd, buffer,
- (VENDOR_ID == VENDOR_HP_4020) ? 0x04 : 0x0c);
+ (VENDOR_ID == VENDOR_HP_4020) ? 0x04 : 0x0c, 0);
if (rc != 0) {
break;
}
if ((rc = buffer[2]) == 0) {
printk (KERN_WARNING
- "sr (hp): No finished session\n");
+ "sr%d: No finished session\n",minor);
break;
}
- if (VENDOR_ID == VENDOR_HP_4020) {
- cmd[0] = READ_TOC; /* Read TOC */
- cmd[1] = (scsi_CDs[minor].device->lun << 5);
- cmd[6] = rc & 0x7f; /* number of last session */
- cmd[8] = 0x0c;
- cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 12);
- if (rc != 0) {
- break;
- }
+ if (VENDOR_ID == VENDOR_HP_4020) {
+ cmd[0] = READ_TOC; /* Read TOC */
+ cmd[1] = (scsi_CDs[minor].device->lun << 5);
+ cmd[6] = rc & 0x7f; /* number of last session */
+ cmd[8] = 0x0c;
+ cmd[9] = 0x40;
+ rc = sr_do_ioctl(minor, cmd, buffer, 12, 0);
+ if (rc != 0) {
+ break;
+ }
}
sector = buffer[11] + (buffer[10] << 8) +
(buffer[9] << 16) + (buffer[8] << 24);
break;
-
- case VENDOR_SONY_LIKE:
- memset(cmd,0,12);
- cmd[0] = READ_TOC;
- cmd[1] = (scsi_CDs[minor].device->lun << 5);
- cmd[8] = 12;
- cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 12);
- if (rc != 0) {
- break;
- }
- if ((buffer[0] << 8) + buffer[1] < 0x0a) {
- printk(KERN_INFO "sr (sony): Hmm, seems the drive doesn't support multisession CD's\n");
- no_multi = 1;
- break;
- }
- sector = buffer[11] + (buffer[10] << 8) +
- (buffer[9] << 16) + (buffer[8] << 24);
- if (buffer[6] <= 1) {
- /* ignore sector offsets from first track */
- sector = 0;
- }
- break;
-
- case VENDOR_CAN_NOT_HANDLE:
- sector = 0;
- no_multi = 1;
- break;
+#endif /* CONFIG_BLK_DEV_SR_VENDOR */
default:
/* should not happen */
printk(KERN_WARNING
- "sr: unknown vendor code (%i), not initialized ?\n",
- VENDOR_ID);
+ "sr%d: unknown vendor code (%i), not initialized ?\n",
+ minor,VENDOR_ID);
sector = 0;
no_multi = 1;
break;
}
-
- scsi_CDs[minor].xa_flag = 0;
- if (CDS_AUDIO != sr_disk_status(cdi)) {
- /* read a sector in raw mode to check the sector format */
- raw_sector = (unsigned char *) scsi_malloc(2048+512);
- if (!buffer) return -ENOMEM;
- if (0 == sr_read_sector(minor,sector+16,CD_FRAMESIZE_RAW1,
- raw_sector)){
- is_xa = (raw_sector[3] == 0x02);
- if (sector > 0 && !is_xa)
- printk(KERN_INFO "sr: broken CD found: It is "
- "multisession, but has'nt XA sectors\n");
- } else {
- /* read a raw sector failed for some reason. */
- is_xa = (sector > 0);
- }
- scsi_free(raw_sector, 2048+512);
- }
-#ifdef DEBUG
- else printk("sr: audio CD found\n");
-#endif
-
scsi_CDs[minor].ms_offset = sector;
- scsi_CDs[minor].xa_flag = is_xa;
+ scsi_CDs[minor].xa_flag = 0;
+ if (CDS_AUDIO != sr_disk_status(cdi) && 1 == sr_is_xa(minor))
+ scsi_CDs[minor].xa_flag = 1;
+
+ if (2048 != scsi_CDs[minor].sector_size)
+ sr_set_blocklength(minor,2048);
if (no_multi)
cdi->mask |= CDC_MULTI_SESSION;
#ifdef DEBUG
- printk(KERN_DEBUG
- "sr: multisession offset=%lu, XA=%s\n",
- sector,is_xa ? "yes" : "no");
+ if (sector)
+ printk(KERN_DEBUG "sr%d: multisession offset=%lu\n",
+ minor,sector);
#endif
-
scsi_free(buffer, 512);
return rc;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov