Add support for the DVD ioctl interface.
This commit is contained in:
parent
c0c9cad1af
commit
88f25c0840
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* Copyright (c) 1997, 1998, 1999 Kenneth D. Merry.
|
||||
* Copyright (c) 1997, 1998, 1999, 2000 Kenneth D. Merry.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -56,6 +56,7 @@
|
||||
#include <sys/disk.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/cdio.h>
|
||||
#include <sys/dvdio.h>
|
||||
#include <sys/devicestat.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
@ -226,6 +227,12 @@ static int cdplaytracks(struct cam_periph *periph,
|
||||
static int cdpause(struct cam_periph *periph, u_int32_t go);
|
||||
static int cdstopunit(struct cam_periph *periph, u_int32_t eject);
|
||||
static int cdstartunit(struct cam_periph *periph);
|
||||
static int cdreportkey(struct cam_periph *periph,
|
||||
struct dvd_authinfo *authinfo);
|
||||
static int cdsendkey(struct cam_periph *periph,
|
||||
struct dvd_authinfo *authinfo);
|
||||
static int cdreaddvdstructure(struct cam_periph *periph,
|
||||
struct dvd_struct *dvdstruct);
|
||||
|
||||
static struct periph_driver cddriver =
|
||||
{
|
||||
@ -2399,6 +2406,27 @@ cdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
|
||||
/* return (cd_reset(periph)); */
|
||||
error = ENOTTY;
|
||||
break;
|
||||
case DVDIOCSENDKEY:
|
||||
case DVDIOCREPORTKEY: {
|
||||
struct dvd_authinfo *authinfo;
|
||||
|
||||
authinfo = (struct dvd_authinfo *)addr;
|
||||
|
||||
if (cmd == DVDIOCREPORTKEY)
|
||||
error = cdreportkey(periph, authinfo);
|
||||
else
|
||||
error = cdsendkey(periph, authinfo);
|
||||
break;
|
||||
}
|
||||
case DVDIOCREADSTRUCTURE: {
|
||||
struct dvd_struct *dvdstruct;
|
||||
|
||||
dvdstruct = (struct dvd_struct *)addr;
|
||||
|
||||
error = cdreaddvdstructure(periph, dvdstruct);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error = cam_periph_ioctl(periph, cmd, addr, cderror);
|
||||
break;
|
||||
@ -2941,3 +2969,560 @@ cdstopunit(struct cam_periph *periph, u_int32_t eject)
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
static int
|
||||
cdreportkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
|
||||
{
|
||||
union ccb *ccb;
|
||||
u_int8_t *databuf;
|
||||
u_int32_t lba;
|
||||
int error;
|
||||
int length;
|
||||
|
||||
error = 0;
|
||||
databuf = NULL;
|
||||
lba = 0;
|
||||
|
||||
ccb = cdgetccb(periph, /* priority */ 1);
|
||||
|
||||
switch (authinfo->format) {
|
||||
case DVD_REPORT_AGID:
|
||||
length = sizeof(struct scsi_report_key_data_agid);
|
||||
break;
|
||||
case DVD_REPORT_CHALLENGE:
|
||||
length = sizeof(struct scsi_report_key_data_challenge);
|
||||
break;
|
||||
case DVD_REPORT_KEY1:
|
||||
length = sizeof(struct scsi_report_key_data_key1_key2);
|
||||
break;
|
||||
case DVD_REPORT_TITLE_KEY:
|
||||
length = sizeof(struct scsi_report_key_data_title);
|
||||
/* The lba field is only set for the title key */
|
||||
lba = authinfo->lba;
|
||||
break;
|
||||
case DVD_REPORT_ASF:
|
||||
length = sizeof(struct scsi_report_key_data_asf);
|
||||
break;
|
||||
case DVD_REPORT_RPC:
|
||||
length = sizeof(struct scsi_report_key_data_rpc);
|
||||
break;
|
||||
case DVD_INVALIDATE_AGID:
|
||||
length = 0;
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
goto bailout;
|
||||
break; /* NOTREACHED */
|
||||
}
|
||||
|
||||
if (length != 0) {
|
||||
databuf = malloc(length, M_DEVBUF, M_WAITOK);
|
||||
bzero(databuf, length);
|
||||
} else
|
||||
databuf = NULL;
|
||||
|
||||
|
||||
scsi_report_key(&ccb->csio,
|
||||
/* retries */ 1,
|
||||
/* cbfcnp */ cddone,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
/* lba */ lba,
|
||||
/* agid */ authinfo->agid,
|
||||
/* key_format */ authinfo->format,
|
||||
/* data_ptr */ databuf,
|
||||
/* dxfer_len */ length,
|
||||
/* sense_len */ SSD_FULL_SIZE,
|
||||
/* timeout */ 50000);
|
||||
|
||||
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
|
||||
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
|
||||
|
||||
if (error != 0)
|
||||
goto bailout;
|
||||
|
||||
if (ccb->csio.resid != 0) {
|
||||
xpt_print_path(periph->path);
|
||||
printf("warning, residual for report key command is %d\n",
|
||||
ccb->csio.resid);
|
||||
}
|
||||
|
||||
switch(authinfo->format) {
|
||||
case DVD_REPORT_AGID: {
|
||||
struct scsi_report_key_data_agid *agid_data;
|
||||
|
||||
agid_data = (struct scsi_report_key_data_agid *)databuf;
|
||||
|
||||
authinfo->agid = (agid_data->agid & RKD_AGID_MASK) >>
|
||||
RKD_AGID_SHIFT;
|
||||
break;
|
||||
}
|
||||
case DVD_REPORT_CHALLENGE: {
|
||||
struct scsi_report_key_data_challenge *chal_data;
|
||||
|
||||
chal_data = (struct scsi_report_key_data_challenge *)databuf;
|
||||
|
||||
bcopy(chal_data->challenge_key, authinfo->keychal,
|
||||
min(sizeof(chal_data->challenge_key),
|
||||
sizeof(authinfo->keychal)));
|
||||
break;
|
||||
}
|
||||
case DVD_REPORT_KEY1: {
|
||||
struct scsi_report_key_data_key1_key2 *key1_data;
|
||||
|
||||
key1_data = (struct scsi_report_key_data_key1_key2 *)databuf;
|
||||
|
||||
bcopy(key1_data->key1, authinfo->keychal,
|
||||
min(sizeof(key1_data->key1), sizeof(authinfo->keychal)));
|
||||
break;
|
||||
}
|
||||
case DVD_REPORT_TITLE_KEY: {
|
||||
struct scsi_report_key_data_title *title_data;
|
||||
|
||||
title_data = (struct scsi_report_key_data_title *)databuf;
|
||||
|
||||
authinfo->cpm = (title_data->byte0 & RKD_TITLE_CPM) >>
|
||||
RKD_TITLE_CPM_SHIFT;
|
||||
authinfo->cp_sec = (title_data->byte0 & RKD_TITLE_CP_SEC) >>
|
||||
RKD_TITLE_CP_SEC_SHIFT;
|
||||
authinfo->cgms = (title_data->byte0 & RKD_TITLE_CMGS_MASK) >>
|
||||
RKD_TITLE_CMGS_SHIFT;
|
||||
bcopy(title_data->title_key, authinfo->keychal,
|
||||
min(sizeof(title_data->title_key),
|
||||
sizeof(authinfo->keychal)));
|
||||
break;
|
||||
}
|
||||
case DVD_REPORT_ASF: {
|
||||
struct scsi_report_key_data_asf *asf_data;
|
||||
|
||||
asf_data = (struct scsi_report_key_data_asf *)databuf;
|
||||
|
||||
authinfo->asf = asf_data->success & RKD_ASF_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case DVD_REPORT_RPC: {
|
||||
struct scsi_report_key_data_rpc *rpc_data;
|
||||
|
||||
rpc_data = (struct scsi_report_key_data_rpc *)databuf;
|
||||
|
||||
authinfo->reg_type = (rpc_data->byte4 & RKD_RPC_TYPE_MASK) >>
|
||||
RKD_RPC_TYPE_SHIFT;
|
||||
authinfo->vend_rsts =
|
||||
(rpc_data->byte4 & RKD_RPC_VENDOR_RESET_MASK) >>
|
||||
RKD_RPC_VENDOR_RESET_SHIFT;
|
||||
authinfo->user_rsts = rpc_data->byte4 & RKD_RPC_USER_RESET_MASK;
|
||||
break;
|
||||
}
|
||||
case DVD_INVALIDATE_AGID:
|
||||
break;
|
||||
default:
|
||||
/* This should be impossible, since we checked above */
|
||||
error = EINVAL;
|
||||
goto bailout;
|
||||
break; /* NOTREACHED */
|
||||
}
|
||||
bailout:
|
||||
if (databuf != NULL)
|
||||
free(databuf, M_DEVBUF);
|
||||
|
||||
xpt_release_ccb(ccb);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
static int
|
||||
cdsendkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
|
||||
{
|
||||
union ccb *ccb;
|
||||
u_int8_t *databuf;
|
||||
int length;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
databuf = NULL;
|
||||
|
||||
ccb = cdgetccb(periph, /* priority */ 1);
|
||||
|
||||
switch(authinfo->format) {
|
||||
case DVD_SEND_CHALLENGE: {
|
||||
struct scsi_report_key_data_challenge *challenge_data;
|
||||
|
||||
length = sizeof(*challenge_data);
|
||||
|
||||
challenge_data = malloc(length, M_DEVBUF, M_WAITOK);
|
||||
|
||||
databuf = (u_int8_t *)challenge_data;
|
||||
|
||||
bzero(databuf, length);
|
||||
|
||||
scsi_ulto2b(length - sizeof(challenge_data->data_len),
|
||||
challenge_data->data_len);
|
||||
|
||||
bcopy(authinfo->keychal, challenge_data->challenge_key,
|
||||
min(sizeof(authinfo->keychal),
|
||||
sizeof(challenge_data->challenge_key)));
|
||||
break;
|
||||
}
|
||||
case DVD_SEND_KEY2: {
|
||||
struct scsi_report_key_data_key1_key2 *key2_data;
|
||||
|
||||
length = sizeof(*key2_data);
|
||||
|
||||
key2_data = malloc(length, M_DEVBUF, M_WAITOK);
|
||||
|
||||
databuf = (u_int8_t *)key2_data;
|
||||
|
||||
bzero(databuf, length);
|
||||
|
||||
scsi_ulto2b(length - sizeof(key2_data->data_len),
|
||||
key2_data->data_len);
|
||||
|
||||
bcopy(authinfo->keychal, key2_data->key1,
|
||||
min(sizeof(authinfo->keychal), sizeof(key2_data->key1)));
|
||||
|
||||
break;
|
||||
}
|
||||
case DVD_SEND_RPC: {
|
||||
struct scsi_send_key_data_rpc *rpc_data;
|
||||
|
||||
length = sizeof(*rpc_data);
|
||||
|
||||
rpc_data = malloc(length, M_DEVBUF, M_WAITOK);
|
||||
|
||||
databuf = (u_int8_t *)rpc_data;
|
||||
|
||||
bzero(databuf, length);
|
||||
|
||||
scsi_ulto2b(length - sizeof(rpc_data->data_len),
|
||||
rpc_data->data_len);
|
||||
|
||||
/*
|
||||
* XXX KDM is this the right field from authinfo to use?
|
||||
*/
|
||||
rpc_data->region_code = authinfo->region;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error = EINVAL;
|
||||
goto bailout;
|
||||
break; /* NOTREACHED */
|
||||
}
|
||||
|
||||
scsi_send_key(&ccb->csio,
|
||||
/* retries */ 1,
|
||||
/* cbfcnp */ cddone,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
/* agid */ authinfo->agid,
|
||||
/* key_format */ authinfo->format,
|
||||
/* data_ptr */ databuf,
|
||||
/* dxfer_len */ length,
|
||||
/* sense_len */ SSD_FULL_SIZE,
|
||||
/* timeout */ 50000);
|
||||
|
||||
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
|
||||
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
|
||||
|
||||
bailout:
|
||||
|
||||
if (databuf != NULL)
|
||||
free(databuf, M_DEVBUF);
|
||||
|
||||
xpt_release_ccb(ccb);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
static int
|
||||
cdreaddvdstructure(struct cam_periph *periph, struct dvd_struct *dvdstruct)
|
||||
{
|
||||
union ccb *ccb;
|
||||
u_int8_t *databuf;
|
||||
u_int32_t address;
|
||||
int error;
|
||||
int length;
|
||||
|
||||
error = 0;
|
||||
databuf = NULL;
|
||||
/* The address is reserved for many of the formats */
|
||||
address = 0;
|
||||
|
||||
ccb = cdgetccb(periph, /* priority */ 1);
|
||||
|
||||
switch(dvdstruct->format) {
|
||||
case DVD_STRUCT_PHYSICAL:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_physical);
|
||||
break;
|
||||
case DVD_STRUCT_COPYRIGHT:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_copyright);
|
||||
break;
|
||||
case DVD_STRUCT_DISCKEY:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_disc_key);
|
||||
break;
|
||||
case DVD_STRUCT_BCA:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_bca);
|
||||
break;
|
||||
case DVD_STRUCT_MANUFACT:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_manufacturer);
|
||||
break;
|
||||
case DVD_STRUCT_CMI:
|
||||
error = ENODEV;
|
||||
goto bailout;
|
||||
#ifdef notyet
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_copy_manage);
|
||||
address = dvdstruct->address;
|
||||
#endif
|
||||
break; /* NOTREACHED */
|
||||
case DVD_STRUCT_PROTDISCID:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_prot_discid);
|
||||
break;
|
||||
case DVD_STRUCT_DISCKEYBLOCK:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_disc_key_blk);
|
||||
break;
|
||||
case DVD_STRUCT_DDS:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_dds);
|
||||
break;
|
||||
case DVD_STRUCT_MEDIUM_STAT:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_medium_status);
|
||||
break;
|
||||
case DVD_STRUCT_SPARE_AREA:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_spare_area);
|
||||
break;
|
||||
case DVD_STRUCT_RMD_LAST:
|
||||
error = ENODEV;
|
||||
goto bailout;
|
||||
#ifdef notyet
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_rmd_borderout);
|
||||
address = dvdstruct->address;
|
||||
#endif
|
||||
break; /* NOTREACHED */
|
||||
case DVD_STRUCT_RMD_RMA:
|
||||
error = ENODEV;
|
||||
goto bailout;
|
||||
#ifdef notyet
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_rmd);
|
||||
address = dvdstruct->address;
|
||||
#endif
|
||||
break; /* NOTREACHED */
|
||||
case DVD_STRUCT_PRERECORDED:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_leadin);
|
||||
break;
|
||||
case DVD_STRUCT_UNIQUEID:
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_disc_id);
|
||||
break;
|
||||
case DVD_STRUCT_DCB:
|
||||
error = ENODEV;
|
||||
goto bailout;
|
||||
#ifdef notyet
|
||||
length = sizeof(struct scsi_read_dvd_struct_data_dcb);
|
||||
address = dvdstruct->address;
|
||||
#endif
|
||||
break; /* NOTREACHED */
|
||||
case DVD_STRUCT_LIST:
|
||||
/*
|
||||
* This is the maximum allocation length for the READ DVD
|
||||
* STRUCTURE command. There's nothing in the MMC3 spec
|
||||
* that indicates a limit in the amount of data that can
|
||||
* be returned from this call, other than the limits
|
||||
* imposed by the 2-byte length variables.
|
||||
*/
|
||||
length = 65535;
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
goto bailout;
|
||||
break; /* NOTREACHED */
|
||||
}
|
||||
|
||||
if (length != 0) {
|
||||
databuf = malloc(length, M_DEVBUF, M_WAITOK);
|
||||
bzero(databuf, length);
|
||||
} else
|
||||
databuf = NULL;
|
||||
|
||||
scsi_read_dvd_structure(&ccb->csio,
|
||||
/* retries */ 1,
|
||||
/* cbfcnp */ cddone,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
/* lba */ address,
|
||||
/* layer_number */ dvdstruct->layer_num,
|
||||
/* key_format */ dvdstruct->format,
|
||||
/* agid */ dvdstruct->agid,
|
||||
/* data_ptr */ databuf,
|
||||
/* dxfer_len */ length,
|
||||
/* sense_len */ SSD_FULL_SIZE,
|
||||
/* timeout */ 50000);
|
||||
|
||||
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
|
||||
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
|
||||
|
||||
if (error != 0)
|
||||
goto bailout;
|
||||
|
||||
switch(dvdstruct->format) {
|
||||
case DVD_STRUCT_PHYSICAL: {
|
||||
struct scsi_read_dvd_struct_data_layer_desc *inlayer;
|
||||
struct dvd_layer *outlayer;
|
||||
struct scsi_read_dvd_struct_data_physical *phys_data;
|
||||
|
||||
phys_data =
|
||||
(struct scsi_read_dvd_struct_data_physical *)databuf;
|
||||
inlayer = &phys_data->layer_desc;
|
||||
outlayer = (struct dvd_layer *)&dvdstruct->data;
|
||||
|
||||
dvdstruct->length = sizeof(*inlayer);
|
||||
|
||||
outlayer->book_type = (inlayer->book_type_version &
|
||||
RDSD_BOOK_TYPE_MASK) >> RDSD_BOOK_TYPE_SHIFT;
|
||||
outlayer->book_version = (inlayer->book_type_version &
|
||||
RDSD_BOOK_VERSION_MASK);
|
||||
outlayer->disc_size = (inlayer->disc_size_max_rate &
|
||||
RDSD_DISC_SIZE_MASK) >> RDSD_DISC_SIZE_SHIFT;
|
||||
outlayer->max_rate = (inlayer->disc_size_max_rate &
|
||||
RDSD_MAX_RATE_MASK);
|
||||
outlayer->nlayers = (inlayer->layer_info &
|
||||
RDSD_NUM_LAYERS_MASK) >> RDSD_NUM_LAYERS_SHIFT;
|
||||
outlayer->track_path = (inlayer->layer_info &
|
||||
RDSD_TRACK_PATH_MASK) >> RDSD_TRACK_PATH_SHIFT;
|
||||
outlayer->layer_type = (inlayer->layer_info &
|
||||
RDSD_LAYER_TYPE_MASK);
|
||||
outlayer->linear_density = (inlayer->density &
|
||||
RDSD_LIN_DENSITY_MASK) >> RDSD_LIN_DENSITY_SHIFT;
|
||||
outlayer->track_density = (inlayer->density &
|
||||
RDSD_TRACK_DENSITY_MASK);
|
||||
outlayer->bca = (inlayer->bca & RDSD_BCA_MASK) >>
|
||||
RDSD_BCA_SHIFT;
|
||||
outlayer->start_sector = scsi_3btoul(inlayer->main_data_start);
|
||||
outlayer->end_sector = scsi_3btoul(inlayer->main_data_end);
|
||||
outlayer->end_sector_l0 =
|
||||
scsi_3btoul(inlayer->end_sector_layer0);
|
||||
break;
|
||||
}
|
||||
case DVD_STRUCT_COPYRIGHT: {
|
||||
struct scsi_read_dvd_struct_data_copyright *copy_data;
|
||||
|
||||
copy_data = (struct scsi_read_dvd_struct_data_copyright *)
|
||||
databuf;
|
||||
|
||||
dvdstruct->cpst = copy_data->cps_type;
|
||||
dvdstruct->rmi = copy_data->region_info;
|
||||
dvdstruct->length = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/*
|
||||
* Tell the user what the overall length is, no matter
|
||||
* what we can actually fit in the data buffer.
|
||||
*/
|
||||
dvdstruct->length = length - ccb->csio.resid -
|
||||
sizeof(struct scsi_read_dvd_struct_data_header);
|
||||
|
||||
/*
|
||||
* But only actually copy out the smaller of what we read
|
||||
* in or what the structure can take.
|
||||
*/
|
||||
bcopy(databuf + sizeof(struct scsi_read_dvd_struct_data_header),
|
||||
dvdstruct->data,
|
||||
min(sizeof(dvdstruct->data), dvdstruct->length));
|
||||
break;
|
||||
}
|
||||
bailout:
|
||||
|
||||
if (databuf != NULL)
|
||||
free(databuf, M_DEVBUF);
|
||||
|
||||
xpt_release_ccb(ccb);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_report_key(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, u_int32_t lba, u_int8_t agid,
|
||||
u_int8_t key_format, u_int8_t *data_ptr, u_int32_t dxfer_len,
|
||||
u_int8_t sense_len, u_int32_t timeout)
|
||||
{
|
||||
struct scsi_report_key *scsi_cmd;
|
||||
|
||||
scsi_cmd = (struct scsi_report_key *)&csio->cdb_io.cdb_bytes;
|
||||
bzero(scsi_cmd, sizeof(*scsi_cmd));
|
||||
scsi_cmd->opcode = REPORT_KEY;
|
||||
scsi_ulto4b(lba, scsi_cmd->lba);
|
||||
scsi_ulto2b(dxfer_len, scsi_cmd->alloc_len);
|
||||
scsi_cmd->agid_keyformat = (agid << RK_KF_AGID_SHIFT) |
|
||||
(key_format & RK_KF_KEYFORMAT_MASK);
|
||||
|
||||
cam_fill_csio(csio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/ (dxfer_len == 0) ? CAM_DIR_NONE : CAM_DIR_IN,
|
||||
tag_action,
|
||||
/*data_ptr*/ data_ptr,
|
||||
/*dxfer_len*/ dxfer_len,
|
||||
sense_len,
|
||||
sizeof(*scsi_cmd),
|
||||
timeout);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_send_key(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, u_int8_t agid, u_int8_t key_format,
|
||||
u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
|
||||
u_int32_t timeout)
|
||||
{
|
||||
struct scsi_send_key *scsi_cmd;
|
||||
|
||||
scsi_cmd = (struct scsi_send_key *)&csio->cdb_io.cdb_bytes;
|
||||
bzero(scsi_cmd, sizeof(*scsi_cmd));
|
||||
scsi_cmd->opcode = SEND_KEY;
|
||||
|
||||
scsi_ulto2b(dxfer_len, scsi_cmd->param_len);
|
||||
scsi_cmd->agid_keyformat = (agid << RK_KF_AGID_SHIFT) |
|
||||
(key_format & RK_KF_KEYFORMAT_MASK);
|
||||
|
||||
cam_fill_csio(csio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/ CAM_DIR_OUT,
|
||||
tag_action,
|
||||
/*data_ptr*/ data_ptr,
|
||||
/*dxfer_len*/ dxfer_len,
|
||||
sense_len,
|
||||
sizeof(*scsi_cmd),
|
||||
timeout);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scsi_read_dvd_structure(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, u_int32_t address,
|
||||
u_int8_t layer_number, u_int8_t format, u_int8_t agid,
|
||||
u_int8_t *data_ptr, u_int32_t dxfer_len,
|
||||
u_int8_t sense_len, u_int32_t timeout)
|
||||
{
|
||||
struct scsi_read_dvd_structure *scsi_cmd;
|
||||
|
||||
scsi_cmd = (struct scsi_read_dvd_structure *)&csio->cdb_io.cdb_bytes;
|
||||
bzero(scsi_cmd, sizeof(*scsi_cmd));
|
||||
scsi_cmd->opcode = READ_DVD_STRUCTURE;
|
||||
|
||||
scsi_ulto4b(address, scsi_cmd->address);
|
||||
scsi_cmd->layer_number = layer_number;
|
||||
scsi_cmd->format = format;
|
||||
scsi_ulto2b(dxfer_len, scsi_cmd->alloc_len);
|
||||
/* The AGID is the top two bits of this byte */
|
||||
scsi_cmd->agid = agid << 6;
|
||||
|
||||
cam_fill_csio(csio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/ CAM_DIR_IN,
|
||||
tag_action,
|
||||
/*data_ptr*/ data_ptr,
|
||||
/*dxfer_len*/ dxfer_len,
|
||||
sense_len,
|
||||
sizeof(*scsi_cmd),
|
||||
timeout);
|
||||
}
|
||||
|
@ -1,3 +1,29 @@
|
||||
/*-
|
||||
* Copyright (c) 2000 Kenneth D. Merry
|
||||
* 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,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Written by Julian Elischer (julian@tfs.com)
|
||||
* for TRW Financial Systems.
|
||||
@ -144,6 +170,71 @@ struct scsi_read_cd_capacity
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
struct scsi_report_key
|
||||
{
|
||||
u_int8_t opcode;
|
||||
u_int8_t reserved0;
|
||||
u_int8_t lba[4];
|
||||
u_int8_t reserved1[2];
|
||||
u_int8_t alloc_len[2];
|
||||
u_int8_t agid_keyformat;
|
||||
#define RK_KF_AGID_MASK 0xc0
|
||||
#define RK_KF_AGID_SHIFT 6
|
||||
#define RK_KF_KEYFORMAT_MASK 0x3f
|
||||
#define RK_KF_AGID 0x00
|
||||
#define RK_KF_CHALLENGE 0x01
|
||||
#define RF_KF_KEY1 0x02
|
||||
#define RK_KF_KEY2 0x03
|
||||
#define RF_KF_TITLE 0x04
|
||||
#define RF_KF_ASF 0x05
|
||||
#define RK_KF_RPC_SET 0x06
|
||||
#define RF_KF_RPC_REPORT 0x08
|
||||
#define RF_KF_INV_AGID 0x3f
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
/*
|
||||
* See the report key structure for key format and AGID definitions.
|
||||
*/
|
||||
struct scsi_send_key
|
||||
{
|
||||
u_int8_t opcode;
|
||||
u_int8_t reserved[7];
|
||||
u_int8_t param_len[2];
|
||||
u_int8_t agid_keyformat;
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_structure
|
||||
{
|
||||
u_int8_t opcode;
|
||||
u_int8_t reserved;
|
||||
u_int8_t address[4];
|
||||
u_int8_t layer_number;
|
||||
u_int8_t format;
|
||||
#define RDS_FORMAT_PHYSICAL 0x00
|
||||
#define RDS_FORMAT_COPYRIGHT 0x01
|
||||
#define RDS_FORMAT_DISC_KEY 0x02
|
||||
#define RDS_FORMAT_BCA 0x03
|
||||
#define RDS_FORMAT_MANUFACTURER 0x04
|
||||
#define RDS_FORMAT_CMGS_CPM 0x05
|
||||
#define RDS_FORMAT_PROT_DISCID 0x06
|
||||
#define RDS_FORMAT_DISC_KEY_BLOCK 0x07
|
||||
#define RDS_FORMAT_DDS 0x08
|
||||
#define RDS_FORMAT_DVDRAM_MEDIA_STAT 0x09
|
||||
#define RDS_FORMAT_SPARE_AREA 0x0a
|
||||
#define RDS_FORMAT_RMD_BORDEROUT 0x0c
|
||||
#define RDS_FORMAT_RMD 0x0d
|
||||
#define RDS_FORMAT_LEADIN 0x0e
|
||||
#define RDS_FORMAT_DISC_ID 0x0f
|
||||
#define RDS_FORMAT_DCB 0x30
|
||||
#define RDS_FORMAT_WRITE_PROT 0xc0
|
||||
#define RDS_FORMAT_STRUCTURE_LIST 0xff
|
||||
u_int8_t alloc_len[2];
|
||||
u_int8_t agid;
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
/*
|
||||
* Opcodes
|
||||
*/
|
||||
@ -156,10 +247,391 @@ struct scsi_read_cd_capacity
|
||||
#define PLAY_TRACK 0x48 /* cdrom play track/index mode */
|
||||
#define PLAY_TRACK_REL 0x49 /* cdrom play track/index mode */
|
||||
#define PAUSE 0x4b /* cdrom pause in 'play audio' mode */
|
||||
#define SEND_KEY 0xa3 /* dvd send key command */
|
||||
#define REPORT_KEY 0xa4 /* dvd report key command */
|
||||
#define PLAY_12 0xa5 /* cdrom pause in 'play audio' mode */
|
||||
#define PLAY_TRACK_REL_BIG 0xa9 /* cdrom play track/index mode */
|
||||
#define READ_DVD_STRUCTURE 0xad /* read dvd structure */
|
||||
|
||||
struct scsi_report_key_data_header
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
};
|
||||
|
||||
struct scsi_report_key_data_agid
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[5];
|
||||
u_int8_t agid;
|
||||
#define RKD_AGID_MASK 0xc0
|
||||
#define RKD_AGID_SHIFT 6
|
||||
};
|
||||
|
||||
struct scsi_report_key_data_challenge
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved0[2];
|
||||
u_int8_t challenge_key[10];
|
||||
u_int8_t reserved1[2];
|
||||
};
|
||||
|
||||
struct scsi_report_key_data_key1_key2
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved0[2];
|
||||
u_int8_t key1[5];
|
||||
u_int8_t reserved1[3];
|
||||
};
|
||||
|
||||
struct scsi_report_key_data_title
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved0[2];
|
||||
u_int8_t byte0;
|
||||
#define RKD_TITLE_CPM 0x80
|
||||
#define RKD_TITLE_CPM_SHIFT 7
|
||||
#define RKD_TITLE_CP_SEC 0x40
|
||||
#define RKD_TITLE_CP_SEC_SHIFT 6
|
||||
#define RKD_TITLE_CMGS_MASK 0x30
|
||||
#define RKD_TITLE_CMGS_SHIFT 4
|
||||
#define RKD_TITLE_CMGS_NO_RST 0x00
|
||||
#define RKD_TITLE_CMGS_RSVD 0x10
|
||||
#define RKD_TITLE_CMGS_1_GEN 0x20
|
||||
#define RKD_TITLE_CMGS_NO_COPY 0x30
|
||||
u_int8_t title_key[5];
|
||||
u_int8_t reserved1[2];
|
||||
};
|
||||
|
||||
struct scsi_report_key_data_asf
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[5];
|
||||
u_int8_t success;
|
||||
#define RKD_ASF_SUCCESS 0x01
|
||||
};
|
||||
|
||||
struct scsi_report_key_data_rpc
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t rpc_scheme0;
|
||||
#define RKD_RPC_SCHEME_UNKNOWN 0x00
|
||||
#define RKD_RPC_SCHEME_PHASE_II 0x01
|
||||
u_int8_t reserved0;
|
||||
u_int8_t byte4;
|
||||
#define RKD_RPC_TYPE_MASK 0xC0
|
||||
#define RKD_RPC_TYPE_SHIFT 6
|
||||
#define RKD_RPC_TYPE_NONE 0x00
|
||||
#define RKD_RPC_TYPE_SET 0x40
|
||||
#define RKD_RPC_TYPE_LAST_CHANCE 0x80
|
||||
#define RKD_RPC_TYPE_PERM 0xC0
|
||||
#define RKD_RPC_VENDOR_RESET_MASK 0x38
|
||||
#define RKD_RPC_VENDOR_RESET_SHIFT 3
|
||||
#define RKD_RPC_USER_RESET_MASK 0x07
|
||||
#define RKD_RPC_USER_RESET_SHIFT 0
|
||||
u_int8_t region_mask;
|
||||
u_int8_t rpc_scheme1;
|
||||
u_int8_t reserved1;
|
||||
};
|
||||
|
||||
struct scsi_send_key_data_rpc
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved0[2];
|
||||
u_int8_t region_code;
|
||||
u_int8_t reserved1[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* Common header for the return data from the READ DVD STRUCTURE command.
|
||||
*/
|
||||
struct scsi_read_dvd_struct_data_header
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_layer_desc
|
||||
{
|
||||
u_int8_t book_type_version;
|
||||
#define RDSD_BOOK_TYPE_DVD_ROM 0x00
|
||||
#define RDSD_BOOK_TYPE_DVD_RAM 0x10
|
||||
#define RDSD_BOOK_TYPE_DVD_R 0x20
|
||||
#define RDSD_BOOK_TYPE_DVD_RW 0x30
|
||||
#define RDSD_BOOK_TYPE_DVD_PRW 0x90
|
||||
#define RDSD_BOOK_TYPE_MASK 0xf0
|
||||
#define RDSD_BOOK_TYPE_SHIFT 4
|
||||
#define RDSD_BOOK_VERSION_MASK 0x0f
|
||||
/*
|
||||
* The lower 4 bits of this field is referred to as the "minimum
|
||||
* rate" field in MMC2, and the "maximum rate" field in MMC3. Ugh.
|
||||
*/
|
||||
u_int8_t disc_size_max_rate;
|
||||
#define RDSD_DISC_SIZE_120MM 0x00
|
||||
#define RDSD_DISC_SIZE_80MM 0x10
|
||||
#define RDSD_DISC_SIZE_MASK 0xf0
|
||||
#define RDSD_DISC_SIZE_SHIFT 4
|
||||
#define RDSD_MAX_RATE_0252 0x00
|
||||
#define RDSD_MAX_RATE_0504 0x01
|
||||
#define RDSD_MAX_RATE_1008 0x02
|
||||
#define RDSD_MAX_RATE_NOT_SPEC 0x0f
|
||||
#define RDSD_MAX_RATE_MASK 0x0f
|
||||
u_int8_t layer_info;
|
||||
#define RDSD_NUM_LAYERS_MASK 0x60
|
||||
#define RDSD_NUM_LAYERS_SHIFT 5
|
||||
#define RDSD_NL_ONE_LAYER 0x00
|
||||
#define RDSD_NL_TWO_LAYERS 0x20
|
||||
#define RDSD_TRACK_PATH_MASK 0x10
|
||||
#define RDSD_TRACK_PATH_SHIFT 4
|
||||
#define RDSD_TP_PTP 0x00
|
||||
#define RDSD_TP_OTP 0x10
|
||||
#define RDSD_LAYER_TYPE_RO 0x01
|
||||
#define RDSD_LAYER_TYPE_RECORD 0x02
|
||||
#define RDSD_LAYER_TYPE_RW 0x04
|
||||
#define RDSD_LAYER_TYPE_MASK 0x0f
|
||||
u_int8_t density;
|
||||
#define RDSD_LIN_DENSITY_0267 0x00
|
||||
#define RDSD_LIN_DENSITY_0293 0x10
|
||||
#define RDSD_LIN_DENSITY_0409_0435 0x20
|
||||
#define RDSD_LIN_DENSITY_0280_0291 0x40
|
||||
/* XXX MMC2 uses 0.176um/bit instead of 0.353 as in MMC3 */
|
||||
#define RDSD_LIN_DENSITY_0353 0x80
|
||||
#define RDSD_LIN_DENSITY_MASK 0xf0
|
||||
#define RDSD_LIN_DENSITY_SHIFT 4
|
||||
#define RDSD_TRACK_DENSITY_074 0x00
|
||||
#define RDSD_TRACK_DENSITY_080 0x01
|
||||
#define RDSD_TRACK_DENSITY_0615 0x02
|
||||
#define RDSD_TRACK_DENSITY_MASK 0x0f
|
||||
u_int8_t zeros0;
|
||||
u_int8_t main_data_start[3];
|
||||
#define RDSD_MAIN_DATA_START_DVD_RO 0x30000
|
||||
#define RDSD_MAIN_DATA_START_DVD_RW 0x31000
|
||||
u_int8_t zeros1;
|
||||
u_int8_t main_data_end[3];
|
||||
u_int8_t zeros2;
|
||||
u_int8_t end_sector_layer0[3];
|
||||
u_int8_t bca;
|
||||
#define RDSD_BCA 0x80
|
||||
#define RDSD_BCA_MASK 0x80
|
||||
#define RDSD_BCA_SHIFT 7
|
||||
u_int8_t media_specific[2031];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_physical
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
struct scsi_read_dvd_struct_data_layer_desc layer_desc;
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_copyright
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved0[2];
|
||||
u_int8_t cps_type;
|
||||
#define RDSD_CPS_NOT_PRESENT 0x00
|
||||
#define RDSD_CPS_DATA_EXISTS 0x01
|
||||
u_int8_t region_info;
|
||||
u_int8_t reserved1[2];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_disc_key
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t disc_key[2048];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_bca
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t bca_info[188]; /* XXX 12-188 bytes */
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_manufacturer
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t manuf_info[2048];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_copy_manage
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved0[2];
|
||||
u_int8_t byte4;
|
||||
#define RDSD_CPM_NO_COPYRIGHT 0x00
|
||||
#define RDSD_CPM_HAS_COPYRIGHT 0x80
|
||||
#define RDSD_CPM_MASK 0x80
|
||||
#define RDSD_CMGS_COPY_ALLOWED 0x00
|
||||
#define RDSD_CMGS_ONE_COPY 0x20
|
||||
#define RDSD_CMGS_NO_COPIES 0x30
|
||||
#define RDSD_CMGS_MASK 0x30
|
||||
u_int8_t reserved1[3];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_prot_discid
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t prot_discid_data[16];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_disc_key_blk
|
||||
{
|
||||
/*
|
||||
* Length is 0x6ffe == 28670 for CPRM, 0x3002 == 12990 for CSS2.
|
||||
*/
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved;
|
||||
u_int8_t total_packs;
|
||||
u_int8_t disc_key_pack_data[28668];
|
||||
};
|
||||
struct scsi_read_dvd_struct_data_dds
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t dds_info[2048];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_medium_status
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved0[2];
|
||||
u_int8_t byte4;
|
||||
#define RDSD_MS_CARTRIDGE 0x80
|
||||
#define RDSD_MS_OUT 0x40
|
||||
#define RDSD_MS_MSWI 0x08
|
||||
#define RDSD_MS_CWP 0x04
|
||||
#define RDSD_MS_PWP 0x02
|
||||
u_int8_t disc_type_id;
|
||||
#define RDSD_DT_NEED_CARTRIDGE 0x00
|
||||
#define RDSD_DT_NO_CART_NEEDED 0x01
|
||||
u_int8_t reserved1;
|
||||
u_int8_t ram_swi_info;
|
||||
#define RDSD_SWI_NO_BARE 0x01
|
||||
#define RDSD_SWI_UNSPEC 0xff
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_spare_area
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t unused_primary[4];
|
||||
u_int8_t unused_supl[4];
|
||||
u_int8_t allocated_supl[4];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_rmd_borderout
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t rmd[30720]; /* maximum is 30720 bytes */
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_rmd
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t last_sector_num[4];
|
||||
u_int8_t rmd_bytes[32768]; /* This is the maximum */
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX KDM this is the MMC2 version of the structure.
|
||||
* The variable positions have changed (in a semi-conflicting way) in the
|
||||
* MMC3 spec, although the overall length of the structure is the same.
|
||||
*/
|
||||
struct scsi_read_dvd_struct_data_leadin
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved0[2];
|
||||
u_int8_t field_id_1;
|
||||
u_int8_t app_code;
|
||||
u_int8_t disc_physical_data;
|
||||
u_int8_t last_addr[3];
|
||||
u_int8_t reserved1[2];
|
||||
u_int8_t field_id_2;
|
||||
u_int8_t rwp;
|
||||
u_int8_t rwp_wavelength;
|
||||
u_int8_t optimum_write_strategy;
|
||||
u_int8_t reserved2[4];
|
||||
u_int8_t field_id_3;
|
||||
u_int8_t manuf_id_17_12[6];
|
||||
u_int8_t reserved3;
|
||||
u_int8_t field_id_4;
|
||||
u_int8_t manuf_id_11_6[6];
|
||||
u_int8_t reserved4;
|
||||
u_int8_t field_id_5;
|
||||
u_int8_t manuf_id_5_0[6];
|
||||
u_int8_t reserved5[25];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_disc_id
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[4];
|
||||
u_int8_t random_num[2];
|
||||
u_int8_t year[4];
|
||||
u_int8_t month[2];
|
||||
u_int8_t day[2];
|
||||
u_int8_t hour[2];
|
||||
u_int8_t minute[2];
|
||||
u_int8_t second[2];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_generic_dcb
|
||||
{
|
||||
u_int8_t content_desc[4];
|
||||
#define SCSI_RCB
|
||||
u_int8_t unknown_desc_actions[4];
|
||||
#define RDSD_ACTION_RECORDING 0x0001
|
||||
#define RDSD_ACTION_READING 0x0002
|
||||
#define RDSD_ACTION_FORMAT 0x0004
|
||||
#define RDSD_ACTION_MODIFY_DCB 0x0008
|
||||
u_int8_t vendor_id[32];
|
||||
u_int8_t dcb_data[32728];
|
||||
};
|
||||
|
||||
struct scsi_read_dvd_struct_data_dcb
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
struct scsi_read_dvd_struct_data_generic_dcb dcb;
|
||||
};
|
||||
|
||||
struct read_dvd_struct_write_prot
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved0[2];
|
||||
u_int8_t write_prot_status;
|
||||
#define RDSD_WPS_MSWI 0x08
|
||||
#define RDSD_WPS_CWP 0x04
|
||||
#define RDSD_WPS_PWP 0x02
|
||||
#define RDSD_WPS_SWPP 0x01
|
||||
u_int8_t reserved[3];
|
||||
};
|
||||
|
||||
struct read_dvd_struct_list_entry
|
||||
{
|
||||
u_int8_t format_code;
|
||||
u_int8_t sds_rds;
|
||||
#define RDSD_SDS_NOT_WRITEABLE 0x00
|
||||
#define RDSD_SDS_WRITEABLE 0x80
|
||||
#define RDSD_SDS_MASK 0x80
|
||||
#define RDSD_RDS_NOT_READABLE 0x00
|
||||
#define RDSD_RDS_READABLE 0x40
|
||||
#define RDSD_RDS_MASK 0x40
|
||||
u_int8_t struct_len[2];
|
||||
};
|
||||
|
||||
struct read_dvd_struct_data_list
|
||||
{
|
||||
u_int8_t data_len[2];
|
||||
u_int8_t reserved[2];
|
||||
struct read_dvd_struct_list_entry entries[0];
|
||||
};
|
||||
|
||||
struct scsi_read_cd_cap_data
|
||||
{
|
||||
@ -213,5 +685,30 @@ struct cd_mode_data
|
||||
struct scsi_mode_blk_desc blk_desc;
|
||||
union cd_pages page;
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
void scsi_report_key(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, u_int32_t lba, u_int8_t agid,
|
||||
u_int8_t key_format, u_int8_t *data_ptr,
|
||||
u_int32_t dxfer_len, u_int8_t sense_len,
|
||||
u_int32_t timeout);
|
||||
|
||||
void scsi_send_key(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, u_int8_t agid, u_int8_t key_format,
|
||||
u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
|
||||
u_int32_t timeout);
|
||||
|
||||
void scsi_read_dvd_structure(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, u_int32_t address,
|
||||
u_int8_t layer_number, u_int8_t format,
|
||||
u_int8_t agid, u_int8_t *data_ptr,
|
||||
u_int32_t dxfer_len, u_int8_t sense_len,
|
||||
u_int32_t timeout);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /*_SCSI_SCSI_CD_H*/
|
||||
|
||||
|
@ -82,6 +82,8 @@ struct dvd_authinfo {
|
||||
#define DVD_STRUCT_PROTDISCID 0x06
|
||||
#define DVD_STRUCT_DISCKEYBLOCK 0x07
|
||||
#define DVD_STRUCT_DDS 0x08
|
||||
#define DVD_STRUCT_MEDIUM_STAT 0x09
|
||||
#define DVD_STRUCT_SPARE_AREA 0x0A
|
||||
#define DVD_STRUCT_RMD_LAST 0x0C
|
||||
#define DVD_STRUCT_RMD_RMA 0x0D
|
||||
#define DVD_STRUCT_PRERECORDED 0x0E
|
||||
|
Loading…
Reference in New Issue
Block a user