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

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: }

unix.superglobalmegacorp.com

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