Date: Tue, 22 Dec 1998 06:18:01 -0600 From: David Deaven <deaven@execpc.com> To: Steve Willoughby <steve@alchemy.com> Cc: freebsd-questions@FreeBSD.ORG Subject: Re: problem with CD-R writing. Message-ID: <199812221214.GAA16013@pop05.execpc.com> In-Reply-To: Your message of "Sat, 19 Dec 1998 13:29:58 PST." <Pine.BSF.4.01.9812191312430.3532-100000@elemental.alchemy.com>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multipart MIME message.
--==_Exmh_18900079500
Content-Type: text/plain; charset=us-ascii
Have you tried using this drive as a CD-ROM (read-only)? The SCSI error
you are getting is very basic -- all SCSI devices (besides CD-Rs) should
support the TEST_UNIT_READY command, so it really looks like a hardware
problem...
I've attached a small C program that uses the FreeBSD SCSI ioctls to do
a test unit ready command when run with no arguments. When I run it on
my SCSI 2 CDRW drive (which works great with cdrecord) I get:
# ./scsi
bus0 target1 lun0
sending SCSI command 00 00 00 00 00 00
test unit ready: sense ASC=0 ASCQ=0
You might want to try it out to pursue this issue; it might be easier to
debug than going through Schilling's generic scg driver code in cdrecord. You
might need to change the device, which is hard-coded to be /dev/cd0c in main().
Finally, my probe looks like this, almost exactly like yours:
ncr0 <ncr 53c810a fast10 scsi> rev 18 int a irq 11 on pci0:11:0
ncr0 waiting for scsi devices to settle
(ncr0:1:0): "RICOH MP6201S 2.03" type 5 removable SCSI 2
cd0(ncr0:1:0): CD-ROM cd present [203237 x 2048 byte records]
Good luck, hope this is of some help.
Dave Deaven
>I have a generic SCSI CD-R drive (the brand is Smart and Friendly, which I'd
>never heard of, but I (naively?) thought that SCSI drives were SCSI drives
>were SCSI drives)...
>
>The drive works fine under Win95, so I don't think the problem is that the
>hardware's broken, but when I try to run it in my FreeBSD 2.2.7 system,
>I get the following. I hope someone out there has a clue to help.
>Thanks in advance.
>
>Okay, here are the gory details...
>
>The drive is recognized at boot time:
> (ahc0:4:0): "SAF CD-RW226 1.12" type 5 removable SCSI 2
> cd0(ahc0:4:0): CD-ROM cd present [400000 x 2048 byte records]
>
>The second line is puzzling since there was no cd present, but I didn't
>think much of that.
>
>When using cdrecord, I consistently get the following, no matter what operatio
>n
>I try to perform:
>
> # cdrecord -inq dev=4,0
> Cdrecord release 1.6 Copyright (C) 1995-1998 Jvrg Schilling
> scsidev: '4,0'
> scsibus: 0 target: 4 lun: 0
> cdrecord: Cannot do inquiry for CD-Recorder.
> cdrecord: Undefined error: 0. test unit ready: scsi sendcmd: fatal error
> CDB: 00 00 00 00 00 00
> cmd finished after 0.000s timeout 40s
>
>SCSI scans don't find anything:
>
> # cdrecord -scanbus
> Cdrecord release 1.6 Copyright (C) 1995-1998 Jvrg Schilling
> cdrecord: No target found.
>
>I also tried cd-write, but that just spews Tk errors about undefined variables
>(TkPriv, etc.), and that's running it with freshly-compiled Tcl/Tk 8.0.3+ libs
>and Tix 4.1.8.0, so I don't think that's the problem. But one thing that doe
>s
>manage to come up with cd-write is the following which I get from the
>"copy cd" command:
>
>It IDs the drive as "SAF CD-RW226 1.12", which I believe is the SCSI ID string
>(since that came up at the boot-time scan too), but I get the TEST UNIT READY
>failure message:
>
> TEST UNIT READY command failed
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> flags=0x1 senselen_used=32 status=0x02 retsts=0x03 error=0x0
> 70 00 02 00 00 00 00 0a 00 00 00 00 3a 00 00 00 00 00 00 ff 94 3e 63 00 00
> 00 00 00 00 00 00 00
>
>Do I just have a hopelessly incompatible CD-R drive, or can I do something
>to the cdrecod sources, or did I miss something obvious?
>
>TIA,
>Steve Willoughby
>steve@alchemy.com
>
>
>To Unsubscribe: send mail to majordomo@FreeBSD.org
>with "unsubscribe freebsd-questions" in the body of the message
>
--==_Exmh_18900079500
Content-Type: text/plain ; name="scsi.c"; charset=us-ascii
Content-Description: scsi.c
Content-Disposition: attachment; filename="scsi.c"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/scsiio.h>
#include <sys/cdio.h>
#ifndef EXIT_FAILURE
#define EXIT_FAILURE -1
#endif
/* SCSI command codes */
#define SC_TEST_UNIT_READY 0x00
#define SC_INQUIRY 0x12
#define SC_BLANK 0xA1
#define SC_PLAY_AUDIO 0xA5
#define SC_PLAY_AUDIO_TRACK_INDEX 0x48
#define SC_PLAY_TRACK_RELATIVE 0x49
#define SC_GROUP0_LEN 6
#define SC_GROUP1_LEN 10
#define SC_GROUP2_LEN 10
#define SC_GROUP3_LEN 0 /* reserved */
#define SC_GROUP4_LEN 0 /* reserved */
#define SC_GROUP5_LEN 12
#define SC_GROUP6_LEN 0 /* vendor */
#define SC_GROUP7_LEN 0 /* vendor */
/* Identify the bus, target, and lun associated with
the file descriptor, or return -1 if the attached device
is not a SCSI device.
*/
int scsi_identify(int fd, int btl[3])
{
struct scsi_addr saddr;
if (ioctl(fd, SCIOCIDENTIFY, &saddr) < 0) {
perror("getting SCSI address");
return -1;
}
#ifdef __NetBSD__
if (saddr.type != TYPE_SCSI) {
printf("not a SCSI address\n");
return -1;
}
btl[0] = saddr.addr.scsi.scbus;
btl[1] = saddr.addr.scsi.target;
btl[2] = saddr.addr.scsi.lun;
#else
btl[0] = saddr.scbus;
btl[1] = saddr.target;
btl[2] = saddr.lun;
#endif
return 0;
}
/* Reset the specified device.
*/
int scsi_reset(int fd)
{
if (ioctl(fd, SCIOCRESET, 0) < 0) {
perror("reseting SCSI device\n");
return -1;
}
return 0;
}
/* Turn debugging on for the specified device.
*/
int scsi_debug(int fd, int level)
{
int cmd = 0;
if (level > 0)
cmd = SC_DB_CMDS;
if (ioctl(fd, SCIOCDEBUG, cmd) < 0) {
perror("setting SCSI debug level");
return -1;
}
return 0;
}
static int scsi_command(int fd, scsireq_t *req)
{
int status = 0;
req->flags |= SCCMD_ESCAPE; /* We set the SCSI cmd len */
if (req->timeout == 0)
req->timeout = 1000; /* 1 sec */
bzero(req->sense, sizeof(req->sense));
req->senselen = sizeof(req->sense);
req->senselen_used = 0;
req->status = 0;
req->retsts = 0;
req->error = 0;
printf("sending SCSI command");
{ int i; for (i = 0; i < req->cmdlen; i++) printf(" %02x", req->cmd[i]); }
printf("\n");
fflush(stdout);
if (ioctl(fd, SCIOCCOMMAND, req) < 0) {
perror("sending SCSI command");
return -1;
}
switch (req->retsts) {
case SCCMD_OK:
break;
case SCCMD_TIMEOUT:
printf("scsi timeout\n");
status = -1;
break;
case SCCMD_BUSY:
printf("scsi device busy\n");
status = -1;
break;
case SCCMD_SENSE:
printf("scsi check sense\n");
status = -1;
break;
default:
case SCCMD_UNKNOWN:
printf("unknown scsi status %d\n", req->retsts);
status = -1;
}
return status;
}
/*
+=====-========-========-========-========-========-========-========-========+
| Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|Byte | | | | | | | | |
|=====+=======================================================================|
| 0 | Operation code (00h) |
|-----+-----------------------------------------------------------------------|
| 1 | Logical unit number | Reserved |
|-----+-----------------------------------------------------------------------|
| 2 | Reserved |
|-----+-----------------------------------------------------------------------|
| 3 | Reserved |
|-----+-----------------------------------------------------------------------|
| 4 | Reserved |
|-----+-----------------------------------------------------------------------|
| 5 | Control |
+=============================================================================+
*/
int scsi_test_unit_ready(int fd)
{
scsireq_t req;
int status = 0;
bzero(&req, sizeof(req));
req.cmd[0] = SC_TEST_UNIT_READY;
req.cmdlen = SC_GROUP0_LEN;
status = scsi_command(fd, &req);
if (status == 0)
{
int asc = req.sense[12];
int ascq = req.sense[13];
printf("test unit ready: sense ASC=%x ASCQ=%x\n", asc, ascq);
}
return status;
}
/*
Table 44 - INQUIRY command
+=====-========-========-========-========-========-========-========-========+
| Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|Byte | | | | | | | | |
|=====+=======================================================================|
| 0 | Operation code (12h) |
|-----+-----------------------------------------------------------------------|
| 1 | Logical unit number | Reserved | EVPD |
|-----+-----------------------------------------------------------------------|
| 2 | Page code |
|-----+-----------------------------------------------------------------------|
| 3 | Reserved |
|-----+-----------------------------------------------------------------------|
| 4 | Allocation length |
|-----+-----------------------------------------------------------------------|
| 5 | Control |
+=============================================================================+
*/
int scsi_inquiry(int fd, char buffer[96])
{
scsireq_t req;
bzero(&req, sizeof(req));
bzero(buffer, 96);
req.cmd[0] = SC_INQUIRY;
req.cmd[4] = 96;
req.cmdlen = SC_GROUP0_LEN;
req.flags = SCCMD_READ;
req.databuf = buffer;
req.datalen = 96;
req.timeout = 10 * 1000;
if (scsi_command(fd, &req) < 0)
return -1;
return 0;
}
int scsi_quick_erase(int fd)
{
scsireq_t req;
bzero(&req, sizeof(req));
req.cmd[0] = SC_BLANK;
req.cmd[1] = 1; /* code 1 blank type -- quick erase */
req.cmdlen = SC_GROUP5_LEN;
req.timeout = 240 * 1000;
if (scsi_command(fd, &req) < 0)
return -1;
return 0;
}
static int scsi_play_audio_track(int fd, int track, int index)
{
#if 0
scsireq_t req;
bzero(&req, sizeof(req));
req.cmd[0] = SC_PLAY_AUDIO_TRACK_INDEX;
req.cmd[4] = track;
req.cmd[5] = index;
req.cmd[7] = track + 1;
req.cmd[8] = index + 1;
req.cmdlen = SC_GROUP1_LEN;
req.timeout = 240 * 1000;
if (scsi_command(fd, &req) < 0)
return -1;
return 0;
#else
struct ioc_play_track play;
struct ioc_toc_header tochdr;
if (ioctl(fd, CDIOREADTOCHEADER, &tochdr) < 0) {
perror("reading CD TOC header");
return -1;
}
printf("disk contains %d tracks\n",
tochdr.ending_track - tochdr.starting_track + 1);
play.start_track = track;
play.start_index = index;
play.end_track = tochdr.ending_track;
play.end_index = 99;
if (ioctl(fd, CDIOCSTART) < 0) {
perror("starting CD");
return -1;
}
sleep(30);
#if 0
if (ioctl(fd, CDIOCPLAYTRACKS, &play) < 0) {
perror("playing tracks");
return -1;
}
#endif
return 0;
#endif
}
int scsi_play_audio(int fd)
{
unsigned long tlen = 650 * 1024 * 1024; /* whole disk */
scsireq_t req;
bzero(&req, sizeof(req));
req.cmd[0] = SC_PLAY_AUDIO;
req.cmd[6] = (tlen >> 24) & 0xff;
req.cmd[7] = (tlen >> 16) & 0xff;
req.cmd[8] = (tlen >> 8) & 0xff;
req.cmd[9] = tlen & 0xff;
req.cmdlen = SC_GROUP5_LEN;
req.timeout = 240 * 1000;
if (scsi_command(fd, &req) < 0)
return -1;
return 0;
}
static void print_field(char *s, int l1, int l2)
{
int i;
for (i = l1; i <= l2; i++)
putchar(s[i]);
}
/*
Table 45 - Standard INQUIRY data format
+=====-========-========-========-========-========-========-========-========+
| Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|Byte | | | | | | | | |
|=====+==========================+============================================|
| 0 | Peripheral qualifier | Peripheral device type |
|-----+-----------------------------------------------------------------------|
| 1 | RMB | Device-type modifier |
|-----+-----------------------------------------------------------------------|
| 2 | ISO version | ECMA version | ANSI-approved version |
|-----+-----------------+-----------------------------------------------------|
| 3 | AENC | TrmIOP | Reserved | Response data format |
|-----+-----------------------------------------------------------------------|
| 4 | Additional length (n-4) |
|-----+-----------------------------------------------------------------------|
| 5 | Reserved |
|-----+-----------------------------------------------------------------------|
| 6 | Reserved |
|-----+-----------------------------------------------------------------------|
| 7 | RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe |
|-----+-----------------------------------------------------------------------|
| 8 | (MSB) |
|- - -+--- Vendor identification ---|
| 15 | (LSB) |
|-----+-----------------------------------------------------------------------|
| 16 | (MSB) |
|- - -+--- Product identification ---|
| 31 | (LSB) |
|-----+-----------------------------------------------------------------------|
| 32 | (MSB) |
|- - -+--- Product revision level ---|
| 35 | (LSB) |
|-----+-----------------------------------------------------------------------|
| 36 | |
|- - -+--- Vendor-specific ---|
| 55 | |
|-----+-----------------------------------------------------------------------|
| 56 | |
|- - -+--- Reserved ---|
| 95 | |
|=====+=======================================================================|
| | Vendor-specific parameters |
|=====+=======================================================================|
| 96 | |
|- - -+--- Vendor-specific ---|
| n | |
+=============================================================================+
*/
static int print_inquiry_data(char buffer[96])
{
int i;
int dt;
static char* device_type[] = {
"direct-access",
"sequential-access",
"printer device",
"processor device",
"write-once device",
"CD-ROM",
"scanner",
"optical memory",
"medium changer",
"communications"
};
printf("INQUIRY buffer:");
for (i = 0; i < 96; i++) {
unsigned char uc = buffer[i];
printf("%c0x%x", i % 8 == 0 ? '\n' : ' ', (int) uc);
}
printf("\n");
dt = buffer[0] & 0x1f;
printf("SCSI device: %s ", dt < 10 ? device_type[dt] : "unknown");
print_field(buffer, 8, 15); printf(" revision "); print_field(buffer, 32, 35);
printf("\n");
return 0;
}
int main(int argc, char**argv)
{
int fd;
int arg;
char* fn = "/dev/cd0c";
int scsiaddr[3];
int status = 0;
fd = open(fn, O_RDWR, 0);
if (fd < 0) {
perror("opening SCSI device");
exit(EXIT_FAILURE);
}
if (scsi_identify(fd, scsiaddr) < 0) {
printf("failed to identify SCSI device\n");
exit(EXIT_FAILURE);
}
printf("bus%d target%d lun%d\n", scsiaddr[0],
scsiaddr[1], scsiaddr[2]);
if (scsi_test_unit_ready(fd) < 0) {
printf("unit failed to test ready\n");
exit(EXIT_FAILURE);
}
for (arg = 1; arg < argc; arg++)
{
if (strcmp("--quick-erase", argv[arg]) == 0)
{
status = scsi_quick_erase(fd);
}
else if (strcmp("--play-audio", argv[arg]) == 0)
{
int use_track = 0;
int track = 1;
int index = 1;
if (argc > (arg + 1)) {
track = atoi(argv[++arg]);
use_track = 1;
if (argc > (arg + 1))
index = atoi(argv[++arg]);
}
if (use_track) {
printf("playing track %d index %d\n", track, index);
status = scsi_play_audio_track(fd, track, index);
}
else
status = scsi_play_audio(fd);
}
else if (strcmp("--inquiry", argv[arg]) == 0)
{
char buffer[96];
scsi_inquiry(fd, buffer);
print_inquiry_data(buffer);
}
else if (strcmp("--debug", argv[arg]) == 0)
{
scsi_debug(fd, 1);
}
else
{
printf("unrecognized command %s\n", argv[arg]);
fflush(stdout);
exit(EXIT_FAILURE);
}
}
if (status != 0) {
printf("resetting SCSI unit\n");
scsi_reset(fd);
}
exit(0);
}
--==_Exmh_18900079500
Content-Type: text/plain; charset=us-ascii
-------------------------------------
David Deaven deaven@execpc.com
http://www.execpc.com/~deaven
--==_Exmh_18900079500--
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199812221214.GAA16013>
