A few improvements to the worm driver.
- remove all calls to scsi_stop_unit(). Some drives refuse commands when stopped. This will fix the 'device not configured' message which was cleared after opening/closing the tray. - Never set the logical block address in the scsi_cmd struct when writing. The computation was bogus for block sizes not a multiple of DEV_BSIZE. (the bug is still there in the READ case) - reset the block size to the 2048 bytes in finalize_track() track to avoid an error when mounting a disk after an audio write. - remove the WORMIOCQUIRKSELECT ioctl. Quirks are now recorded at probe time (see scsiconf.c) - change and expand the argument to the WORMIOCPREPTRACK ioctl. It now possible to select more track options (copy bits, ISRC codes, track type, track number) - add an error handler to catch false errors (warnings in fact) and record the error type. - add an ioctl call (WORMIOERROR) to get more information on the nature of the error when a command or a write failed. - add an ioctl call (WORMIOCFINISHTRACK) to finalize a track without closing the device (closing the device still finalize the track if the command was not performed) Approved by: joerg
This commit is contained in:
parent
7136226da3
commit
1ad8b2cb84
@ -32,7 +32,7 @@
|
||||
.\" USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
.\" DAMAGE.
|
||||
.\"
|
||||
.\" $Id$
|
||||
.\" $Id: worm.4,v 1.10 1997/02/22 13:24:55 peter Exp $
|
||||
.\" "
|
||||
.Dd January 27, 1996
|
||||
.Dt WORM 4
|
||||
@ -125,23 +125,7 @@ The following
|
||||
calls apply to CD-R devices. Their declaration can be found in the
|
||||
header file
|
||||
.Pa <sys/wormio.h> .
|
||||
.Bl -tag -width WORMIOCQUIRKSELECT
|
||||
.It Dv WORMIOCQUIRKSELECT
|
||||
Select the set of quirk functions to use for this device. This is the
|
||||
only allowed action on a virgin device after booting. The argument
|
||||
structure takes a vendor and a model string, which are matched against
|
||||
the vendor and model strings of all quirk records that have been
|
||||
registered with the driver. Currently, the only known quirks must
|
||||
have been statically compiled into the driver.
|
||||
.Pp
|
||||
If the driver fails to match the vendor and model string against any
|
||||
known quirk record, the system call returns with an error, and the
|
||||
variable
|
||||
.Va errno
|
||||
will be set to
|
||||
.Er EINVAL .
|
||||
The system call argument is a pointer to a
|
||||
.Dv struct wormio_quirk_select .
|
||||
.Bl -tag -width WORMIOFINISHTRACK
|
||||
.It Dv WORMIOCPREPDISK
|
||||
This command selects several session-wide parameters in the driver.
|
||||
The argument structure,
|
||||
@ -161,22 +145,98 @@ is device-dependent, where a speed value of one generally applies to
|
||||
audio disks, and a speed value of 2 (or more) is used for recording
|
||||
data.
|
||||
.It Dv WORMIOCPREPTRACK
|
||||
The two parameters
|
||||
This command selects several options for writing the next track.
|
||||
The argument structure,
|
||||
.Dv struct wormio_prepare_track
|
||||
is as follows:
|
||||
.Bd -literal -offset indent
|
||||
struct wormio_prepare_track {
|
||||
int audio;
|
||||
int preemp;
|
||||
int track_type;
|
||||
int copy_bits;
|
||||
int track_number;
|
||||
char ISRC_country[2];
|
||||
char ISRC_owner[3];
|
||||
int ISRC_year;
|
||||
char ISRC_serial[5];
|
||||
};
|
||||
.Ed
|
||||
.Dv audio
|
||||
and
|
||||
.Dv preemp
|
||||
are being passed as arguments in a
|
||||
.Dv struct wormio_prepare_track .
|
||||
Both are Boolean, i.e. can be either 0 or 1. If
|
||||
.Dv audio
|
||||
is set to 1, the next track will be recorded in audio format, with
|
||||
2352 bytes per block. If
|
||||
should be set to 1 if you are recording an audio track.
|
||||
If
|
||||
.Dv preemp
|
||||
is also set to 1, the audio data are assumed to be recorded with
|
||||
preemphasis. If
|
||||
preemphasis.
|
||||
.Dv track_type
|
||||
defines both the the specific data fields in a user data block and
|
||||
its size. Currently available types are
|
||||
.Bl -tag -width BLOCK_MODE_2_FORM_2b
|
||||
.It Dv BLOCK_RAW
|
||||
2352 bytes, raw data.
|
||||
.It Dv BLOCK_RAWPQ
|
||||
2368 bytes, raw data with P and Q subchannels.
|
||||
.It Dv BLOCK_RAWPW
|
||||
2448 bytes, raw data with P-W subchannel appended.
|
||||
.It Dv BLOCK_MODE_1
|
||||
2048 bytes, mode 1 (ISO/IEC 10149).
|
||||
.It Dv BLOCK_MODE_2
|
||||
2336 bytes, mode 2 (ISO/IEC 10149).
|
||||
.It Dv BLOCK_MODE_2_FORM_1
|
||||
2048 bytes, CD-ROM XA form 1.
|
||||
.It Dv BLOCK_MODE_2_FORM_1b
|
||||
2056 bytes, CD-ROM XA form 1.
|
||||
.It Dv BLOCK_MODE_2_FORM_2
|
||||
2324 bytes, CD-ROM XA form 2.
|
||||
.It Dv BLOCK_MODE_2_FORM_2b
|
||||
2332 bytes, CD-ROM XA form 2.
|
||||
.El
|
||||
.Pp
|
||||
Note that not all track types are supported for a given drive.
|
||||
.Pp
|
||||
.Dv copy_bits
|
||||
define the permissions for copying the track. Available values are
|
||||
.Bl -tag -width COPY_PERMITTED
|
||||
.It Dv COPY_INHIBIT
|
||||
No copy is allowed.
|
||||
.It Dv COPY_PERMITTED
|
||||
The track can be copied.
|
||||
.It Dv COPY_SCMS
|
||||
The track can be copied once.
|
||||
.El
|
||||
|
||||
.Dv track_number :
|
||||
if the track number is zero, a new track will be created with a track
|
||||
number one higher than the previous track. If the track number is not
|
||||
zero, then this track number must point to a reserved track, unless it
|
||||
is an empty disc which will start with the given track number.
|
||||
|
||||
.Dv ISRC_country :
|
||||
two characters in the range [0-9A-Z] defining the country code.
|
||||
|
||||
.Dv ISRC_owner :
|
||||
three characters in the range [0-9A-Z] defining the owner code.
|
||||
|
||||
.Dv ISRC_year :
|
||||
the year of recording.
|
||||
|
||||
.Dv ISRC_serial :
|
||||
a serial number, composed of 5 digits.
|
||||
.Pp
|
||||
For writing an audio track, setting
|
||||
.Dv audio
|
||||
is 0, CD-ROM data with a block length of 2048 bytes are about to be
|
||||
written next.
|
||||
to 1,
|
||||
.Dv preemp
|
||||
to 0 or 1 and all the other field to 0 will do the job. For writing a
|
||||
data track, you can just set
|
||||
.Dv track_type
|
||||
to
|
||||
.Dv BLOCK_MODE_1 .
|
||||
|
||||
.It Dv WORMIOCFINISHTRACK
|
||||
Will terminate the track. It takes no argument. Note that closing the
|
||||
device will also terminate the track.
|
||||
|
||||
.It Dv WORMIOCFIXATION
|
||||
This closes the current session. The argument is a pointer to
|
||||
.Dv struct wormio_fixation ,
|
||||
@ -190,15 +250,50 @@ to 1 will cause the next session being opened, so further recording
|
||||
can be performed into the remaining space. If
|
||||
.Dv onp
|
||||
is 0, the disk will be closed once and for all.
|
||||
|
||||
.It Dv WORMIOERROR
|
||||
This call may be used to get additional information when a I/O error
|
||||
occured or to check if the last command ended with a recovered
|
||||
error or a warning. The argument is a pointer to an integer. The
|
||||
returned value can be:
|
||||
.Bl -tag -width WORM_
|
||||
.It Dv WORM_SEQUENCE_ERROR
|
||||
Occurs if a write is performed when the track has not been prepared or
|
||||
if
|
||||
.Dv WORMCPREPTRACK
|
||||
is done without a prior
|
||||
.Dv WORMIOCPREPDISK .
|
||||
.It Dv WORM_BUFFER_UNDERRUN
|
||||
Indicates that the write action stopped because the cache buffer emptied.
|
||||
.It Dv WORM_DUMMY_BLOCKS_ADDED
|
||||
This a warning which may occur when the track is closed. Indicates
|
||||
that during writing dummy blocks are added to meet the disc
|
||||
specification (minimum of 300 blocks for a track).
|
||||
.It Dv WORM_CALIBRATION_AREA_ALMOST_FULL
|
||||
This is warning which indicates that a few Optimum Power Calibration
|
||||
areas are left. It is recommended to fixate after the tracks are written.
|
||||
.It Dv WORM_CALIBRATION_AREA_FULL
|
||||
Indicates that the Calibration area is full. This means that no further
|
||||
writes can be performed on this disc.
|
||||
.It Dv WORM_ABSORPTION_CONTROL_ERROR
|
||||
Indicates that an error might have occurred in the recorded data that
|
||||
was written, caused by laser power clipping. This is a warning.
|
||||
.It Dv WORM_END_OF_MEDIUM
|
||||
Indicates that during writing the end of medium is detected or the
|
||||
amount of track reached the limit of 99.
|
||||
.It Dv WORM_OPTIMUM_POWER_CALIBRATION_ERROR
|
||||
Indicates that power calibration failed. This could indicate: Wrong WO
|
||||
medium installed, laser failure or drive failure.
|
||||
.Pp
|
||||
.El
|
||||
If an unknown error occured, the returned value will be -1.
|
||||
|
||||
.El
|
||||
Specifying wrong argument values to the above ioctl command will cause
|
||||
the driver to return an error condition with
|
||||
.Va errno
|
||||
set to
|
||||
.Er EINVAL .
|
||||
Any attempt to perform something else then selecting a quirks record
|
||||
on a device where this has not been done yet will return an error of
|
||||
.Er ENXIO .
|
||||
.Pp
|
||||
In addition, the
|
||||
.Xr scsi 4
|
||||
|
503
sys/scsi/worm.c
503
sys/scsi/worm.c
@ -43,7 +43,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: worm.c,v 1.37 1997/05/05 13:35:01 joerg Exp $
|
||||
* $Id: worm.c,v 1.38 1997/05/10 12:12:47 joerg Exp $
|
||||
*/
|
||||
|
||||
#include "opt_bounce.h"
|
||||
@ -72,18 +72,12 @@
|
||||
|
||||
struct worm_quirks
|
||||
{
|
||||
/*
|
||||
* Vendor and model are used for comparision; the model may be
|
||||
* abbreviated (or could even be empty at all).
|
||||
*/
|
||||
const char *vendor;
|
||||
const char *model;
|
||||
/*
|
||||
* The device-specific functions that need to be called during
|
||||
* the several steps.
|
||||
*/
|
||||
errval (*prepare_disk)(struct scsi_link *, int dummy, int speed);
|
||||
errval (*prepare_track)(struct scsi_link *, int audio, int preemp);
|
||||
errval (*prepare_track)(struct scsi_link *, struct wormio_prepare_track *t);
|
||||
errval (*finalize_track)(struct scsi_link *);
|
||||
errval (*finalize_disk)(struct scsi_link *, int toc_type, int onp);
|
||||
};
|
||||
@ -105,14 +99,30 @@ struct scsi_data
|
||||
|
||||
u_int8_t dummy; /* use dummy writes */
|
||||
u_int8_t speed; /* select drive speed */
|
||||
u_int8_t audio; /* write audio data */
|
||||
u_int8_t preemp; /* audio only: use preemphasis */
|
||||
|
||||
u_int32_t worm_flags; /* driver-internal flags */
|
||||
#define WORMFL_DISK_PREPED 0x01 /* disk parameters have been spec'ed */
|
||||
#define WORMFL_TRACK_PREPED 0x02 /* track parameters have been spec'ed */
|
||||
#define WORMFL_WRITTEN 0x04 /* track has been written */
|
||||
#define WORMFL_IOCTL_ONLY 0x08 /* O_NDELAY, only ioctls allowed */
|
||||
|
||||
int error; /* last error */
|
||||
};
|
||||
|
||||
struct {
|
||||
int asc;
|
||||
int devmode;
|
||||
int error;
|
||||
int ret;
|
||||
} worm_error[] = {
|
||||
{0x24, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_ABSORPTION_CONTROL_ERROR, 0},
|
||||
{0xb0, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_CALIBRATION_AREA_ALMOST_FULL, 0},
|
||||
{0xb4, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_CALIBRATION_AREA_FULL, SCSIRET_CONTINUE},
|
||||
{0xb5, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_DUMMY_BLOCKS_ADDED, 0},
|
||||
{0xaa, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_END_OF_MEDIUM, SCSIRET_CONTINUE},
|
||||
{0xad, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_BUFFER_UNDERRUN, SCSIRET_CONTINUE},
|
||||
{0xaf, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_OPTIMUM_POWER_CALIBRATION_ERROR, SCSIRET_CONTINUE},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static void wormstart(u_int32_t unit, u_int32_t flags);
|
||||
@ -124,22 +134,20 @@ static errval worm_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
|
||||
static errval worm_close(dev_t dev, int flag, int fmt, struct proc *p,
|
||||
struct scsi_link *sc_link);
|
||||
static void worm_strategy(struct buf *bp, struct scsi_link *sc_link);
|
||||
|
||||
static errval worm_quirk_select(struct scsi_link *sc_link, u_int32_t unit,
|
||||
struct wormio_quirk_select *);
|
||||
static errval worm_read_toc(struct scsi_link *sc_link,
|
||||
u_int32_t mode, u_int32_t start,
|
||||
struct cd_toc_entry *data, u_int32_t len);
|
||||
static errval worm_rezero_unit(struct scsi_link *sc_link);
|
||||
static int worm_sense_handler(struct scsi_xfer *);
|
||||
|
||||
/* XXX should be moved out to an LKM */
|
||||
static errval rf4100_prepare_disk(struct scsi_link *, int dummy, int speed);
|
||||
static errval rf4100_prepare_track(struct scsi_link *, int audio, int preemp);
|
||||
static errval rf4100_prepare_track(struct scsi_link *, struct wormio_prepare_track *);
|
||||
static errval rf4100_finalize_track(struct scsi_link *);
|
||||
static errval rf4100_finalize_disk(struct scsi_link *, int toc_type, int onp);
|
||||
|
||||
static errval hp4020i_prepare_disk(struct scsi_link *, int dummy, int speed);
|
||||
static errval hp4020i_prepare_track(struct scsi_link *, int audio, int preemp);
|
||||
static errval hp4020i_prepare_track(struct scsi_link *, struct wormio_prepare_track *);
|
||||
static errval hp4020i_finalize_track(struct scsi_link *);
|
||||
static errval hp4020i_finalize_disk(struct scsi_link *, int toc_type, int onp);
|
||||
|
||||
@ -168,7 +176,7 @@ SCSI_DEVICE_ENTRIES(worm)
|
||||
|
||||
static struct scsi_device worm_switch =
|
||||
{
|
||||
NULL,
|
||||
worm_sense_handler,
|
||||
wormstart, /* we have a queue, and this is how we service it */
|
||||
NULL,
|
||||
NULL,
|
||||
@ -189,24 +197,13 @@ static struct scsi_device worm_switch =
|
||||
worm_strategy,
|
||||
};
|
||||
|
||||
/* XXX This should become the registration table for the LKMs. */
|
||||
struct worm_quirks worm_quirks[] = {
|
||||
{
|
||||
"PLASMON", "RF410",
|
||||
rf4100_prepare_disk, rf4100_prepare_track,
|
||||
rf4100_finalize_track, rf4100_finalize_disk
|
||||
},
|
||||
{
|
||||
"HP", "4020i",
|
||||
hp4020i_prepare_disk, hp4020i_prepare_track,
|
||||
hp4020i_finalize_track, hp4020i_finalize_disk
|
||||
},
|
||||
{
|
||||
"PHILIPS", "CDD2000",
|
||||
hp4020i_prepare_disk, hp4020i_prepare_track,
|
||||
hp4020i_finalize_track, hp4020i_finalize_disk
|
||||
},
|
||||
{0}
|
||||
static struct worm_quirks worm_quirks_plasmon = {
|
||||
rf4100_prepare_disk, rf4100_prepare_track,
|
||||
rf4100_finalize_track, rf4100_finalize_disk
|
||||
};
|
||||
static struct worm_quirks worm_quirks_philips = {
|
||||
hp4020i_prepare_disk, hp4020i_prepare_track,
|
||||
hp4020i_finalize_track, hp4020i_finalize_disk
|
||||
};
|
||||
|
||||
static inline void
|
||||
@ -238,7 +235,6 @@ worm_size(struct scsi_link *sc_link, int flags)
|
||||
* doesn't give us any good results. Make a more educated
|
||||
* guess instead.
|
||||
*/
|
||||
worm->blk_size = (worm->audio? 2352: 2048);
|
||||
|
||||
if (worm->n_blks)
|
||||
{
|
||||
@ -298,6 +294,9 @@ wormattach(struct scsi_link *sc_link)
|
||||
* XXX It looks like we need a "scsistart" to hoist common code up
|
||||
* into. In particular, the removable media checking should be
|
||||
* handled in one place.
|
||||
*
|
||||
* Writes will fail if the disk and track not been prepared via the control
|
||||
* device.
|
||||
*/
|
||||
static void
|
||||
wormstart(unit, flags)
|
||||
@ -309,7 +308,7 @@ wormstart(unit, flags)
|
||||
register struct buf *bp = 0;
|
||||
struct scsi_rw_big cmd;
|
||||
|
||||
u_int32_t lba; /* Logical block address */
|
||||
u_int32_t lba; /* Logical block address */
|
||||
u_int32_t tl; /* Transfer length */
|
||||
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("wormstart "));
|
||||
@ -340,6 +339,15 @@ wormstart(unit, flags)
|
||||
}
|
||||
TAILQ_REMOVE( &worm->buf_queue, bp, b_act);
|
||||
|
||||
if (((bp->b_flags & B_READ) == B_WRITE)
|
||||
&& ((worm->worm_flags & WORMFL_TRACK_PREPED) == 0)) {
|
||||
SC_DEBUG(sc_link, SDEV_DB3, ("sequence error\n"));
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
worm->error = WORM_SEQUENCE_ERROR;
|
||||
biodone(bp);
|
||||
goto badnews;
|
||||
}
|
||||
/*
|
||||
* Fill out the scsi command
|
||||
*/
|
||||
@ -352,11 +360,19 @@ wormstart(unit, flags)
|
||||
flags |= SCSI_DATA_IN;
|
||||
}
|
||||
|
||||
worm->error = 0;
|
||||
|
||||
lba = bp->b_blkno / (worm->blk_size / DEV_BSIZE);
|
||||
lba = bp->b_blkno / (worm->blk_size / DEV_BSIZE);
|
||||
tl = bp->b_bcount / worm->blk_size;
|
||||
|
||||
scsi_uto4b(lba, &cmd.addr_3);
|
||||
if (bp->b_flags & B_READ)
|
||||
/*
|
||||
* Leave the LBA as 0 for write operations, it
|
||||
* is reserved in this case (and wouldn't make
|
||||
* any sense to set it at all, since CD-R write
|
||||
* operations are in `streaming' mode anyway.
|
||||
*/
|
||||
scsi_uto4b(lba, &cmd.addr_3);
|
||||
scsi_uto2b(tl, &cmd.length2);
|
||||
|
||||
/*
|
||||
@ -459,8 +475,6 @@ worm_strategy(struct buf *bp, struct scsi_link *sc_link)
|
||||
/*
|
||||
* Open the device.
|
||||
* Only called for the "real" device, not for the control device.
|
||||
* Will fail if the disk and track not been prepared via the control
|
||||
* device.
|
||||
*/
|
||||
static int
|
||||
worm_open(dev_t dev, int flags, int fmt, struct proc *p,
|
||||
@ -495,18 +509,7 @@ worm_open(dev_t dev, int flags, int fmt, struct proc *p,
|
||||
* If the device has been opened with O_NONBLOCK set, no
|
||||
* actual IO will be allowed, and the command sequence is only
|
||||
* subject to the restrictions as in worm_ioctl() below.
|
||||
*
|
||||
* If the device is to be opened with O_RDWR/O_WRONLY, the
|
||||
* disk and track must have been prepared accordingly by
|
||||
* preceding ioctls (on an O_NONBLOCK descriptor for the device),
|
||||
* or a sequence error will result here.
|
||||
*/
|
||||
if ((flags & FWRITE) != 0 &&
|
||||
(worm->worm_flags & WORMFL_TRACK_PREPED) == 0) {
|
||||
SC_DEBUG(sc_link, SDEV_DB3, ("sequence error\n"));
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Next time actually take notice of error returns,
|
||||
* unit attn errors are now errors.
|
||||
@ -527,12 +530,9 @@ worm_open(dev_t dev, int flags, int fmt, struct proc *p,
|
||||
|
||||
if((flags & FWRITE) != 0) {
|
||||
if ((error = worm_rezero_unit(sc_link)) != 0 ||
|
||||
(error = worm_size(sc_link, 0)) != 0 ||
|
||||
(error = (worm->quirks->prepare_track)
|
||||
(sc_link, worm->audio, worm->preemp)) != 0) {
|
||||
(error = worm_size(sc_link, 0)) != 0) {
|
||||
SC_DEBUG(sc_link, SDEV_DB3,
|
||||
("rezero, get size, or prepare_track failed\n"));
|
||||
scsi_stop_unit(sc_link, 0, SCSI_SILENT);
|
||||
("rezero, or get size failed\n"));
|
||||
scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
|
||||
worm->worm_flags &= ~WORMFL_TRACK_PREPED;
|
||||
sc_link->flags &= ~SDEV_OPEN;
|
||||
@ -542,7 +542,6 @@ worm_open(dev_t dev, int flags, int fmt, struct proc *p,
|
||||
if ((error = worm_size(sc_link, 0)) != 0) {
|
||||
SC_DEBUG(sc_link, SDEV_DB3,
|
||||
("get size failed\n"));
|
||||
scsi_stop_unit(sc_link, 0, SCSI_SILENT);
|
||||
scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
|
||||
worm->worm_flags &= ~WORMFL_TRACK_PREPED;
|
||||
sc_link->flags &= ~SDEV_OPEN;
|
||||
@ -551,6 +550,17 @@ worm_open(dev_t dev, int flags, int fmt, struct proc *p,
|
||||
} else
|
||||
worm->worm_flags |= WORMFL_IOCTL_ONLY;
|
||||
|
||||
switch (*(int *) sc_link->devmodes) {
|
||||
case WORM_Q_PLASMON:
|
||||
worm->quirks = &worm_quirks_plasmon;
|
||||
break;
|
||||
case WORM_Q_PHILIPS:
|
||||
worm->quirks = &worm_quirks_philips;
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
}
|
||||
worm->error = 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -564,15 +574,13 @@ worm_close(dev_t dev, int flags, int fmt, struct proc *p,
|
||||
error = 0;
|
||||
|
||||
if ((worm->worm_flags & WORMFL_IOCTL_ONLY) == 0) {
|
||||
scsi_stop_unit(sc_link, 0, SCSI_SILENT);
|
||||
scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
|
||||
|
||||
sc_link->flags &= ~SDEV_OPEN;
|
||||
|
||||
if ((flags & FWRITE) != 0) {
|
||||
worm->worm_flags &= ~WORMFL_TRACK_PREPED;
|
||||
worm->error = 0;
|
||||
if ((worm->worm_flags & WORMFL_TRACK_PREPED) != 0)
|
||||
error = (worm->quirks->finalize_track)(sc_link);
|
||||
worm->worm_flags &= ~WORMFL_TRACK_PREPED;
|
||||
}
|
||||
scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
|
||||
}
|
||||
sc_link->flags &= ~SDEV_OPEN;
|
||||
worm->worm_flags &= ~WORMFL_IOCTL_ONLY;
|
||||
@ -600,75 +608,76 @@ worm_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("wormioctl 0x%x ", cmd));
|
||||
|
||||
switch (cmd) {
|
||||
case WORMIOCQUIRKSELECT:
|
||||
error = worm_quirk_select(sc_link, unit,
|
||||
(struct wormio_quirk_select *)addr);
|
||||
break;
|
||||
|
||||
case WORMIOCPREPDISK:
|
||||
if (worm->quirks == 0)
|
||||
error = ENXIO;
|
||||
else {
|
||||
struct wormio_prepare_disk *w =
|
||||
(struct wormio_prepare_disk *)addr;
|
||||
if (w->dummy != 0 && w->dummy != 1)
|
||||
error = EINVAL;
|
||||
else {
|
||||
error = (worm->quirks->prepare_disk)
|
||||
(sc_link, w->dummy, w->speed);
|
||||
if (error == 0) {
|
||||
worm->worm_flags |= WORMFL_DISK_PREPED;
|
||||
worm->dummy = w->dummy;
|
||||
worm->speed = w->speed;
|
||||
}
|
||||
}
|
||||
{
|
||||
struct wormio_prepare_disk *w =
|
||||
(struct wormio_prepare_disk *)addr;
|
||||
if (w->dummy != 0 && w->dummy != 1)
|
||||
error = EINVAL;
|
||||
else {
|
||||
error = (worm->quirks->prepare_disk)
|
||||
(sc_link, w->dummy, w->speed);
|
||||
if (error == 0) {
|
||||
worm->worm_flags |= WORMFL_DISK_PREPED;
|
||||
worm->dummy = w->dummy;
|
||||
worm->speed = w->speed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WORMIOCPREPTRACK:
|
||||
if (worm->quirks == 0)
|
||||
error = ENXIO;
|
||||
else {
|
||||
struct wormio_prepare_track *w =
|
||||
(struct wormio_prepare_track *)addr;
|
||||
if (w->audio != 0 && w->audio != 1)
|
||||
error = EINVAL;
|
||||
else if (w->audio == 0 && w->preemp)
|
||||
error = EINVAL;
|
||||
else if ((worm->worm_flags & WORMFL_DISK_PREPED)==0)
|
||||
error = EINVAL;
|
||||
else {
|
||||
worm->audio = w->audio;
|
||||
worm->preemp = w->preemp;
|
||||
worm->worm_flags |=
|
||||
WORMFL_TRACK_PREPED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
{
|
||||
struct wormio_prepare_track *w =
|
||||
(struct wormio_prepare_track *)addr;
|
||||
if (w->audio != 0 && w->audio != 1)
|
||||
error = EINVAL;
|
||||
else if (w->audio == 0 && w->preemp)
|
||||
error = EINVAL;
|
||||
else if ((worm->worm_flags & WORMFL_DISK_PREPED)==0) {
|
||||
error = EINVAL;
|
||||
worm->error = WORM_SEQUENCE_ERROR;
|
||||
} else {
|
||||
if ((error = (worm->quirks->prepare_track)
|
||||
(sc_link, w)) == 0)
|
||||
worm->worm_flags |=
|
||||
WORMFL_TRACK_PREPED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WORMIOCFINISHTRACK:
|
||||
error = (worm->quirks->finalize_track)(sc_link);
|
||||
worm->worm_flags &= ~WORMFL_TRACK_PREPED;
|
||||
break;
|
||||
|
||||
case WORMIOCFIXATION:
|
||||
if (worm->quirks == 0)
|
||||
error = ENXIO;
|
||||
else {
|
||||
struct wormio_fixation *w =
|
||||
(struct wormio_fixation *)addr;
|
||||
|
||||
if ((worm->worm_flags & WORMFL_WRITTEN) == 0)
|
||||
error = EINVAL;
|
||||
else if (w->toc_type < WORM_TOC_TYPE_AUDIO ||
|
||||
w->toc_type > WORM_TOC_TYPE_CDI)
|
||||
error = EINVAL;
|
||||
else if (w->onp != 0 && w->onp != 1)
|
||||
error = EINVAL;
|
||||
else {
|
||||
worm->worm_flags = 0;
|
||||
/* no fixation needed if dummy write */
|
||||
if (worm->dummy == 0)
|
||||
error = (worm->quirks->finalize_disk)
|
||||
(sc_link, w->toc_type, w->onp);
|
||||
}
|
||||
{
|
||||
struct wormio_fixation *w =
|
||||
(struct wormio_fixation *)addr;
|
||||
|
||||
if ((worm->worm_flags & WORMFL_WRITTEN) == 0)
|
||||
error = EINVAL;
|
||||
else if (w->toc_type < WORM_TOC_TYPE_AUDIO ||
|
||||
w->toc_type > WORM_TOC_TYPE_CDI)
|
||||
error = EINVAL;
|
||||
else if (w->onp != 0 && w->onp != 1)
|
||||
error = EINVAL;
|
||||
else {
|
||||
worm->worm_flags = 0;
|
||||
/* no fixation needed if dummy write */
|
||||
if (worm->dummy == 0) {
|
||||
worm->error = 0;
|
||||
error = (worm->quirks->finalize_disk)
|
||||
(sc_link, w->toc_type, w->onp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WORMIOERROR:
|
||||
bcopy(&(worm->error), addr, sizeof (int));
|
||||
break;
|
||||
|
||||
case CDIOREADTOCHEADER:
|
||||
{
|
||||
@ -877,33 +886,29 @@ worm_read_toc(struct scsi_link *sc_link, u_int32_t mode, u_int32_t start,
|
||||
SCSI_DATA_IN));
|
||||
}
|
||||
|
||||
static errval
|
||||
worm_quirk_select(struct scsi_link *sc_link, u_int32_t unit,
|
||||
struct wormio_quirk_select *qs)
|
||||
static int
|
||||
worm_sense_handler(struct scsi_xfer *xs)
|
||||
{
|
||||
struct worm_quirks *qp;
|
||||
struct scsi_data *worm = sc_link->sd;
|
||||
errval error = 0;
|
||||
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("worm_quirk_select"));
|
||||
struct scsi_data *worm;
|
||||
struct scsi_sense_data *sense;
|
||||
struct scsi_sense_extended *ext;
|
||||
int asc, devmode, i;
|
||||
|
||||
worm = xs->sc_link->sd;
|
||||
sense = &(xs->sense);
|
||||
ext = (struct scsi_sense_extended *) &(sense->ext.extended);
|
||||
asc = ext->add_sense_code;
|
||||
devmode = *(int *) xs->sc_link->devmodes;
|
||||
|
||||
for (qp = worm_quirks; qp->vendor; qp++)
|
||||
if (strcmp(qp->vendor, qs->vendor) == 0 &&
|
||||
strncmp(qp->model, qs->model, strlen(qp->model)) == 0)
|
||||
break;
|
||||
if (qp->vendor) {
|
||||
SC_DEBUG(sc_link, SDEV_DB3,
|
||||
("worm_quirk_select: %s %s",
|
||||
qp->vendor, qp->model));
|
||||
worm->quirks = qp;
|
||||
for (i = 0; worm_error[i].asc; i++)
|
||||
if ((asc == worm_error[i].asc) && (devmode & worm_error[i].devmode)) {
|
||||
worm->error = worm_error[i].error;
|
||||
return worm_error[i].ret;
|
||||
}
|
||||
else
|
||||
error = EINVAL;
|
||||
|
||||
return error;
|
||||
worm->error = -1;
|
||||
return SCSIRET_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
worm_drvinit(void *unused)
|
||||
{
|
||||
@ -920,6 +925,16 @@ SYSINIT(wormdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,worm_drvinit,NULL)
|
||||
* Begin device-specific stuff. Subject to being moved out to LKMs.
|
||||
*/
|
||||
|
||||
static u_char
|
||||
ascii_to_6bit (char c)
|
||||
{
|
||||
if (c < '0' || c > 'Z' || (c > '9' && c < 'A'))
|
||||
return 0;
|
||||
if (c <= '9')
|
||||
return c - '0';
|
||||
else
|
||||
return c - 'A' + 11;
|
||||
}
|
||||
/*
|
||||
* PLASMON RF4100/4102
|
||||
* Perhaps other Plasmon's, too.
|
||||
@ -951,7 +966,7 @@ struct plasmon_rf4100_pages
|
||||
#define RF4100_MIXED_MODE 0x08 /* mixed mode data enabled */
|
||||
#define RF4100_AUDIO_MODE 0x04 /* audio mode data enabled */
|
||||
#define RF4100_MODE_1 0x01 /* mode 1 blocks are enabled */
|
||||
#define RF4110_MODE_2 0x02 /* mode 2 blocks are enabled */
|
||||
#define RF4100_MODE_2 0x02 /* mode 2 blocks are enabled */
|
||||
u_char track_number;
|
||||
u_char isrc_i1; /* country code, ASCII */
|
||||
u_char isrc_i2;
|
||||
@ -1028,15 +1043,19 @@ rf4100_prepare_disk(struct scsi_link *sc_link, int dummy, int speed)
|
||||
|
||||
|
||||
static errval
|
||||
rf4100_prepare_track(struct scsi_link *sc_link, int audio, int preemp)
|
||||
rf4100_prepare_track(struct scsi_link *sc_link, struct wormio_prepare_track *t)
|
||||
{
|
||||
struct scsi_mode_select scsi_cmd;
|
||||
struct scsi_data *worm;
|
||||
struct {
|
||||
struct scsi_mode_header header;
|
||||
struct blk_desc blk_desc;
|
||||
struct plasmon_rf4100_pages page;
|
||||
} dat;
|
||||
u_int32_t pagelen, dat_len, blk_len;
|
||||
int year;
|
||||
|
||||
worm = sc_link->sd;
|
||||
|
||||
pagelen = sizeof(dat.page.pages.page_0x21) + PAGE_HEADERLEN;
|
||||
dat_len = sizeof(struct scsi_mode_header)
|
||||
@ -1045,16 +1064,6 @@ rf4100_prepare_track(struct scsi_link *sc_link, int audio, int preemp)
|
||||
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("rf4100_prepare_track"));
|
||||
|
||||
if (!audio && preemp)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* By now, make a simple decision about the block length to be
|
||||
* used. It's just only Red Book (Audio) == 2352 bytes, or
|
||||
* Yellow Book (CD-ROM) Mode 1 == 2048 bytes.
|
||||
*/
|
||||
blk_len = audio? 2352: 2048;
|
||||
|
||||
/*
|
||||
* Set up a mode page 0x21. Note that the block descriptor is
|
||||
* mandatory in at least one of the MODE SELECT commands, in
|
||||
@ -1072,15 +1081,70 @@ rf4100_prepare_track(struct scsi_link *sc_link, int audio, int preemp)
|
||||
scsi_cmd.op_code = MODE_SELECT;
|
||||
scsi_cmd.length = dat_len;
|
||||
dat.header.blk_desc_len = sizeof(struct blk_desc);
|
||||
/* dat.header.dev_spec = host application code; (see spec) */
|
||||
scsi_uto3b(blk_len, dat.blk_desc.blklen);
|
||||
dat.page.page_code = RF4100_PAGE_CODE_21;
|
||||
dat.page.param_len = sizeof(dat.page.pages.page_0x21);
|
||||
dat.page.pages.page_0x21.mode =
|
||||
(audio? RF4100_AUDIO_MODE: RF4100_MODE_1) +
|
||||
(preemp? RF4100_MODE_1: 0);
|
||||
/* dat.page.pages.page_0x21.track_number = 0; (current track) */
|
||||
/* dat.header.dev_spec = host application code; (see spec) */
|
||||
if (t->audio) {
|
||||
blk_len = 2352;
|
||||
dat.page.pages.page_0x21.mode = RF4100_AUDIO_MODE +
|
||||
(t->preemp? RF4100_MODE_1 : 0);
|
||||
} else
|
||||
switch (t->track_type) {
|
||||
case BLOCK_RAW:
|
||||
blk_len = 2352;
|
||||
dat.page.pages.page_0x21.mode = RF4100_RAW_MODE;
|
||||
break;
|
||||
case BLOCK_MODE_1:
|
||||
blk_len = 2048;
|
||||
dat.page.pages.page_0x21.mode = RF4100_MODE_1;
|
||||
break;
|
||||
case BLOCK_MODE_2:
|
||||
blk_len = 2336;
|
||||
dat.page.pages.page_0x21.mode = RF4100_MODE_2;
|
||||
break;
|
||||
case BLOCK_MODE_2_FORM_1:
|
||||
blk_len = 2048;
|
||||
dat.page.pages.page_0x21.mode = RF4100_MODE_2;
|
||||
break;
|
||||
case BLOCK_MODE_2_FORM_1b:
|
||||
blk_len = 2056;
|
||||
dat.page.pages.page_0x21.mode = RF4100_MODE_2;
|
||||
break;
|
||||
case BLOCK_MODE_2_FORM_2:
|
||||
blk_len = 2324;
|
||||
dat.page.pages.page_0x21.mode = RF4100_MODE_2;
|
||||
break;
|
||||
case BLOCK_MODE_2_FORM_2b:
|
||||
blk_len = 2332;
|
||||
dat.page.pages.page_0x21.mode = RF4100_MODE_2;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
dat.page.pages.page_0x21.mode |= t->copy_bits << 5;
|
||||
|
||||
worm->blk_size = blk_len;
|
||||
|
||||
dat.page.pages.page_0x21.track_number = t->track_number;
|
||||
|
||||
dat.page.pages.page_0x21.isrc_i1 = ascii_to_6bit(t->ISRC_country[0]);
|
||||
dat.page.pages.page_0x21.isrc_i2 = ascii_to_6bit(t->ISRC_country[1]);
|
||||
dat.page.pages.page_0x21.isrc_i3 = ascii_to_6bit(t->ISRC_owner[0]);
|
||||
dat.page.pages.page_0x21.isrc_i4 = ascii_to_6bit(t->ISRC_owner[1]);
|
||||
dat.page.pages.page_0x21.isrc_i5 = ascii_to_6bit(t->ISRC_owner[2]);
|
||||
year = t->ISRC_year > 1900 ? t->ISRC_year - 1900 : t->ISRC_year;
|
||||
if (year > 99 || year < 0)
|
||||
return EINVAL;
|
||||
dat.page.pages.page_0x21.isrc_i6_7 = bin2bcd(year);
|
||||
if (t->ISRC_serial[0]) {
|
||||
dat.page.pages.page_0x21.isrc_i8_9 = ((t->ISRC_serial[0]-'0') << 8) ||
|
||||
(t->ISRC_serial[1] - '0');
|
||||
dat.page.pages.page_0x21.isrc_i10_11 = ((t->ISRC_serial[2]-'0') << 8) ||
|
||||
(t->ISRC_serial[3] - '0');
|
||||
dat.page.pages.page_0x21.isrc_i12_0 = (t->ISRC_serial[4] - '0' << 8);
|
||||
}
|
||||
scsi_uto3b(blk_len, dat.blk_desc.blklen);
|
||||
|
||||
/*
|
||||
* Fire it off.
|
||||
*/
|
||||
@ -1100,7 +1164,8 @@ static errval
|
||||
rf4100_finalize_track(struct scsi_link *sc_link)
|
||||
{
|
||||
struct scsi_synchronize_cache cmd;
|
||||
|
||||
int error;
|
||||
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("rf4100_finalize_track"));
|
||||
|
||||
/*
|
||||
@ -1108,7 +1173,7 @@ rf4100_finalize_track(struct scsi_link *sc_link)
|
||||
*/
|
||||
bzero(&cmd, sizeof(cmd));
|
||||
cmd.op_code = SYNCHRONIZE_CACHE;
|
||||
return scsi_scsi_cmd(sc_link,
|
||||
error = scsi_scsi_cmd(sc_link,
|
||||
(struct scsi_generic *) &cmd,
|
||||
sizeof(cmd),
|
||||
0, /* no data transfer */
|
||||
@ -1117,6 +1182,13 @@ rf4100_finalize_track(struct scsi_link *sc_link)
|
||||
60000, /* this may take a while */
|
||||
NULL,
|
||||
0);
|
||||
if (!error) {
|
||||
struct wormio_prepare_track t;
|
||||
bzero (&t, sizeof (t));
|
||||
t.track_type = BLOCK_MODE_1;
|
||||
error = rf4100_prepare_track(sc_link, &t);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@ -1190,7 +1262,7 @@ struct hp_4020i_pages
|
||||
u_char isrc_i3; /* owner code, ASCII */
|
||||
u_char isrc_i4;
|
||||
u_char isrc_i5;
|
||||
u_char isrc_i6_7; /* country code, BCD */
|
||||
u_char isrc_i6_7; /* year code, BCD */
|
||||
u_char isrc_i8_9; /* serial number, BCD */
|
||||
u_char isrc_i10_11;
|
||||
u_char isrc_i12_0;
|
||||
@ -1261,15 +1333,19 @@ hp4020i_prepare_disk(struct scsi_link *sc_link, int dummy, int speed)
|
||||
|
||||
|
||||
static errval
|
||||
hp4020i_prepare_track(struct scsi_link *sc_link, int audio, int preemp)
|
||||
hp4020i_prepare_track(struct scsi_link *sc_link, struct wormio_prepare_track *t)
|
||||
{
|
||||
struct scsi_mode_select scsi_cmd;
|
||||
struct scsi_data *worm;
|
||||
struct {
|
||||
struct scsi_mode_header header;
|
||||
struct blk_desc blk_desc;
|
||||
struct hp_4020i_pages page;
|
||||
} dat;
|
||||
u_int32_t pagelen, dat_len, blk_len;
|
||||
int year;
|
||||
|
||||
worm = sc_link->sd;
|
||||
|
||||
pagelen = sizeof(dat.page.pages.page_0x21) + PAGE_HEADERLEN;
|
||||
dat_len = sizeof(struct scsi_mode_header)
|
||||
@ -1278,15 +1354,6 @@ hp4020i_prepare_track(struct scsi_link *sc_link, int audio, int preemp)
|
||||
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_prepare_track"));
|
||||
|
||||
if (!audio && preemp)
|
||||
return EINVAL;
|
||||
|
||||
/*
|
||||
* By now, make a simple decision about the block length to be
|
||||
* used. It's just only Red Book (Audio) == 2352 bytes, or
|
||||
* Yellow Book (CD-ROM) Mode 1 == 2048 bytes.
|
||||
*/
|
||||
blk_len = audio? 2352: 2048;
|
||||
|
||||
/*
|
||||
* Set up a mode page 0x21. Note that the block descriptor is
|
||||
@ -1306,14 +1373,70 @@ hp4020i_prepare_track(struct scsi_link *sc_link, int audio, int preemp)
|
||||
scsi_cmd.byte2 |= SMS_PF;
|
||||
scsi_cmd.length = dat_len;
|
||||
dat.header.blk_desc_len = sizeof(struct blk_desc);
|
||||
/* dat.header.dev_spec = host application code; (see spec) */
|
||||
scsi_uto3b(blk_len, dat.blk_desc.blklen);
|
||||
dat.page.page_code = HP4020I_PAGE_CODE_21;
|
||||
dat.page.param_len = sizeof(dat.page.pages.page_0x21);
|
||||
dat.page.pages.page_0x21.mode =
|
||||
(audio? HP4020I_AUDIO_MODE: HP4020I_MODE_1) +
|
||||
(preemp? HP4020I_MODE_1: 0);
|
||||
/* dat.page.pages.page_0x21.track_number = 0; (current track) */
|
||||
/* dat.header.dev_spec = host application code; (see spec) */
|
||||
if (t->audio) {
|
||||
blk_len = 2352;
|
||||
dat.page.pages.page_0x21.mode = HP4020I_AUDIO_MODE +
|
||||
(t->preemp? HP4020I_MODE_1 : 0);
|
||||
} else
|
||||
switch (t->track_type) {
|
||||
case BLOCK_RAW:
|
||||
blk_len = 2352;
|
||||
dat.page.pages.page_0x21.mode = HP4020I_RAW_MODE;
|
||||
break;
|
||||
case BLOCK_MODE_1:
|
||||
blk_len = 2048;
|
||||
dat.page.pages.page_0x21.mode = HP4020I_MODE_1;
|
||||
break;
|
||||
case BLOCK_MODE_2:
|
||||
blk_len = 2336;
|
||||
dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
|
||||
break;
|
||||
case BLOCK_MODE_2_FORM_1:
|
||||
blk_len = 2048;
|
||||
dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
|
||||
break;
|
||||
case BLOCK_MODE_2_FORM_1b:
|
||||
blk_len = 2056;
|
||||
dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
|
||||
break;
|
||||
case BLOCK_MODE_2_FORM_2:
|
||||
blk_len = 2324;
|
||||
dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
|
||||
break;
|
||||
case BLOCK_MODE_2_FORM_2b:
|
||||
blk_len = 2332;
|
||||
dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
dat.page.pages.page_0x21.mode |= t->copy_bits << 5;
|
||||
|
||||
worm->blk_size = blk_len;
|
||||
|
||||
dat.page.pages.page_0x21.track_number = t->track_number;
|
||||
|
||||
dat.page.pages.page_0x21.isrc_i1 = ascii_to_6bit(t->ISRC_country[0]);
|
||||
dat.page.pages.page_0x21.isrc_i2 = ascii_to_6bit(t->ISRC_country[1]);
|
||||
dat.page.pages.page_0x21.isrc_i3 = ascii_to_6bit(t->ISRC_owner[0]);
|
||||
dat.page.pages.page_0x21.isrc_i4 = ascii_to_6bit(t->ISRC_owner[1]);
|
||||
dat.page.pages.page_0x21.isrc_i5 = ascii_to_6bit(t->ISRC_owner[2]);
|
||||
year = t->ISRC_year > 1900 ? t->ISRC_year - 1900 : t->ISRC_year;
|
||||
if (year > 99 || year < 0)
|
||||
return EINVAL;
|
||||
dat.page.pages.page_0x21.isrc_i6_7 = bin2bcd(year);
|
||||
if (t->ISRC_serial[0]) {
|
||||
dat.page.pages.page_0x21.isrc_i8_9 = ((t->ISRC_serial[0]-'0') << 8) ||
|
||||
(t->ISRC_serial[1] - '0');
|
||||
dat.page.pages.page_0x21.isrc_i10_11 = ((t->ISRC_serial[2]-'0') << 8) ||
|
||||
(t->ISRC_serial[3] - '0');
|
||||
dat.page.pages.page_0x21.isrc_i12_0 = (t->ISRC_serial[4] - '0' << 8);
|
||||
}
|
||||
|
||||
scsi_uto3b(blk_len, dat.blk_desc.blklen);
|
||||
|
||||
/*
|
||||
* Fire it off.
|
||||
@ -1334,7 +1457,8 @@ static errval
|
||||
hp4020i_finalize_track(struct scsi_link *sc_link)
|
||||
{
|
||||
struct scsi_synchronize_cache cmd;
|
||||
|
||||
int error;
|
||||
|
||||
SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_finalize_track"));
|
||||
|
||||
/*
|
||||
@ -1342,7 +1466,7 @@ hp4020i_finalize_track(struct scsi_link *sc_link)
|
||||
*/
|
||||
bzero(&cmd, sizeof(cmd));
|
||||
cmd.op_code = SYNCHRONIZE_CACHE;
|
||||
return scsi_scsi_cmd(sc_link,
|
||||
error = scsi_scsi_cmd(sc_link,
|
||||
(struct scsi_generic *) &cmd,
|
||||
sizeof(cmd),
|
||||
0, /* no data transfer */
|
||||
@ -1351,6 +1475,13 @@ hp4020i_finalize_track(struct scsi_link *sc_link)
|
||||
60000, /* this may take a while */
|
||||
NULL,
|
||||
0);
|
||||
if (!error) {
|
||||
struct wormio_prepare_track t;
|
||||
bzero (&t, sizeof (t));
|
||||
t.track_type = BLOCK_MODE_1;
|
||||
error = hp4020i_prepare_track(sc_link, &t);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,18 +9,6 @@
|
||||
* Ioctls for the WORM drive *
|
||||
\***************************************************************/
|
||||
|
||||
/*
|
||||
* Quirk select: chose the set of quirk functions to use for this
|
||||
* device.
|
||||
*/
|
||||
|
||||
struct wormio_quirk_select
|
||||
{
|
||||
const char *vendor; /* vendor name */
|
||||
const char *model; /* model name */
|
||||
};
|
||||
|
||||
#define WORMIOCQUIRKSELECT _IOW('W', 10, struct wormio_quirk_select)
|
||||
|
||||
/*
|
||||
* Prepare disk-wide parameters.
|
||||
@ -42,10 +30,29 @@ struct wormio_prepare_track
|
||||
{
|
||||
int audio; /* audio track (data track if 0) */
|
||||
int preemp; /* audio with preemphasis */
|
||||
#define BLOCK_RAW 0 /* 2352 bytes, raw data */
|
||||
#define BLOCK_RAWPQ 1 /* 2368 bytes, raw data with P and Q subchannels */
|
||||
#define BLOCK_RAWPW 2 /* 2448 bytes, raw data with P-W subchannel appended */
|
||||
#define BLOCK_MODE_1 8 /* 2048 bytes, mode 1 (ISO/IEC 10149) */
|
||||
#define BLOCK_MODE_2 9 /* 2336 bytes, mode 2 (ISO/IEC 10149) */
|
||||
#define BLOCK_MODE_2_FORM_1 10 /* 2048 bytes, CD-ROM XA form 1 */
|
||||
#define BLOCK_MODE_2_FORM_1b 11 /* 2056 bytes, CD-ROM XA form 1 */
|
||||
#define BLOCK_MODE_2_FORM_2 12 /* 2324 bytes, CD-ROM XA form 2 */
|
||||
#define BLOCK_MODE_2_FORM_2b 13 /* 2332 bytes, CD-ROM XA form 2 */
|
||||
int track_type; /* defines the number of bytes in a block */
|
||||
#define COPY_INHIBIT 0 /* no copy allowed */
|
||||
#define COPY_PERMITTED 1 /* track can be copied */
|
||||
#define COPY_SCMS 2 /* alternate copy */
|
||||
int copy_bits; /* define the possibilities for copying */
|
||||
int track_number;
|
||||
char ISRC_country[2]; /* country code (2 chars) */
|
||||
char ISRC_owner[3]; /* owner code (3 chars) */
|
||||
int ISRC_year; /* year of recording */
|
||||
char ISRC_serial[5]; /* serial number */
|
||||
};
|
||||
|
||||
#define WORMIOCPREPTRACK _IOW('W', 21, struct wormio_prepare_track)
|
||||
|
||||
|
||||
/*
|
||||
* Fixation: write leadins and leadouts. Select table-of-contents
|
||||
* type for this session. If onp is != 0, another session will be
|
||||
@ -60,4 +67,21 @@ struct wormio_fixation
|
||||
|
||||
#define WORMIOCFIXATION _IOW('W', 22, struct wormio_fixation)
|
||||
|
||||
/*
|
||||
* Finalize track
|
||||
*/
|
||||
#define WORMIOCFINISHTRACK _IO('W', 23)
|
||||
|
||||
/* Errors/warnings */
|
||||
#define WORM_SEQUENCE_ERROR 1
|
||||
#define WORM_DUMMY_BLOCKS_ADDED 2
|
||||
#define WORM_CALIBRATION_AREA_ALMOST_FULL 3
|
||||
#define WORM_CALIBRATION_AREA_FULL 4
|
||||
#define WORM_BUFFER_UNDERRUN 5
|
||||
#define WORM_ABSORPTION_CONTROL_ERROR 6
|
||||
#define WORM_END_OF_MEDIUM 7
|
||||
#define WORM_OPTIMUM_POWER_CALIBRATION_ERROR 8
|
||||
|
||||
#define WORMIOERROR _IOR('W', 24, int)
|
||||
|
||||
#endif /* !_SYS_WORMIO_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user