[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [VCDImager Bugs/Devel] vcdxrip rip errors
From: |
Steven M. Schultz |
Subject: |
Re: [VCDImager Bugs/Devel] vcdxrip rip errors |
Date: |
Sat, 13 Oct 2001 12:13:22 -0700 (PDT) |
Hi!
> well the workaround is there, in case the CMD_READ_CD ioctl doesn't work
> (usually because the command is not implemented...), then the fall back
> to work with CMD_READ_10 is used instead...
> actually I wanted to get rid of the regular read(), since it's not that
> flexible;
And I know it works because I tested it when you first wrote it ;)
> well, maybe the workaround mechanism doesn't work anymore...
Possible.
> maybe one should check the return values...
I mention that below and have provided an updated module that does
report more information.
> btw, have you changed hardware? cause vcd_image_bsdicd.c hasn't changed
> since 2001/08/31 in cvs... and you told me that version worked... :-/
Yes. I am no a different system and the CDrom drive is a different
brand. When I tested earlier I was using either an ATAPI DVDrom drive
or a Yamaha 8824S CDRW drive. Last night and today I am using
a system that has a Plextor CDrom drive and a Yamaha 8424S.
And now for the news you've been waiting for :)
I have narrowed down the problem.
It turns out I was indeed offbase before - the _workaround flag
can work (and has worked - I remember testing it before).
IF I use a Plextor Ultraplex CDrom drive I get failures. However
if a Yamaha 8424S CD/RW drive is used the 'vcdxrip' works correctly!
Enclosed is an updated vcd_image_bsdicd.c module that adds some
debugging output. It is necessary to check both the 'ioctl' status
(which says the kernel accepted the request) _and_ the SCSI status
suc.suc_sus.sus_status because that is how devices pass back
success/failure. I also print out the first 8 bytes of the sense
data returned.
Then there was a duplicated ioctl (fd, SCSIRAWCDB, &suc) call. It
did not seem logical to do this:
ioctl (fd, SCSIRAWCDB, &suc);
if (_workaround)
{
ioctl (fd, SCSIRAWCDB, &suc);
}
else
ioctl (fd, SCSIRAWCDB, &suc);
The fix is to simply remove the first 'ioctl (fd, SCSIRAWCDB, &suc)' and
rely on the 'if ... else ...' to issue the ioctl.
Included also is the output from the plextor drive - I will have to
find a SCSI error code listing somewhere to decode what:
INFO: _read_mode2 sense: 70 0 5 0 0 0 0 a
means - obviously Plextor drives do not like the SCSI commands being
presented. If those bits make sense to you then perhaps a fix
for SCSI Plextor drives can be created.
Steven Schultz
-----------------------------cut here-----------------------
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2001-10-13 12:02 PDT by <address@hidden>.
# Source directory was `/tmp'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 240 -rw-r--r-- vcdxrip.script
# 7597 -rw-r--r-- vcd_image_bsdicd.c
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
if test "$gettext_dir" = FAILED && test -f $dir/gettext \
&& ($dir/gettext --version >/dev/null 2>&1)
then
set `$dir/gettext --version 2>&1`
if test "$3" = GNU
then
gettext_dir=$dir
fi
fi
if test "$locale_dir" = FAILED && test -f $dir/shar \
&& ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
then
locale_dir=`$dir/shar --print-text-domain-dir`
fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
echo=echo
else
TEXTDOMAINDIR=$locale_dir
export TEXTDOMAINDIR
TEXTDOMAIN=sharutils
export TEXTDOMAIN
echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
shar_touch=touch
else
shar_touch=:
echo
$echo 'WARNING: not restoring timestamps. Consider getting and'
$echo "installing GNU \`touch', distributed in GNU File Utilities..."
echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh02113; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
exit 1
fi
# ============= vcdxrip.script ==============
if test -f 'vcdxrip.script' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'vcdxrip.script' '(file already exists)'
else
$echo 'x -' extracting 'vcdxrip.script' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'vcdxrip.script' &&
Script started on Sat Oct 13 11:51:01 2001
moe.2685-> ./vcdxrip --cdrom-device=/dev/rsr1c
INFO: _read_mode2 sus_status 2
INFO: _read_mode2 sense: 70 0 5 0 0 0 0 a
**ERROR: unexcected descriptor type
X
Script done on Sat Oct 13 11:51:29 2001
SHAR_EOF
$shar_touch -am 1013120101 'vcdxrip.script' &&
chmod 0644 'vcdxrip.script' ||
$echo 'restore of' 'vcdxrip.script' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'vcdxrip.script:' 'MD5 check failed'
743b9faa0636e5ecbe528ba3ba576f2f vcdxrip.script
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'vcdxrip.script'`"
test 240 -eq "$shar_count" ||
$echo 'vcdxrip.script:' 'original size' '240,' 'current size' "$shar_count!"
fi
fi
# ============= vcd_image_bsdicd.c ==============
if test -f 'vcd_image_bsdicd.c' && test "$first_param" != -c; then
$echo 'x -' SKIPPING 'vcd_image_bsdicd.c' '(file already exists)'
else
$echo 'x -' extracting 'vcd_image_bsdicd.c' '(text)'
sed 's/^X//' << 'SHAR_EOF' > 'vcd_image_bsdicd.c' &&
/*
X $Id: vcd_image_bsdicd.c,v 1.2 2001/08/31 09:04:53 hvr Exp $
X
X Copyright (C) 2001 Herbert Valerio Riedel <address@hidden>
X
X This program is free software; you can redistribute it and/or modify
X it under the terms of the GNU General Public License as published by
X the Free Software Foundation; either version 2 of the License, or
X (at your option) any later version.
X
X This program is distributed in the hope that it will be useful,
X but WITHOUT ANY WARRANTY; without even the implied warranty of
X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X GNU General Public License for more details.
X
X You should have received a copy of the GNU General Public License
X along with this program; if not, write to the Free Software
X Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
X
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
X
#include <libvcd/vcd_assert.h>
#include <libvcd/vcd_bytesex.h>
#include <libvcd/vcd_cd_sector.h>
#include <libvcd/vcd_image_bsdicd.h>
#include <libvcd/vcd_iso9660.h>
#include <libvcd/vcd_logging.h>
#include <libvcd/vcd_util.h>
X
static const char _rcsid[] = "$Id: vcd_image_bsdicd.c,v 1.2 2001/08/31 09:04:53
hvr Exp $";
X
#if defined(__bsdi__)
/* && defined(SCSIRAWCDB) */
X
#include </sys/dev/scsi/scsi.h>
#include </sys/dev/scsi/scsi_ioctl.h>
X
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
X
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
X
/* reader */
X
typedef struct {
X int fd;
X
X enum {
X _AM_NONE,
X _AM_READ_CD,
X _AM_READ_10
X } access_mode;
X
X char *device;
X
X bool init;
} _img_bsdicd_src_t;
X
static void
_source_init (_img_bsdicd_src_t *_obj)
{
X if (_obj->init)
X return;
X
X _obj->fd = open (_obj->device, O_RDONLY, 0);
X _obj->access_mode = _AM_READ_CD;
X
X if (_obj->fd < 0)
X {
X vcd_error ("open (%s): %s", _obj->device, strerror (errno));
X return;
X }
X
X _obj->init = true;
}
X
X
static void
_source_free (void *user_data)
{
X _img_bsdicd_src_t *_obj = user_data;
X
X free (_obj->device);
X
X if (_obj->fd)
X close (_obj->fd);
X
X free (_obj);
}
X
static int
_set_bsize (int fd, unsigned bsize)
{
X struct
X {
X uint8_t reserved1;
X uint8_t medium;
X uint8_t reserved2;
X uint8_t block_desc_length;
X uint8_t density;
X uint8_t number_of_blocks_hi;
X uint8_t number_of_blocks_med;
X uint8_t number_of_blocks_lo;
X uint8_t reserved3;
X uint8_t block_length_hi;
X uint8_t block_length_med;
X uint8_t block_length_lo;
X } mh;
X
X struct scsi_user_cdb suc;
X
X memset (&mh, 0, sizeof (mh));
X memset (&suc, 0, sizeof (struct scsi_user_cdb));
X
X suc.suc_cdb[0] = 0x15;
X suc.suc_cdb[1] = 1 << 4;
X suc.suc_cdb[4] = 12;
X suc.suc_cdblen = 6;;
X
X suc.suc_data = (u_char *)&mh;
X suc.suc_datalen = sizeof (mh);
X
X suc.suc_timeout = 500;
X suc.suc_flags = SUC_WRITE;
X
X mh.block_desc_length = 0x08;
X mh.block_length_hi = (bsize >> 16) & 0xff;
X mh.block_length_med = (bsize >> 8) & 0xff;
X mh.block_length_lo = (bsize >> 0) & 0xff;
X
X return ioctl (fd, SCSIRAWCDB, &suc);
}
X
static int
_read_mode2 (int fd, void *buf, uint32_t lba, unsigned nblocks,
X bool _workaround)
{
X struct scsi_user_cdb suc;
X u_char *cp;
X
X memset (&suc, 0, sizeof (struct scsi_user_cdb));
X
X suc.suc_cdb[0] = (_workaround
X ? 0x28 /* CMD_READ_10 */
X : 0xbe /* CMD_READ_CD */);
X
X if (!_workaround)
X suc.suc_cdb[1] = 0; /* sector size mode2 */
X
X suc.suc_cdb[2] = (lba >> 24) & 0xff;
X suc.suc_cdb[3] = (lba >> 16) & 0xff;
X suc.suc_cdb[4] = (lba >> 8) & 0xff;
X suc.suc_cdb[5] = (lba >> 0) & 0xff;
X
X suc.suc_cdb[6] = (nblocks >> 16) & 0xff;
X suc.suc_cdb[7] = (nblocks >> 8) & 0xff;
X suc.suc_cdb[8] = (nblocks >> 0) & 0xff;
X
X if (!_workaround)
X suc.suc_cdb[9] = 0x58; /* 2336 mode2 mixed form */
X
X suc.suc_cdblen = _workaround ? 10 : 12;
X
X suc.suc_data = buf;
X suc.suc_datalen = 2336 * nblocks;
X
X suc.suc_timeout = 500;
X suc.suc_flags = SUC_READ;
X
X if (_workaround)
X {
X int retval;
X
X if ((retval = _set_bsize (fd, 2336)))
X return retval;
X
X if ((retval = ioctl (fd, SCSIRAWCDB, &suc)))
X {
X _set_bsize (fd, 2048);
X return retval;
X }
X
X if ((retval = _set_bsize (fd, 2048)))
X return retval;
X }
X else
X {
X if (ioctl (fd, SCSIRAWCDB, &suc))
X vcd_error ("ioctl (SCSIRAWCDB): %s", strerror (errno));
X if (suc.suc_sus.sus_status)
X {
X vcd_info("_read_mode2 sus_status %d\n", suc.suc_sus.sus_status);
X cp = suc.suc_sus.sus_sense;
X vcd_info("_read_mode2 sense: %x %x %x %x %x %x %x %x\n",
X cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
X }
X }
X return 0;
}
X
static int
_read_mode2_sector (void *user_data, void *data, uint32_t lsn, bool form2)
{
X _img_bsdicd_src_t *_obj = user_data;
X
X _source_init (_obj);
X
X if (form2)
X {
X retry:
X switch (_obj->access_mode)
X {
X case _AM_NONE:
X vcd_error ("no way to read mode2");
X return 1;
X break;
X
X case _AM_READ_CD:
X case _AM_READ_10:
X if (_read_mode2 (_obj->fd, data, lsn, 1,
X (_obj->access_mode == _AM_READ_10)))
X {
X perror ("ioctl()");
X if (_obj->access_mode == _AM_READ_CD)
X {
X vcd_info ("READ_CD failed; switching to READ_10 mode...");
X _obj->access_mode = _AM_READ_10;
X goto retry;
X }
X else
X {
X vcd_info ("READ_10 failed; no way to read mode2 left.");
X _obj->access_mode = _AM_NONE;
X goto retry;
X }
X return 1;
X }
X break;
X }
X }
X else
X {
X char buf[M2RAW_SIZE] = { 0, };
X int retval;
X
X if ((retval = _read_mode2_sector (_obj, buf, lsn, true)))
X return retval;
X
X memcpy (data, buf + 8, ISO_BLOCKSIZE);
X }
X
X return 0;
}
X
static const u_char scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10};
X
static uint32_t
_stat_size (void *user_data)
{
X _img_bsdicd_src_t *_obj = user_data;
X
X struct scsi_user_cdb suc;
X uint8_t buf[12] = { 0, };
X
X uint32_t retval;
X
X _source_init(_obj);
X
X memset (&suc, 0, sizeof (struct scsi_user_cdb));
X
X suc.suc_cdb[0] = 0x43; /* CMD_READ_TOC_PMA_ATIP */
X suc.suc_cdb[1] = 0; /* lba; msf: 0x2 */
X suc.suc_cdb[6] = 0xaa; /* CDROM_LEADOUT */
X suc.suc_cdb[8] = 12; /* ? */
X suc.suc_cdblen = 10;
X
X suc.suc_data = buf;
X suc.suc_datalen = sizeof (buf);
X
X suc.suc_timeout = 500;
X suc.suc_flags = SUC_READ;
X
X if (ioctl (_obj->fd, SCSIRAWCDB, &suc))
X {
X vcd_error ("ioctl (SCSIRAWCDB): %s", strerror (errno));
X return 0;
X }
X
X if (suc.suc_sus.sus_status)
X {
X vcd_error ("scsistatus = %d", suc.suc_sus.sus_status);
X return 0;
X }
X
X {
X int i;
X
X retval = 0;
X for (i = 8; i < 12; i++)
X {
X retval <<= 8;
X retval += buf[i];
X }
X }
X
X return retval;
}
X
static int
_source_set_arg (void *user_data, const char key[], const char value[])
{
X _img_bsdicd_src_t *_obj = user_data;
X
X if (!strcmp (key, "device"))
X {
X if (!value)
X return -2;
X
X free (_obj->device);
X
X _obj->device = strdup (value);
X }
X else
X return -1;
X
X return 0;
}
X
#endif /* defined(__bsdi__) */
X
VcdImageSource *
vcd_image_source_new_bsdicd (void)
{
#if defined(__bsdi__)
X _img_bsdicd_src_t *_data;
X
X vcd_image_source_funcs _funcs = {
X read_mode2_sector: _read_mode2_sector,
X stat_size: _stat_size,
X free: _source_free,
X setarg: _source_set_arg
X };
X
X _data = _vcd_malloc (sizeof (_img_bsdicd_src_t));
X _data->device = strdup ("/dev/cdrom");
X
X return vcd_image_source_new (_data, &_funcs);
#else
X vcd_error ("bsdi cd image source only supported under BSDI");
X return NULL;
#endif
}
X
X
SHAR_EOF
$shar_touch -am 1013120201 'vcd_image_bsdicd.c' &&
chmod 0644 'vcd_image_bsdicd.c' ||
$echo 'restore of' 'vcd_image_bsdicd.c' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'vcd_image_bsdicd.c:' 'MD5 check failed'
e16de4a466501aba60b5ce598c3b0ee5 vcd_image_bsdicd.c
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'vcd_image_bsdicd.c'`"
test 7597 -eq "$shar_count" ||
$echo 'vcd_image_bsdicd.c:' 'original size' '7597,' 'current size'
"$shar_count!"
fi
fi
rm -fr _sh02113
exit 0