mirror of
https://github.com/phabrics/Run-Sun3-SunOS-4.1.1.git
synced 2026-04-29 11:02:59 -04:00
630 lines
19 KiB
C
630 lines
19 KiB
C
/* $Id: scsi-cdrom.c,v 1.3 2009/09/26 13:07:39 fredette Exp $ */
|
|
|
|
/* scsi/scsi-cdrom.c - implementation of SCSI CD-ROM emulation: */
|
|
|
|
/*
|
|
* Copyright (c) 2007 Matt Fredette
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Matt Fredette.
|
|
* 4. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <tme/common.h>
|
|
_TME_RCSID("$Id: scsi-cdrom.c,v 1.3 2009/09/26 13:07:39 fredette Exp $");
|
|
|
|
/* includes: */
|
|
#include <tme/scsi/scsi-cdrom.h>
|
|
#ifdef HAVE_STDARG_H
|
|
#include <stdarg.h>
|
|
#else /* HAVE_STDARG_H */
|
|
#include <varargs.h>
|
|
#endif /* HAVE_STDARG_H */
|
|
|
|
/* macros: */
|
|
|
|
/* globals: */
|
|
|
|
/* the list of cdroms that we emulate: */
|
|
const struct {
|
|
|
|
/* the type name: */
|
|
const char *_tme_scsi_cdrom_list_type;
|
|
|
|
/* the initialization function: */
|
|
int (*_tme_scsi_cdrom_list_init) _TME_P((struct tme_scsi_cdrom *));
|
|
} _tme_scsi_cdrom_list[] = {
|
|
|
|
/* the generic TME SCSI-1 cdrom: */
|
|
{ "tme-scsi-1", tme_scsi_cdrom_tme_init },
|
|
};
|
|
|
|
/* this implements the CD-ROM INQUIRY command: */
|
|
_TME_SCSI_DEVICE_CDB_DECL(tme_scsi_cdrom_cdb_inquiry)
|
|
{
|
|
int lun;
|
|
struct tme_scsi_device_inquiry inquiry;
|
|
tme_uint8_t *data;
|
|
|
|
/* get the active LUN: */
|
|
lun = scsi_device->tme_scsi_device_addressed_lun;
|
|
|
|
/* this is a CD-ROM: */
|
|
inquiry.tme_scsi_device_inquiry_type = TME_SCSI_TYPE_CDROM;
|
|
|
|
/* if this LUN is defined: */
|
|
inquiry.tme_scsi_device_inquiry_lun_state
|
|
= ((scsi_device->tme_scsi_device_luns
|
|
& TME_BIT(lun))
|
|
? TME_SCSI_LUN_PRESENT
|
|
: TME_SCSI_LUN_UNSUPPORTED);
|
|
|
|
/* the device type qualifier: */
|
|
inquiry.tme_scsi_device_inquiry_type_qualifier = 0x00;
|
|
|
|
/* nonzero iff the LUN is removable: */
|
|
inquiry.tme_scsi_device_inquiry_lun_removable = TRUE;
|
|
|
|
/* the various standards versions: */
|
|
inquiry.tme_scsi_device_inquiry_std_ansi = 1;
|
|
inquiry.tme_scsi_device_inquiry_std_ecma = 1;
|
|
inquiry.tme_scsi_device_inquiry_std_iso = 1;
|
|
|
|
/* the response format: */
|
|
inquiry.tme_scsi_device_response_format = TME_SCSI_FORMAT_CCS;
|
|
|
|
/* make the inquiry data: */
|
|
data
|
|
= tme_scsi_device_make_inquiry_data(scsi_device,
|
|
&inquiry);
|
|
scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
|
|
= TME_MIN((data
|
|
- scsi_device->tme_scsi_device_dma.tme_scsi_dma_out),
|
|
scsi_device->tme_scsi_device_cdb[4]);
|
|
|
|
/* finish the command: */
|
|
tme_scsi_device_target_do_dsmf(scsi_device,
|
|
TME_SCSI_STATUS_GOOD,
|
|
TME_SCSI_MSG_CMD_COMPLETE);
|
|
}
|
|
|
|
/* this implements the CD-ROM READ TOC command: */
|
|
_TME_SCSI_DEVICE_CDB_DECL(tme_scsi_cdrom_cdb_read_toc)
|
|
{
|
|
struct tme_scsi_cdrom *scsi_cdrom;
|
|
struct tme_scsi_cdrom_connection *conn_scsi_cdrom;
|
|
struct tme_disk_connection *conn_disk;
|
|
tme_uint8_t *data;
|
|
tme_uint32_t space;
|
|
tme_uint32_t length;
|
|
int lun;
|
|
|
|
/* recover our CD-ROM: */
|
|
scsi_cdrom = (struct tme_scsi_cdrom *) scsi_device;
|
|
|
|
/* get the active LUN: */
|
|
lun = scsi_device->tme_scsi_device_addressed_lun;
|
|
|
|
/* get the CD-ROM connection: */
|
|
conn_scsi_cdrom
|
|
= scsi_cdrom->tme_scsi_cdrom_connections[lun];
|
|
conn_disk
|
|
= ((struct tme_disk_connection *)
|
|
conn_scsi_cdrom->tme_scsi_disk_connection.tme_disk_connection.tme_connection_other);
|
|
|
|
/* we require that the MSF bit be zero: */
|
|
if (scsi_device->tme_scsi_device_cdb[1] & 0x02) {
|
|
tme_scsi_device_check_condition(scsi_device,
|
|
TME_SCSI_SENSE_EXT_KEY_ILLEGAL_REQUEST,
|
|
TME_SCSI_SENSE_EXT_ASC_ASCQ_INVALID_FIELD_CDB);
|
|
return;
|
|
}
|
|
|
|
/* "If the starting track field is not valid for the currently
|
|
installed medium, the command shall be terminated with CHECK
|
|
CONDITION status. The sense key shall be set to ILLEGAL REQUEST
|
|
and the additional sense code set to INVALID FIELD IN CDB." */
|
|
/* NB: for now, we support only one track: */
|
|
if (scsi_device->tme_scsi_device_cdb[6] > 1) {
|
|
tme_scsi_device_check_condition(scsi_device,
|
|
TME_SCSI_SENSE_EXT_KEY_ILLEGAL_REQUEST,
|
|
TME_SCSI_SENSE_EXT_ASC_ASCQ_INVALID_FIELD_CDB);
|
|
return;
|
|
}
|
|
|
|
/* start returning the data: */
|
|
data = &scsi_device->tme_scsi_device_data[0];
|
|
|
|
/* bytes 0 and 1 are the TOC data length. we will fill this in later: */
|
|
data += 2;
|
|
|
|
/* the first and last track numbers: */
|
|
/* NB: for now, we support only one track: */
|
|
*(data++) = 1;
|
|
*(data++) = 1;
|
|
|
|
/* one TOC track descriptor: */
|
|
|
|
/* a reserved byte: */
|
|
data++;
|
|
|
|
/* the ADR and control byte: */
|
|
/* NB: this specifies no sub-channel Q mode, and a data track: */
|
|
*(data++) = (0x0 << 4) | (1 << 2);
|
|
|
|
/* the track number: */
|
|
*(data++) = 1;
|
|
|
|
/* this track begins at block zero: */
|
|
*(data++) = 0;
|
|
*(data++) = 0;
|
|
*(data++) = 0;
|
|
*(data++) = 0;
|
|
|
|
/* fill in the TOC data length, which does not include the TOC data
|
|
length field itself: */
|
|
length = (data - (&scsi_device->tme_scsi_device_data[0] + sizeof(tme_uint16_t)));
|
|
scsi_device->tme_scsi_device_data[0] = (length >> 8);
|
|
scsi_device->tme_scsi_device_data[1] = length;
|
|
|
|
/* set the DMA pointer and length: */
|
|
space = scsi_device->tme_scsi_device_cdb[7];
|
|
space = (space << 8) + scsi_device->tme_scsi_device_cdb[8];
|
|
scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
|
|
= TME_MIN((unsigned long) (data - &scsi_device->tme_scsi_device_data[0]),
|
|
space);
|
|
scsi_device->tme_scsi_device_dma.tme_scsi_dma_out
|
|
= &scsi_device->tme_scsi_device_data[0];
|
|
scsi_device->tme_scsi_device_dma.tme_scsi_dma_in
|
|
= NULL;
|
|
|
|
/* finish the command: */
|
|
tme_scsi_device_target_do_dsmf(scsi_device,
|
|
TME_SCSI_STATUS_GOOD,
|
|
TME_SCSI_MSG_CMD_COMPLETE);
|
|
}
|
|
|
|
/* this implements the CD-ROM MODE SENSE command: */
|
|
_TME_SCSI_DEVICE_CDB_DECL(tme_scsi_cdrom_cdb_mode_sense)
|
|
{
|
|
struct tme_scsi_cdrom *scsi_cdrom;
|
|
struct tme_scsi_cdrom_connection *conn_scsi_cdrom;
|
|
tme_uint8_t *data;
|
|
tme_uint32_t block_size;
|
|
tme_uint32_t length;
|
|
int is_group0_cmd;
|
|
int lun;
|
|
|
|
/* see if this is a Group 0 MODE SELECT: */
|
|
is_group0_cmd
|
|
= ((scsi_device->tme_scsi_device_cdb[0]
|
|
& TME_SCSI_CDB_GROUP_MASK)
|
|
== TME_SCSI_CDB_GROUP_0);
|
|
|
|
/* recover our CD-ROM: */
|
|
scsi_cdrom = (struct tme_scsi_cdrom *) scsi_device;
|
|
|
|
/* get the active LUN: */
|
|
lun = scsi_device->tme_scsi_device_addressed_lun;
|
|
|
|
/* get the CD-ROM connection: */
|
|
conn_scsi_cdrom
|
|
= scsi_cdrom->tme_scsi_cdrom_connections[lun];
|
|
|
|
data = &scsi_device->tme_scsi_device_data[0];
|
|
|
|
/* the Mode Data Length is one byte for the Group 0 command and two
|
|
bytes otherwise. we will fill this in later: */
|
|
data += (is_group0_cmd ? 1 : 2);
|
|
|
|
/* the Medium Type is one byte: */
|
|
*(data++) = 0x00; /* default (only one medium type supported) */
|
|
|
|
/* the Device Specific Parameter is one byte: */
|
|
*(data++) = 0x00; /* no DPO/FUA support */
|
|
|
|
/* if this is not the Group 0 command, skip two reserved bytes: */
|
|
if (!is_group0_cmd) {
|
|
data += 2;
|
|
}
|
|
|
|
/* the Block Descriptor Length is one byte for the Group 0 command
|
|
and two bytes otherwise. we will fill this in later: */
|
|
data += (is_group0_cmd ? 1 : 2);
|
|
|
|
/* the first Block Descriptor: */
|
|
|
|
/* the Block Descriptor density code: */
|
|
*(data++) = 0x01; /* User Data only - 2048 bytes per physical sector */
|
|
|
|
/* the Number of Blocks: */
|
|
/* "A value of zero indicates that all of the remaining logical
|
|
blocks of the logical unit shall have the medium characteristics
|
|
specified." */
|
|
*(data++) = 0x00;
|
|
*(data++) = 0x00;
|
|
*(data++) = 0x00;
|
|
|
|
/* a reserved byte: */
|
|
data++;
|
|
|
|
/* the Block Length: */
|
|
block_size
|
|
= conn_scsi_cdrom->tme_scsi_disk_connection_block_size.tme_value64_uint32_lo;
|
|
*(data++) = (block_size >> 16) & 0xff;
|
|
*(data++) = (block_size >> 8) & 0xff;
|
|
*(data++) = (block_size >> 0) & 0xff;
|
|
|
|
/* fill in the Block Descriptor Length: */
|
|
if (is_group0_cmd) {
|
|
length = (data - &scsi_device->tme_scsi_device_data[4]);
|
|
scsi_device->tme_scsi_device_data[3] = length;
|
|
}
|
|
else {
|
|
length = (data - &scsi_device->tme_scsi_device_data[8]);
|
|
scsi_device->tme_scsi_device_data[6] = (length >> 8);
|
|
scsi_device->tme_scsi_device_data[7] = length;
|
|
}
|
|
|
|
/* there are no vendor-unique bytes: */
|
|
|
|
/* fill in the Mode Data Length: */
|
|
if (is_group0_cmd) {
|
|
length = (data - &scsi_device->tme_scsi_device_data[1]);
|
|
scsi_device->tme_scsi_device_data[0] = length;
|
|
}
|
|
else {
|
|
length = (data - &scsi_device->tme_scsi_device_data[2]);
|
|
scsi_device->tme_scsi_device_data[0] = (length >> 8);
|
|
scsi_device->tme_scsi_device_data[1] = length;
|
|
}
|
|
|
|
/* set the DMA pointer and length: */
|
|
if (is_group0_cmd) {
|
|
length = scsi_device->tme_scsi_device_cdb[4];
|
|
}
|
|
else {
|
|
length = scsi_device->tme_scsi_device_cdb[7];
|
|
length = (length << 8) + scsi_device->tme_scsi_device_cdb[8];
|
|
}
|
|
scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
|
|
= TME_MIN((unsigned long)
|
|
(data
|
|
- &scsi_device->tme_scsi_device_data[0]),
|
|
length);
|
|
scsi_device->tme_scsi_device_dma.tme_scsi_dma_out
|
|
= &scsi_device->tme_scsi_device_data[0];
|
|
scsi_device->tme_scsi_device_dma.tme_scsi_dma_in
|
|
= NULL;
|
|
|
|
/* finish the command: */
|
|
tme_scsi_device_target_do_dsmf(scsi_device,
|
|
TME_SCSI_STATUS_GOOD,
|
|
TME_SCSI_MSG_CMD_COMPLETE);
|
|
}
|
|
|
|
/* this handles block descriptors from a MODE SELECT command: */
|
|
static int
|
|
_tme_scsi_cdrom_do_mode_select_blocks(struct tme_scsi_device *scsi_device,
|
|
const struct tme_scsi_device_mode_blocks *blocks)
|
|
{
|
|
struct tme_scsi_cdrom *scsi_cdrom;
|
|
struct tme_scsi_cdrom_connection *conn_scsi_cdrom;
|
|
int lun;
|
|
|
|
/* recover our CD-ROM: */
|
|
scsi_cdrom = (struct tme_scsi_cdrom *) scsi_device;
|
|
|
|
/* get the active LUN: */
|
|
lun = scsi_device->tme_scsi_device_addressed_lun;
|
|
|
|
/* get the CD-ROM connection: */
|
|
conn_scsi_cdrom
|
|
= scsi_cdrom->tme_scsi_cdrom_connections[lun];
|
|
|
|
/* XXX FIXME - this needs to be implemented correctly: */
|
|
|
|
/* if this block descriptor doesn't describe the entire CD-ROM: */
|
|
if (blocks->tme_scsi_device_mode_blocks_number != 0) {
|
|
tme_scsi_device_check_condition(scsi_device,
|
|
TME_SCSI_SENSE_EXT_KEY_ILLEGAL_REQUEST,
|
|
TME_SCSI_SENSE_EXT_ASC_ASCQ_PARAMETER_VALUE_INVALID);
|
|
return (-1);
|
|
}
|
|
|
|
/* dispatch on the density code: */
|
|
switch (blocks->tme_scsi_device_mode_blocks_density_code) {
|
|
case 0x00: /* Default density code */
|
|
case 0x01: /* User Data Only, 2048 bytes per physical sector */
|
|
break;
|
|
default:
|
|
tme_scsi_device_check_condition(scsi_device,
|
|
TME_SCSI_SENSE_EXT_KEY_ILLEGAL_REQUEST,
|
|
TME_SCSI_SENSE_EXT_ASC_ASCQ_PARAMETER_VALUE_INVALID);
|
|
return (-1);
|
|
}
|
|
|
|
/* the logical block size must be an exact divisor or an integral
|
|
multiple of 2048: */
|
|
if (blocks->tme_scsi_device_mode_blocks_length == 0
|
|
|| ((blocks->tme_scsi_device_mode_blocks_length
|
|
< 2048)
|
|
? (2048 % blocks->tme_scsi_device_mode_blocks_length)
|
|
: (blocks->tme_scsi_device_mode_blocks_length % 2048))) {
|
|
tme_scsi_device_check_condition(scsi_device,
|
|
TME_SCSI_SENSE_EXT_KEY_ILLEGAL_REQUEST,
|
|
TME_SCSI_SENSE_EXT_ASC_ASCQ_PARAMETER_VALUE_INVALID);
|
|
return (-1);
|
|
}
|
|
|
|
/* update the logical block size: */
|
|
conn_scsi_cdrom->tme_scsi_disk_connection_block_size.tme_value64_uint32_lo
|
|
= blocks->tme_scsi_device_mode_blocks_length;
|
|
|
|
return (0);
|
|
}
|
|
|
|
/* this handles a mode page from a CD-ROM MODE SELECT command: */
|
|
static int
|
|
_tme_scsi_cdrom_do_mode_select_page(struct tme_scsi_device *scsi_device,
|
|
const tme_uint8_t *mode_page)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
/* this processes the parameter list from a CD-ROM MODE SELECT command: */
|
|
static
|
|
_TME_SCSI_DEVICE_PHASE_DECL(_tme_scsi_cdrom_mode_select_data)
|
|
{
|
|
tme_scsi_device_mode_select_data(scsi_device,
|
|
_tme_scsi_cdrom_do_mode_select_blocks,
|
|
_tme_scsi_cdrom_do_mode_select_page);
|
|
}
|
|
|
|
/* this implements the CD-ROM MODE SELECT command: */
|
|
_TME_SCSI_DEVICE_CDB_DECL(tme_scsi_cdrom_cdb_mode_select)
|
|
{
|
|
tme_uint32_t length;
|
|
int is_group0_cmd;
|
|
|
|
/* see if this is a Group 0 MODE SELECT: */
|
|
is_group0_cmd
|
|
= ((scsi_device->tme_scsi_device_cdb[0]
|
|
& TME_SCSI_CDB_GROUP_MASK)
|
|
== TME_SCSI_CDB_GROUP_0);
|
|
|
|
/* read in the parameter list: */
|
|
if (is_group0_cmd) {
|
|
length = scsi_device->tme_scsi_device_cdb[4];
|
|
}
|
|
else {
|
|
length = scsi_device->tme_scsi_device_cdb[7];
|
|
length = (length << 8) + scsi_device->tme_scsi_device_cdb[8];
|
|
}
|
|
scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
|
|
= TME_MIN(sizeof(scsi_device->tme_scsi_device_data),
|
|
length);
|
|
scsi_device->tme_scsi_device_dma.tme_scsi_dma_in
|
|
= &scsi_device->tme_scsi_device_data[0];
|
|
scsi_device->tme_scsi_device_dma.tme_scsi_dma_out
|
|
= NULL;
|
|
|
|
/* transfer the parameter list: */
|
|
tme_scsi_device_target_phase(scsi_device,
|
|
(TME_SCSI_SIGNAL_BSY
|
|
| TME_SCSI_PHASE_DATA_OUT));
|
|
scsi_device->tme_scsi_device_phase
|
|
= _tme_scsi_cdrom_mode_select_data;
|
|
}
|
|
|
|
/* the new SCSI CD-ROM function: */
|
|
TME_ELEMENT_SUB_NEW_DECL(tme_scsi,cdrom) {
|
|
int id;
|
|
const char *cdrom_type;
|
|
const char *vendor;
|
|
const char *product;
|
|
const char *revision;
|
|
struct tme_scsi_cdrom *scsi_cdrom;
|
|
struct tme_scsi_device *scsi_device;
|
|
int arg_i;
|
|
int usage;
|
|
unsigned int cdrom_list_i;
|
|
int (*cdrom_init) _TME_P((struct tme_scsi_cdrom *));
|
|
int rc;
|
|
|
|
/* check our arguments: */
|
|
id = -1;
|
|
cdrom_type = NULL;
|
|
vendor = NULL;
|
|
product = NULL;
|
|
revision = NULL;
|
|
arg_i = 1;
|
|
usage = FALSE;
|
|
|
|
/* loop reading our arguments: */
|
|
for (;;) {
|
|
|
|
/* the SCSI ID: */
|
|
if (TME_ARG_IS(args[arg_i], "id")
|
|
&& id < 0
|
|
&& (id = tme_scsi_id_parse(args[arg_i + 1])) >= 0) {
|
|
arg_i += 2;
|
|
}
|
|
|
|
/* the CD-ROM type: */
|
|
else if (TME_ARG_IS(args[arg_i], "type")
|
|
&& cdrom_type == NULL
|
|
&& args[arg_i + 1] != NULL) {
|
|
cdrom_type = args[arg_i + 1];
|
|
arg_i += 2;
|
|
}
|
|
|
|
/* any inquiry vendor, product, or revision: */
|
|
else if (TME_ARG_IS(args[arg_i], "vendor")
|
|
&& vendor == NULL
|
|
&& args[arg_i + 1] != NULL) {
|
|
vendor = args[arg_i + 1];
|
|
arg_i += 2;
|
|
}
|
|
else if (TME_ARG_IS(args[arg_i], "product")
|
|
&& product == NULL
|
|
&& args[arg_i + 1] != NULL) {
|
|
product = args[arg_i + 1];
|
|
arg_i += 2;
|
|
}
|
|
else if (TME_ARG_IS(args[arg_i], "revision")
|
|
&& revision == NULL
|
|
&& args[arg_i + 1] != NULL) {
|
|
revision = args[arg_i + 1];
|
|
arg_i += 2;
|
|
}
|
|
|
|
/* if we've run out of arguments: */
|
|
else if (args[arg_i + 0] == NULL) {
|
|
|
|
/* we must have been given an ID and a type: */
|
|
if (id < 0
|
|
|| cdrom_type == NULL) {
|
|
usage = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* this is a bad argument: */
|
|
else {
|
|
tme_output_append_error(_output,
|
|
"%s %s",
|
|
args[arg_i],
|
|
_("unexpected"));
|
|
usage = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (usage) {
|
|
tme_output_append_error(_output,
|
|
"%s %s id %s type %s [ vendor %s ] [ product %s ] [ revision %s ]",
|
|
_("usage:"),
|
|
args[0],
|
|
_("TYPE"),
|
|
_("ID"),
|
|
_("VENDOR"),
|
|
_("PRODUCT"),
|
|
_("REVISION"));
|
|
return (EINVAL);
|
|
}
|
|
|
|
/* make sure that this CD-ROM type is known: */
|
|
cdrom_init = NULL;
|
|
for (cdrom_list_i = 0;
|
|
cdrom_list_i < TME_ARRAY_ELS(_tme_scsi_cdrom_list);
|
|
cdrom_list_i++) {
|
|
if (!strcmp(_tme_scsi_cdrom_list[cdrom_list_i]._tme_scsi_cdrom_list_type,
|
|
cdrom_type)) {
|
|
cdrom_init = _tme_scsi_cdrom_list[cdrom_list_i]._tme_scsi_cdrom_list_init;
|
|
break;
|
|
}
|
|
}
|
|
if (cdrom_init == NULL) {
|
|
tme_output_append_error(_output, "%s", cdrom_type);
|
|
return (ENOENT);
|
|
}
|
|
|
|
/* start the CD-ROM structure: */
|
|
scsi_cdrom = tme_new0(struct tme_scsi_cdrom, 1);
|
|
scsi_cdrom->tme_scsi_cdrom_element = element;
|
|
scsi_cdrom->tme_scsi_cdrom_type = tme_strdup(cdrom_type);
|
|
|
|
/* initialize the generic SCSI device structure: */
|
|
scsi_device = &scsi_cdrom->tme_scsi_cdrom_device;
|
|
rc = tme_scsi_device_new(scsi_device, id);
|
|
assert (rc == TME_OK);
|
|
|
|
scsi_device->tme_scsi_device_vendor
|
|
= tme_strdup((vendor == NULL)
|
|
? "TME"
|
|
: vendor);
|
|
scsi_device->tme_scsi_device_product
|
|
= tme_strdup((product == NULL)
|
|
? "CDROM"
|
|
: product);
|
|
scsi_device->tme_scsi_device_revision
|
|
= tme_strdup((revision == NULL)
|
|
? "0000"
|
|
: revision);
|
|
|
|
/* set the commands for CD-ROMs: */
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_INQUIRY,
|
|
tme_scsi_cdrom_cdb_inquiry);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_READ0,
|
|
tme_scsi_cdrom_cdb_read0);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_MODE_SELECT0,
|
|
tme_scsi_cdrom_cdb_mode_select);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_MODE_SENSE0,
|
|
tme_scsi_cdrom_cdb_mode_sense);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_START_STOP,
|
|
tme_scsi_cdrom_cdb_start_stop);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_PREVENT_ALLOW,
|
|
tme_scsi_cdrom_cdb_prevent_allow);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_READ_CAPACITY,
|
|
tme_scsi_cdrom_cdb_read_capacity);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_READ1,
|
|
tme_scsi_cdrom_cdb_read1);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_READ_SUBCHANNEL,
|
|
tme_scsi_device_cdb_illegal);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_READ_TOC,
|
|
tme_scsi_cdrom_cdb_read_toc);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_PLAY_AUDIO2,
|
|
tme_scsi_device_cdb_illegal);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_READ_DISC_INFORMATION,
|
|
tme_scsi_device_cdb_illegal);
|
|
TME_SCSI_DEVICE_DO_CDB(scsi_device,
|
|
TME_SCSI_CDB_CDROM_CACHE_SYNC,
|
|
tme_scsi_device_cdb_illegal);
|
|
|
|
/* call the type-specific initialization function: */
|
|
rc = (*cdrom_init)(scsi_cdrom);
|
|
assert (rc == TME_OK);
|
|
|
|
/* fill the element: */
|
|
element->tme_element_private = scsi_cdrom;
|
|
element->tme_element_connections_new = tme_scsi_cdrom_connections_new;
|
|
|
|
return (TME_OK);
|
|
}
|