summaryrefslogtreecommitdiff
path: root/drivers/scsi/sr_vendor.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sr_vendor.c')
-rw-r--r--drivers/scsi/sr_vendor.c67
1 files changed, 39 insertions, 28 deletions
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index 92cc2efb25d7..a61635326ae0 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/* -*-linux-c-*-
* vendor-specific code for SCSI CD-ROM's goes here.
@@ -60,14 +61,12 @@
#define VENDOR_NEC 2
#define VENDOR_TOSHIBA 3
#define VENDOR_WRITER 4 /* pre-scsi3 writers */
+#define VENDOR_CYGNAL_85ED 5 /* CD-on-a-chip */
#define VENDOR_TIMEOUT 30*HZ
void sr_vendor_init(Scsi_CD *cd)
{
-#ifndef CONFIG_BLK_DEV_SR_VENDOR
- cd->vendor = VENDOR_SCSI3;
-#else
const char *vendor = cd->device->vendor;
const char *model = cd->device->model;
@@ -98,8 +97,24 @@ void sr_vendor_init(Scsi_CD *cd)
} else if (!strncmp(vendor, "TOSHIBA", 7)) {
cd->vendor = VENDOR_TOSHIBA;
+ } else if (!strncmp(vendor, "Beurer", 6) &&
+ !strncmp(model, "Gluco Memory", 12)) {
+ /* The Beurer GL50 evo uses a Cygnal-manufactured CD-on-a-chip
+ that only accepts a subset of SCSI commands. Most of the
+ not-implemented commands are fine to fail, but a few,
+ particularly around the MMC or Audio commands, will put the
+ device into an unrecoverable state, so they need to be
+ avoided at all costs.
+ */
+ cd->vendor = VENDOR_CYGNAL_85ED;
+ cd->cdi.mask |= (
+ CDC_MULTI_SESSION |
+ CDC_CLOSE_TRAY | CDC_OPEN_TRAY |
+ CDC_LOCK |
+ CDC_GENERIC_PACKET |
+ CDC_PLAY_AUDIO
+ );
}
-#endif
}
@@ -113,17 +128,15 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength)
struct ccs_modesel_head *modesel;
int rc, density = 0;
-#ifdef CONFIG_BLK_DEV_SR_VENDOR
if (cd->vendor == VENDOR_TOSHIBA)
density = (blocklength > 2048) ? 0x81 : 0x83;
-#endif
- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+ buffer = kmalloc(512, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
#ifdef DEBUG
- printk("%s: MODE SELECT 0x%x/%d\n", cd->cdi.name, density, blocklength);
+ sr_printk(KERN_INFO, cd, "MODE SELECT 0x%x/%d\n", density, blocklength);
#endif
memset(&cgc, 0, sizeof(struct packet_command));
cgc.cmd[0] = MODE_SELECT;
@@ -144,8 +157,9 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength)
}
#ifdef DEBUG
else
- printk("%s: switching blocklength to %d bytes failed\n",
- cd->cdi.name, blocklength);
+ sr_printk(KERN_INFO, cd,
+ "switching blocklength to %d bytes failed\n",
+ blocklength);
#endif
kfree(buffer);
return rc;
@@ -165,7 +179,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
if (cd->cdi.mask & CDC_MULTI_SESSION)
return 0;
- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+ buffer = kmalloc(512, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
@@ -190,8 +204,8 @@ int sr_cd_check(struct cdrom_device_info *cdi)
if (rc != 0)
break;
if ((buffer[0] << 8) + buffer[1] < 0x0a) {
- printk(KERN_INFO "%s: Hmm, seems the drive "
- "doesn't support multisession CD's\n", cd->cdi.name);
+ sr_printk(KERN_INFO, cd, "Hmm, seems the drive "
+ "doesn't support multisession CD's\n");
no_multi = 1;
break;
}
@@ -203,7 +217,6 @@ int sr_cd_check(struct cdrom_device_info *cdi)
}
break;
-#ifdef CONFIG_BLK_DEV_SR_VENDOR
case VENDOR_NEC:{
unsigned long min, sec, frame;
cgc.cmd[0] = 0xde;
@@ -218,9 +231,9 @@ int sr_cd_check(struct cdrom_device_info *cdi)
if (rc != 0)
break;
if (buffer[14] != 0 && buffer[14] != 0xb0) {
- printk(KERN_INFO "%s: Hmm, seems the cdrom "
- "doesn't support multisession CD's\n",
- cd->cdi.name);
+ sr_printk(KERN_INFO, cd, "Hmm, seems the cdrom "
+ "doesn't support multisession CD's\n");
+
no_multi = 1;
break;
}
@@ -245,9 +258,8 @@ int sr_cd_check(struct cdrom_device_info *cdi)
cgc.timeout = VENDOR_TIMEOUT;
rc = sr_do_ioctl(cd, &cgc);
if (rc == -EINVAL) {
- printk(KERN_INFO "%s: Hmm, seems the drive "
- "doesn't support multisession CD's\n",
- cd->cdi.name);
+ sr_printk(KERN_INFO, cd, "Hmm, seems the drive "
+ "doesn't support multisession CD's\n");
no_multi = 1;
break;
}
@@ -277,8 +289,8 @@ int sr_cd_check(struct cdrom_device_info *cdi)
break;
}
if ((rc = buffer[2]) == 0) {
- printk(KERN_WARNING
- "%s: No finished session\n", cd->cdi.name);
+ sr_printk(KERN_WARNING, cd,
+ "No finished session\n");
break;
}
cgc.cmd[0] = READ_TOC; /* Read TOC */
@@ -297,13 +309,12 @@ int sr_cd_check(struct cdrom_device_info *cdi)
sector = buffer[11] + (buffer[10] << 8) +
(buffer[9] << 16) + (buffer[8] << 24);
break;
-#endif /* CONFIG_BLK_DEV_SR_VENDOR */
default:
/* should not happen */
- printk(KERN_WARNING
- "%s: unknown vendor code (%i), not initialized ?\n",
- cd->cdi.name, cd->vendor);
+ sr_printk(KERN_WARNING, cd,
+ "unknown vendor code (%i), not initialized ?\n",
+ cd->vendor);
sector = 0;
no_multi = 1;
break;
@@ -321,8 +332,8 @@ int sr_cd_check(struct cdrom_device_info *cdi)
#ifdef DEBUG
if (sector)
- printk(KERN_DEBUG "%s: multisession offset=%lu\n",
- cd->cdi.name, sector);
+ sr_printk(KERN_DEBUG, cd, "multisession offset=%lu\n",
+ sector);
#endif
kfree(buffer);
return rc;