Annotation of tme/scsi/scsi-cdrom.c, revision 1.1.1.2

1.1.1.2 ! root        1: /* $Id: scsi-cdrom.c,v 1.3 2009/09/26 13:07:39 fredette Exp $ */
1.1       root        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>
1.1.1.2 ! root       37: _TME_RCSID("$Id: scsi-cdrom.c,v 1.3 2009/09/26 13:07:39 fredette Exp $");
1.1       root       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);
1.1.1.2 ! root      613:   TME_SCSI_DEVICE_DO_CDB(scsi_device,
        !           614:                         TME_SCSI_CDB_CDROM_READ_DISC_INFORMATION,
        !           615:                         tme_scsi_device_cdb_illegal);
        !           616:   TME_SCSI_DEVICE_DO_CDB(scsi_device,
        !           617:                         TME_SCSI_CDB_CDROM_CACHE_SYNC,
        !           618:                         tme_scsi_device_cdb_illegal);
1.1       root      619: 
                    620:   /* call the type-specific initialization function: */
                    621:   rc = (*cdrom_init)(scsi_cdrom);
                    622:   assert (rc == TME_OK);
                    623: 
                    624:   /* fill the element: */
                    625:   element->tme_element_private = scsi_cdrom;
                    626:   element->tme_element_connections_new = tme_scsi_cdrom_connections_new;
                    627: 
                    628:   return (TME_OK);
                    629: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.