|
|
1.1 ! root 1: /* $Id: scsi-cdrom.c,v 1.2 2007/03/29 01:19:41 fredette Exp $ */ ! 2: ! 3: /* scsi/scsi-cdrom.c - implementation of SCSI CD-ROM emulation: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2007 Matt Fredette ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. All advertising materials mentioning features or use of this software ! 18: * must display the following acknowledgement: ! 19: * This product includes software developed by Matt Fredette. ! 20: * 4. The name of the author may not be used to endorse or promote products ! 21: * derived from this software without specific prior written permission. ! 22: * ! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 33: * POSSIBILITY OF SUCH DAMAGE. ! 34: */ ! 35: ! 36: #include <tme/common.h> ! 37: _TME_RCSID("$Id: scsi-cdrom.c,v 1.2 2007/03/29 01:19:41 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include <tme/scsi/scsi-cdrom.h> ! 41: #ifdef HAVE_STDARG_H ! 42: #include <stdarg.h> ! 43: #else /* HAVE_STDARG_H */ ! 44: #include <varargs.h> ! 45: #endif /* HAVE_STDARG_H */ ! 46: ! 47: /* macros: */ ! 48: ! 49: /* globals: */ ! 50: ! 51: /* the list of cdroms that we emulate: */ ! 52: const struct { ! 53: ! 54: /* the type name: */ ! 55: const char *_tme_scsi_cdrom_list_type; ! 56: ! 57: /* the initialization function: */ ! 58: int (*_tme_scsi_cdrom_list_init) _TME_P((struct tme_scsi_cdrom *)); ! 59: } _tme_scsi_cdrom_list[] = { ! 60: ! 61: /* the generic TME SCSI-1 cdrom: */ ! 62: { "tme-scsi-1", tme_scsi_cdrom_tme_init }, ! 63: }; ! 64: ! 65: /* this implements the CD-ROM INQUIRY command: */ ! 66: _TME_SCSI_DEVICE_CDB_DECL(tme_scsi_cdrom_cdb_inquiry) ! 67: { ! 68: int lun; ! 69: struct tme_scsi_device_inquiry inquiry; ! 70: tme_uint8_t *data; ! 71: ! 72: /* get the active LUN: */ ! 73: lun = scsi_device->tme_scsi_device_addressed_lun; ! 74: ! 75: /* this is a CD-ROM: */ ! 76: inquiry.tme_scsi_device_inquiry_type = TME_SCSI_TYPE_CDROM; ! 77: ! 78: /* if this LUN is defined: */ ! 79: inquiry.tme_scsi_device_inquiry_lun_state ! 80: = ((scsi_device->tme_scsi_device_luns ! 81: & TME_BIT(lun)) ! 82: ? TME_SCSI_LUN_PRESENT ! 83: : TME_SCSI_LUN_UNSUPPORTED); ! 84: ! 85: /* the device type qualifier: */ ! 86: inquiry.tme_scsi_device_inquiry_type_qualifier = 0x00; ! 87: ! 88: /* nonzero iff the LUN is removable: */ ! 89: inquiry.tme_scsi_device_inquiry_lun_removable = TRUE; ! 90: ! 91: /* the various standards versions: */ ! 92: inquiry.tme_scsi_device_inquiry_std_ansi = 1; ! 93: inquiry.tme_scsi_device_inquiry_std_ecma = 1; ! 94: inquiry.tme_scsi_device_inquiry_std_iso = 1; ! 95: ! 96: /* the response format: */ ! 97: inquiry.tme_scsi_device_response_format = TME_SCSI_FORMAT_CCS; ! 98: ! 99: /* make the inquiry data: */ ! 100: data ! 101: = tme_scsi_device_make_inquiry_data(scsi_device, ! 102: &inquiry); ! 103: scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid ! 104: = TME_MIN((data ! 105: - scsi_device->tme_scsi_device_dma.tme_scsi_dma_out), ! 106: scsi_device->tme_scsi_device_cdb[4]); ! 107: ! 108: /* finish the command: */ ! 109: tme_scsi_device_target_do_dsmf(scsi_device, ! 110: TME_SCSI_STATUS_GOOD, ! 111: TME_SCSI_MSG_CMD_COMPLETE); ! 112: } ! 113: ! 114: /* this implements the CD-ROM READ TOC command: */ ! 115: _TME_SCSI_DEVICE_CDB_DECL(tme_scsi_cdrom_cdb_read_toc) ! 116: { ! 117: struct tme_scsi_cdrom *scsi_cdrom; ! 118: struct tme_scsi_cdrom_connection *conn_scsi_cdrom; ! 119: struct tme_disk_connection *conn_disk; ! 120: tme_uint8_t *data; ! 121: tme_uint32_t space; ! 122: tme_uint32_t length; ! 123: int lun; ! 124: ! 125: /* recover our CD-ROM: */ ! 126: scsi_cdrom = (struct tme_scsi_cdrom *) scsi_device; ! 127: ! 128: /* get the active LUN: */ ! 129: lun = scsi_device->tme_scsi_device_addressed_lun; ! 130: ! 131: /* get the CD-ROM connection: */ ! 132: conn_scsi_cdrom ! 133: = scsi_cdrom->tme_scsi_cdrom_connections[lun]; ! 134: conn_disk ! 135: = ((struct tme_disk_connection *) ! 136: conn_scsi_cdrom->tme_scsi_disk_connection.tme_disk_connection.tme_connection_other); ! 137: ! 138: /* we require that the MSF bit be zero: */ ! 139: if (scsi_device->tme_scsi_device_cdb[1] & 0x02) { ! 140: tme_scsi_device_check_condition(scsi_device, ! 141: TME_SCSI_SENSE_EXT_KEY_ILLEGAL_REQUEST, ! 142: TME_SCSI_SENSE_EXT_ASC_ASCQ_INVALID_FIELD_CDB); ! 143: return; ! 144: } ! 145: ! 146: /* "If the starting track field is not valid for the currently ! 147: installed medium, the command shall be terminated with CHECK ! 148: CONDITION status. The sense key shall be set to ILLEGAL REQUEST ! 149: and the additional sense code set to INVALID FIELD IN CDB." */ ! 150: /* NB: for now, we support only one track: */ ! 151: if (scsi_device->tme_scsi_device_cdb[6] > 1) { ! 152: tme_scsi_device_check_condition(scsi_device, ! 153: TME_SCSI_SENSE_EXT_KEY_ILLEGAL_REQUEST, ! 154: TME_SCSI_SENSE_EXT_ASC_ASCQ_INVALID_FIELD_CDB); ! 155: return; ! 156: } ! 157: ! 158: /* start returning the data: */ ! 159: data = &scsi_device->tme_scsi_device_data[0]; ! 160: ! 161: /* bytes 0 and 1 are the TOC data length. we will fill this in later: */ ! 162: data += 2; ! 163: ! 164: /* the first and last track numbers: */ ! 165: /* NB: for now, we support only one track: */ ! 166: *(data++) = 1; ! 167: *(data++) = 1; ! 168: ! 169: /* one TOC track descriptor: */ ! 170: ! 171: /* a reserved byte: */ ! 172: data++; ! 173: ! 174: /* the ADR and control byte: */ ! 175: /* NB: this specifies no sub-channel Q mode, and a data track: */ ! 176: *(data++) = (0x0 << 4) | (1 << 2); ! 177: ! 178: /* the track number: */ ! 179: *(data++) = 1; ! 180: ! 181: /* this track begins at block zero: */ ! 182: *(data++) = 0; ! 183: *(data++) = 0; ! 184: *(data++) = 0; ! 185: *(data++) = 0; ! 186: ! 187: /* fill in the TOC data length, which does not include the TOC data ! 188: length field itself: */ ! 189: length = (data - (&scsi_device->tme_scsi_device_data[0] + sizeof(tme_uint16_t))); ! 190: scsi_device->tme_scsi_device_data[0] = (length >> 8); ! 191: scsi_device->tme_scsi_device_data[1] = length; ! 192: ! 193: /* set the DMA pointer and length: */ ! 194: space = scsi_device->tme_scsi_device_cdb[7]; ! 195: space = (space << 8) + scsi_device->tme_scsi_device_cdb[8]; ! 196: scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid ! 197: = TME_MIN((unsigned long) (data - &scsi_device->tme_scsi_device_data[0]), ! 198: space); ! 199: scsi_device->tme_scsi_device_dma.tme_scsi_dma_out ! 200: = &scsi_device->tme_scsi_device_data[0]; ! 201: scsi_device->tme_scsi_device_dma.tme_scsi_dma_in ! 202: = NULL; ! 203: ! 204: /* finish the command: */ ! 205: tme_scsi_device_target_do_dsmf(scsi_device, ! 206: TME_SCSI_STATUS_GOOD, ! 207: TME_SCSI_MSG_CMD_COMPLETE); ! 208: } ! 209: ! 210: /* this implements the CD-ROM MODE SENSE command: */ ! 211: _TME_SCSI_DEVICE_CDB_DECL(tme_scsi_cdrom_cdb_mode_sense) ! 212: { ! 213: struct tme_scsi_cdrom *scsi_cdrom; ! 214: struct tme_scsi_cdrom_connection *conn_scsi_cdrom; ! 215: tme_uint8_t *data; ! 216: tme_uint32_t block_size; ! 217: tme_uint32_t length; ! 218: int is_group0_cmd; ! 219: int lun; ! 220: ! 221: /* see if this is a Group 0 MODE SELECT: */ ! 222: is_group0_cmd ! 223: = ((scsi_device->tme_scsi_device_cdb[0] ! 224: & TME_SCSI_CDB_GROUP_MASK) ! 225: == TME_SCSI_CDB_GROUP_0); ! 226: ! 227: /* recover our CD-ROM: */ ! 228: scsi_cdrom = (struct tme_scsi_cdrom *) scsi_device; ! 229: ! 230: /* get the active LUN: */ ! 231: lun = scsi_device->tme_scsi_device_addressed_lun; ! 232: ! 233: /* get the CD-ROM connection: */ ! 234: conn_scsi_cdrom ! 235: = scsi_cdrom->tme_scsi_cdrom_connections[lun]; ! 236: ! 237: data = &scsi_device->tme_scsi_device_data[0]; ! 238: ! 239: /* the Mode Data Length is one byte for the Group 0 command and two ! 240: bytes otherwise. we will fill this in later: */ ! 241: data += (is_group0_cmd ? 1 : 2); ! 242: ! 243: /* the Medium Type is one byte: */ ! 244: *(data++) = 0x00; /* default (only one medium type supported) */ ! 245: ! 246: /* the Device Specific Parameter is one byte: */ ! 247: *(data++) = 0x00; /* no DPO/FUA support */ ! 248: ! 249: /* if this is not the Group 0 command, skip two reserved bytes: */ ! 250: if (!is_group0_cmd) { ! 251: data += 2; ! 252: } ! 253: ! 254: /* the Block Descriptor Length is one byte for the Group 0 command ! 255: and two bytes otherwise. we will fill this in later: */ ! 256: data += (is_group0_cmd ? 1 : 2); ! 257: ! 258: /* the first Block Descriptor: */ ! 259: ! 260: /* the Block Descriptor density code: */ ! 261: *(data++) = 0x01; /* User Data only - 2048 bytes per physical sector */ ! 262: ! 263: /* the Number of Blocks: */ ! 264: /* "A value of zero indicates that all of the remaining logical ! 265: blocks of the logical unit shall have the medium characteristics ! 266: specified." */ ! 267: *(data++) = 0x00; ! 268: *(data++) = 0x00; ! 269: *(data++) = 0x00; ! 270: ! 271: /* a reserved byte: */ ! 272: data++; ! 273: ! 274: /* the Block Length: */ ! 275: block_size ! 276: = conn_scsi_cdrom->tme_scsi_disk_connection_block_size.tme_value64_uint32_lo; ! 277: *(data++) = (block_size >> 16) & 0xff; ! 278: *(data++) = (block_size >> 8) & 0xff; ! 279: *(data++) = (block_size >> 0) & 0xff; ! 280: ! 281: /* fill in the Block Descriptor Length: */ ! 282: if (is_group0_cmd) { ! 283: length = (data - &scsi_device->tme_scsi_device_data[4]); ! 284: scsi_device->tme_scsi_device_data[3] = length; ! 285: } ! 286: else { ! 287: length = (data - &scsi_device->tme_scsi_device_data[8]); ! 288: scsi_device->tme_scsi_device_data[6] = (length >> 8); ! 289: scsi_device->tme_scsi_device_data[7] = length; ! 290: } ! 291: ! 292: /* there are no vendor-unique bytes: */ ! 293: ! 294: /* fill in the Mode Data Length: */ ! 295: if (is_group0_cmd) { ! 296: length = (data - &scsi_device->tme_scsi_device_data[1]); ! 297: scsi_device->tme_scsi_device_data[0] = length; ! 298: } ! 299: else { ! 300: length = (data - &scsi_device->tme_scsi_device_data[2]); ! 301: scsi_device->tme_scsi_device_data[0] = (length >> 8); ! 302: scsi_device->tme_scsi_device_data[1] = length; ! 303: } ! 304: ! 305: /* set the DMA pointer and length: */ ! 306: if (is_group0_cmd) { ! 307: length = scsi_device->tme_scsi_device_cdb[4]; ! 308: } ! 309: else { ! 310: length = scsi_device->tme_scsi_device_cdb[7]; ! 311: length = (length << 8) + scsi_device->tme_scsi_device_cdb[8]; ! 312: } ! 313: scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid ! 314: = TME_MIN((unsigned long) ! 315: (data ! 316: - &scsi_device->tme_scsi_device_data[0]), ! 317: length); ! 318: scsi_device->tme_scsi_device_dma.tme_scsi_dma_out ! 319: = &scsi_device->tme_scsi_device_data[0]; ! 320: scsi_device->tme_scsi_device_dma.tme_scsi_dma_in ! 321: = NULL; ! 322: ! 323: /* finish the command: */ ! 324: tme_scsi_device_target_do_dsmf(scsi_device, ! 325: TME_SCSI_STATUS_GOOD, ! 326: TME_SCSI_MSG_CMD_COMPLETE); ! 327: } ! 328: ! 329: /* this handles block descriptors from a MODE SELECT command: */ ! 330: static int ! 331: _tme_scsi_cdrom_do_mode_select_blocks(struct tme_scsi_device *scsi_device, ! 332: const struct tme_scsi_device_mode_blocks *blocks) ! 333: { ! 334: struct tme_scsi_cdrom *scsi_cdrom; ! 335: struct tme_scsi_cdrom_connection *conn_scsi_cdrom; ! 336: int lun; ! 337: ! 338: /* recover our CD-ROM: */ ! 339: scsi_cdrom = (struct tme_scsi_cdrom *) scsi_device; ! 340: ! 341: /* get the active LUN: */ ! 342: lun = scsi_device->tme_scsi_device_addressed_lun; ! 343: ! 344: /* get the CD-ROM connection: */ ! 345: conn_scsi_cdrom ! 346: = scsi_cdrom->tme_scsi_cdrom_connections[lun]; ! 347: ! 348: /* XXX FIXME - this needs to be implemented correctly: */ ! 349: ! 350: /* if this block descriptor doesn't describe the entire CD-ROM: */ ! 351: if (blocks->tme_scsi_device_mode_blocks_number != 0) { ! 352: tme_scsi_device_check_condition(scsi_device, ! 353: TME_SCSI_SENSE_EXT_KEY_ILLEGAL_REQUEST, ! 354: TME_SCSI_SENSE_EXT_ASC_ASCQ_PARAMETER_VALUE_INVALID); ! 355: return (-1); ! 356: } ! 357: ! 358: /* dispatch on the density code: */ ! 359: switch (blocks->tme_scsi_device_mode_blocks_density_code) { ! 360: case 0x00: /* Default density code */ ! 361: case 0x01: /* User Data Only, 2048 bytes per physical sector */ ! 362: break; ! 363: default: ! 364: tme_scsi_device_check_condition(scsi_device, ! 365: TME_SCSI_SENSE_EXT_KEY_ILLEGAL_REQUEST, ! 366: TME_SCSI_SENSE_EXT_ASC_ASCQ_PARAMETER_VALUE_INVALID); ! 367: return (-1); ! 368: } ! 369: ! 370: /* the logical block size must be an exact divisor or an integral ! 371: multiple of 2048: */ ! 372: if (blocks->tme_scsi_device_mode_blocks_length == 0 ! 373: || ((blocks->tme_scsi_device_mode_blocks_length ! 374: < 2048) ! 375: ? (2048 % blocks->tme_scsi_device_mode_blocks_length) ! 376: : (blocks->tme_scsi_device_mode_blocks_length % 2048))) { ! 377: tme_scsi_device_check_condition(scsi_device, ! 378: TME_SCSI_SENSE_EXT_KEY_ILLEGAL_REQUEST, ! 379: TME_SCSI_SENSE_EXT_ASC_ASCQ_PARAMETER_VALUE_INVALID); ! 380: return (-1); ! 381: } ! 382: ! 383: /* update the logical block size: */ ! 384: conn_scsi_cdrom->tme_scsi_disk_connection_block_size.tme_value64_uint32_lo ! 385: = blocks->tme_scsi_device_mode_blocks_length; ! 386: ! 387: return (0); ! 388: } ! 389: ! 390: /* this handles a mode page from a CD-ROM MODE SELECT command: */ ! 391: static int ! 392: _tme_scsi_cdrom_do_mode_select_page(struct tme_scsi_device *scsi_device, ! 393: const tme_uint8_t *mode_page) ! 394: { ! 395: return (0); ! 396: } ! 397: ! 398: /* this processes the parameter list from a CD-ROM MODE SELECT command: */ ! 399: static ! 400: _TME_SCSI_DEVICE_PHASE_DECL(_tme_scsi_cdrom_mode_select_data) ! 401: { ! 402: tme_scsi_device_mode_select_data(scsi_device, ! 403: _tme_scsi_cdrom_do_mode_select_blocks, ! 404: _tme_scsi_cdrom_do_mode_select_page); ! 405: } ! 406: ! 407: /* this implements the CD-ROM MODE SELECT command: */ ! 408: _TME_SCSI_DEVICE_CDB_DECL(tme_scsi_cdrom_cdb_mode_select) ! 409: { ! 410: tme_uint32_t length; ! 411: int is_group0_cmd; ! 412: ! 413: /* see if this is a Group 0 MODE SELECT: */ ! 414: is_group0_cmd ! 415: = ((scsi_device->tme_scsi_device_cdb[0] ! 416: & TME_SCSI_CDB_GROUP_MASK) ! 417: == TME_SCSI_CDB_GROUP_0); ! 418: ! 419: /* read in the parameter list: */ ! 420: if (is_group0_cmd) { ! 421: length = scsi_device->tme_scsi_device_cdb[4]; ! 422: } ! 423: else { ! 424: length = scsi_device->tme_scsi_device_cdb[7]; ! 425: length = (length << 8) + scsi_device->tme_scsi_device_cdb[8]; ! 426: } ! 427: scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid ! 428: = TME_MIN(sizeof(scsi_device->tme_scsi_device_data), ! 429: length); ! 430: scsi_device->tme_scsi_device_dma.tme_scsi_dma_in ! 431: = &scsi_device->tme_scsi_device_data[0]; ! 432: scsi_device->tme_scsi_device_dma.tme_scsi_dma_out ! 433: = NULL; ! 434: ! 435: /* transfer the parameter list: */ ! 436: tme_scsi_device_target_phase(scsi_device, ! 437: (TME_SCSI_SIGNAL_BSY ! 438: | TME_SCSI_PHASE_DATA_OUT)); ! 439: scsi_device->tme_scsi_device_phase ! 440: = _tme_scsi_cdrom_mode_select_data; ! 441: } ! 442: ! 443: /* the new SCSI CD-ROM function: */ ! 444: TME_ELEMENT_SUB_NEW_DECL(tme_scsi,cdrom) { ! 445: int id; ! 446: const char *cdrom_type; ! 447: const char *vendor; ! 448: const char *product; ! 449: const char *revision; ! 450: struct tme_scsi_cdrom *scsi_cdrom; ! 451: struct tme_scsi_device *scsi_device; ! 452: int arg_i; ! 453: int usage; ! 454: unsigned int cdrom_list_i; ! 455: int (*cdrom_init) _TME_P((struct tme_scsi_cdrom *)); ! 456: int rc; ! 457: ! 458: /* check our arguments: */ ! 459: id = -1; ! 460: cdrom_type = NULL; ! 461: vendor = NULL; ! 462: product = NULL; ! 463: revision = NULL; ! 464: arg_i = 1; ! 465: usage = FALSE; ! 466: ! 467: /* loop reading our arguments: */ ! 468: for (;;) { ! 469: ! 470: /* the SCSI ID: */ ! 471: if (TME_ARG_IS(args[arg_i], "id") ! 472: && id < 0 ! 473: && (id = tme_scsi_id_parse(args[arg_i + 1])) >= 0) { ! 474: arg_i += 2; ! 475: } ! 476: ! 477: /* the CD-ROM type: */ ! 478: else if (TME_ARG_IS(args[arg_i], "type") ! 479: && cdrom_type == NULL ! 480: && args[arg_i + 1] != NULL) { ! 481: cdrom_type = args[arg_i + 1]; ! 482: arg_i += 2; ! 483: } ! 484: ! 485: /* any inquiry vendor, product, or revision: */ ! 486: else if (TME_ARG_IS(args[arg_i], "vendor") ! 487: && vendor == NULL ! 488: && args[arg_i + 1] != NULL) { ! 489: vendor = args[arg_i + 1]; ! 490: arg_i += 2; ! 491: } ! 492: else if (TME_ARG_IS(args[arg_i], "product") ! 493: && product == NULL ! 494: && args[arg_i + 1] != NULL) { ! 495: product = args[arg_i + 1]; ! 496: arg_i += 2; ! 497: } ! 498: else if (TME_ARG_IS(args[arg_i], "revision") ! 499: && revision == NULL ! 500: && args[arg_i + 1] != NULL) { ! 501: revision = args[arg_i + 1]; ! 502: arg_i += 2; ! 503: } ! 504: ! 505: /* if we've run out of arguments: */ ! 506: else if (args[arg_i + 0] == NULL) { ! 507: ! 508: /* we must have been given an ID and a type: */ ! 509: if (id < 0 ! 510: || cdrom_type == NULL) { ! 511: usage = TRUE; ! 512: } ! 513: break; ! 514: } ! 515: ! 516: /* this is a bad argument: */ ! 517: else { ! 518: tme_output_append_error(_output, ! 519: "%s %s", ! 520: args[arg_i], ! 521: _("unexpected")); ! 522: usage = TRUE; ! 523: break; ! 524: } ! 525: } ! 526: ! 527: if (usage) { ! 528: tme_output_append_error(_output, ! 529: "%s %s id %s type %s [ vendor %s ] [ product %s ] [ revision %s ]", ! 530: _("usage:"), ! 531: args[0], ! 532: _("TYPE"), ! 533: _("ID"), ! 534: _("VENDOR"), ! 535: _("PRODUCT"), ! 536: _("REVISION")); ! 537: return (EINVAL); ! 538: } ! 539: ! 540: /* make sure that this CD-ROM type is known: */ ! 541: cdrom_init = NULL; ! 542: for (cdrom_list_i = 0; ! 543: cdrom_list_i < TME_ARRAY_ELS(_tme_scsi_cdrom_list); ! 544: cdrom_list_i++) { ! 545: if (!strcmp(_tme_scsi_cdrom_list[cdrom_list_i]._tme_scsi_cdrom_list_type, ! 546: cdrom_type)) { ! 547: cdrom_init = _tme_scsi_cdrom_list[cdrom_list_i]._tme_scsi_cdrom_list_init; ! 548: break; ! 549: } ! 550: } ! 551: if (cdrom_init == NULL) { ! 552: tme_output_append_error(_output, "%s", cdrom_type); ! 553: return (ENOENT); ! 554: } ! 555: ! 556: /* start the CD-ROM structure: */ ! 557: scsi_cdrom = tme_new0(struct tme_scsi_cdrom, 1); ! 558: scsi_cdrom->tme_scsi_cdrom_element = element; ! 559: scsi_cdrom->tme_scsi_cdrom_type = tme_strdup(cdrom_type); ! 560: ! 561: /* initialize the generic SCSI device structure: */ ! 562: scsi_device = &scsi_cdrom->tme_scsi_cdrom_device; ! 563: rc = tme_scsi_device_new(scsi_device, id); ! 564: assert (rc == TME_OK); ! 565: ! 566: scsi_device->tme_scsi_device_vendor ! 567: = tme_strdup((vendor == NULL) ! 568: ? "TME" ! 569: : vendor); ! 570: scsi_device->tme_scsi_device_product ! 571: = tme_strdup((product == NULL) ! 572: ? "CDROM" ! 573: : product); ! 574: scsi_device->tme_scsi_device_revision ! 575: = tme_strdup((revision == NULL) ! 576: ? "0000" ! 577: : revision); ! 578: ! 579: /* set the commands for CD-ROMs: */ ! 580: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 581: TME_SCSI_CDB_INQUIRY, ! 582: tme_scsi_cdrom_cdb_inquiry); ! 583: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 584: TME_SCSI_CDB_CDROM_READ0, ! 585: tme_scsi_cdrom_cdb_read0); ! 586: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 587: TME_SCSI_CDB_CDROM_MODE_SELECT0, ! 588: tme_scsi_cdrom_cdb_mode_select); ! 589: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 590: TME_SCSI_CDB_CDROM_MODE_SENSE0, ! 591: tme_scsi_cdrom_cdb_mode_sense); ! 592: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 593: TME_SCSI_CDB_CDROM_START_STOP, ! 594: tme_scsi_cdrom_cdb_start_stop); ! 595: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 596: TME_SCSI_CDB_CDROM_PREVENT_ALLOW, ! 597: tme_scsi_cdrom_cdb_prevent_allow); ! 598: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 599: TME_SCSI_CDB_CDROM_READ_CAPACITY, ! 600: tme_scsi_cdrom_cdb_read_capacity); ! 601: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 602: TME_SCSI_CDB_CDROM_READ1, ! 603: tme_scsi_cdrom_cdb_read1); ! 604: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 605: TME_SCSI_CDB_CDROM_READ_SUBCHANNEL, ! 606: tme_scsi_device_cdb_illegal); ! 607: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 608: TME_SCSI_CDB_CDROM_READ_TOC, ! 609: tme_scsi_cdrom_cdb_read_toc); ! 610: TME_SCSI_DEVICE_DO_CDB(scsi_device, ! 611: TME_SCSI_CDB_CDROM_PLAY_AUDIO2, ! 612: tme_scsi_device_cdb_illegal); ! 613: ! 614: /* call the type-specific initialization function: */ ! 615: rc = (*cdrom_init)(scsi_cdrom); ! 616: assert (rc == TME_OK); ! 617: ! 618: /* fill the element: */ ! 619: element->tme_element_private = scsi_cdrom; ! 620: element->tme_element_connections_new = tme_scsi_cdrom_connections_new; ! 621: ! 622: return (TME_OK); ! 623: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.