Skip site navigation (1)Skip section navigation (2)
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>