Annotation of tme/scsi/scsi-cdb.c, revision 1.1.1.1

1.1       root        1: /* $Id: scsi-cdb.c,v 1.4 2003/10/16 02:48:25 fredette Exp $ */
                      2: 
                      3: /* scsi/scsi-cdb.c - implementation of generic SCSI device CDB support: */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2003 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-cdb.c,v 1.4 2003/10/16 02:48:25 fredette Exp $");
                     38: 
                     39: /* includes: */
                     40: #include <tme/scsi/scsi-cdb.h>
                     41: #include <tme/scsi/scsi-msg.h>
                     42: 
                     43: /* this handles any illegal request: */
                     44: _TME_SCSI_DEVICE_CDB_DECL(tme_scsi_device_cdb_illegal)
                     45: {
                     46:   struct tme_scsi_device_sense *sense;
                     47:   int lun;
                     48: 
                     49:   /* get the addressed LUN's sense: */
                     50:   lun = scsi_device->tme_scsi_device_addressed_lun;
                     51:   sense = &scsi_device->tme_scsi_device_sense[lun];
                     52: 
                     53:   /* if this target does not support extended sense: */
                     54:   if (scsi_device->tme_scsi_device_sense_no_extended) {
                     55: 
                     56:     /* the error class and error code: */
                     57:     sense->tme_scsi_device_sense_data[0]
                     58:       = 0x20;
                     59:     sense->tme_scsi_device_sense_data[1]
                     60:       = 0;
                     61:     sense->tme_scsi_device_sense_data[2]
                     62:       = 0;
                     63:     sense->tme_scsi_device_sense_data[3]
                     64:       = 0;
                     65:     sense->tme_scsi_device_sense_valid = 4;
                     66:   }
                     67: 
                     68:   /* otherwise, return an extended sense: */
                     69:   else {
                     70: 
                     71:     /* the error class and error code: */
                     72:     sense->tme_scsi_device_sense_data[0]
                     73:       = 0x70;
                     74: 
                     75:     /* the ILLEGAL REQUEST sense key: */
                     76:     sense->tme_scsi_device_sense_data[2]
                     77:        = 0x05;
                     78: 
                     79:     /* the additional sense length: */
                     80:     sense->tme_scsi_device_sense_data[7]
                     81:       = 0x00;
                     82: 
                     83:     sense->tme_scsi_device_sense_valid
                     84:       = TRUE;
                     85:   }
                     86: 
                     87:   /* return the CHECK CONDITION status: */
                     88:   tme_scsi_device_target_do_smf(scsi_device,
                     89:                                TME_SCSI_STATUS_CHECK_CONDITION,
                     90:                                TME_SCSI_MSG_CMD_COMPLETE);
                     91: }
                     92: 
                     93: /* this handles the TEST UNIT READY command: */
                     94: _TME_SCSI_DEVICE_CDB_DECL(tme_scsi_device_cdb_tur)
                     95: {
                     96:   /* finish the command: */
                     97:   tme_scsi_device_target_do_smf(scsi_device,
                     98:                                TME_SCSI_STATUS_GOOD,
                     99:                                TME_SCSI_MSG_CMD_COMPLETE);
                    100: }
                    101: 
                    102: /* this handles the REQUEST SENSE command: */
                    103: _TME_SCSI_DEVICE_CDB_DECL(tme_scsi_device_cdb_request_sense)
                    104: {
                    105:   int lun;
                    106:   struct tme_scsi_device_sense *sense;
                    107:   unsigned long transfer_length;
                    108:   
                    109:   /* get the addressed LUN's sense: */
                    110:   lun = scsi_device->tme_scsi_device_addressed_lun;
                    111:   sense = &scsi_device->tme_scsi_device_sense[lun];
                    112: 
                    113:   /* if the sense is not valid: */
                    114:   if (!sense->tme_scsi_device_sense_valid) {
                    115: 
                    116:     /* if this device doesn't do extended sense: */
                    117:     if (scsi_device->tme_scsi_device_sense_no_extended) {
                    118: 
                    119:       /* conjure up a no-error nonextended sense: */
                    120:       sense->tme_scsi_device_sense_data[0]
                    121:        = 0;
                    122:       sense->tme_scsi_device_sense_data[1]
                    123:        = 0;
                    124:       sense->tme_scsi_device_sense_data[2]
                    125:        = 0;
                    126:       sense->tme_scsi_device_sense_data[3]
                    127:        = 0;
                    128:       sense->tme_scsi_device_sense_valid = 4;
                    129:     }
                    130: 
                    131:     /* otherwise, this device does do extended sense: */
                    132:     else {
                    133:       
                    134:       /* the error class and error code: */
                    135:       sense->tme_scsi_device_sense_data[0]
                    136:        = 0x70;
                    137: 
                    138:       /* the NO SENSE sense key: */
                    139:       sense->tme_scsi_device_sense_data[2]
                    140:        = 0x00;
                    141: 
                    142:       /* the additional sense length: */
                    143:       sense->tme_scsi_device_sense_data[7]
                    144:        = 0x00;
                    145:     }
                    146:   }
                    147: 
                    148:   /* see how much space for sense bytes the initiator
                    149:      has allocated.  zero means four: */
                    150:   transfer_length
                    151:     = scsi_device->tme_scsi_device_cdb[4];
                    152:   if (transfer_length == 0) {
                    153:     transfer_length = 4;
                    154:   }
                    155: 
                    156:   /* bound this with the number of sense bytes we have available.  an
                    157:      extended sense has a length of 8 plus the additional sense
                    158:      length.  any other sense must specify how long it is in the
                    159:      tme_scsi_device_sense_valid field (a standard nonextended sense
                    160:      always has a length of four): */
                    161:   transfer_length
                    162:     = TME_MIN(transfer_length,
                    163:              (((sense->tme_scsi_device_sense_data[0]
                    164:                 & 0x70)
                    165:                == 0x70)
                    166:               ? ((unsigned int) 8
                    167:                  + sense->tme_scsi_device_sense_data[7])
                    168:               : sense->tme_scsi_device_sense_valid));
                    169: 
                    170:   /* set up to transfer the sense: */
                    171:   scsi_device->tme_scsi_device_dma.tme_scsi_dma_in
                    172:     = NULL;
                    173:   scsi_device->tme_scsi_device_dma.tme_scsi_dma_out
                    174:     = &sense->tme_scsi_device_sense_data[0];
                    175:   scsi_device->tme_scsi_device_dma.tme_scsi_dma_resid
                    176:     = transfer_length;
                    177: 
                    178:   /* the sense is no longer valid: */
                    179:   sense->tme_scsi_device_sense_valid = FALSE;
                    180: 
                    181:   /* finish the command: */
                    182:   tme_scsi_device_target_do_dsmf(scsi_device,
                    183:                                 TME_SCSI_STATUS_GOOD,
                    184:                                 TME_SCSI_MSG_CMD_COMPLETE);
                    185: }
                    186: 
                    187: /* this adds one of the inquiry strings to the data: */
                    188: static tme_uint8_t *
                    189: _tme_scsi_device_make_inquiry_string(tme_uint8_t *data,
                    190:                                     const tme_uint8_t *string,
                    191:                                     unsigned int size)
                    192: {
                    193:   tme_uint8_t c;
                    194: 
                    195:   for (; size-- > 0; ) {
                    196:     c = *(string++);
                    197:     if (c == '\0') {
                    198:       c = ' ';
                    199:       string--;
                    200:     }
                    201:     *(data++) = c;
                    202:   }
                    203:   return (data);
                    204: }
                    205: 
                    206: /* this creates INQUIRY data: */
                    207: tme_uint8_t *
                    208: tme_scsi_device_make_inquiry_data(struct tme_scsi_device *scsi_device,
                    209:                                  const struct tme_scsi_device_inquiry *inquiry)
                    210: {
                    211:   tme_uint8_t *data;
                    212:   
                    213:   data = &scsi_device->tme_scsi_device_data[0];
                    214:   scsi_device->tme_scsi_device_dma.tme_scsi_dma_out = data;
                    215:   scsi_device->tme_scsi_device_dma.tme_scsi_dma_in = NULL;
                    216: 
                    217:   /* byte 0 is the peripheral device type: */
                    218:   *(data++)
                    219:     = (inquiry->tme_scsi_device_inquiry_type
                    220:        | inquiry->tme_scsi_device_inquiry_lun_state);
                    221: 
                    222:   /* byte 1 is the device type qualifier: */
                    223:   *(data++)
                    224:     = (inquiry->tme_scsi_device_inquiry_type_qualifier
                    225:        | (inquiry->tme_scsi_device_inquiry_lun_removable
                    226:          ? 0x80
                    227:          : 0x00));
                    228: 
                    229:   /* byte 2 is the standards versions: */
                    230:   *(data++)
                    231:     = ((inquiry->tme_scsi_device_inquiry_std_iso << 6)
                    232:        | (inquiry->tme_scsi_device_inquiry_std_ecma << 3)
                    233:        | (inquiry->tme_scsi_device_inquiry_std_iso << 0));
                    234: 
                    235:   /* byte 3 is the response format: */
                    236:   *(data++)
                    237:     = inquiry->tme_scsi_device_response_format;
                    238: 
                    239:   /* byte 4 is the additional length.  we will come back and
                    240:      fill it later: */
                    241:   data++;
                    242: 
                    243:   /* bytes 5, 6, and 7 are flags, that we initialize to zero: */
                    244:   *(data++) = 0x00;
                    245:   *(data++) = 0x00;
                    246:   *(data++) = 0x00;
                    247: 
                    248:   /* the next eight bytes are for the vendor: */
                    249:   data
                    250:     = _tme_scsi_device_make_inquiry_string(data,
                    251:                                           scsi_device->tme_scsi_device_vendor,
                    252:                                           8);
                    253:     
                    254:   /* the next 16 bytes are for the product: */
                    255:   data
                    256:     = _tme_scsi_device_make_inquiry_string(data,
                    257:                                           scsi_device->tme_scsi_device_product,
                    258:                                           16);
                    259: 
                    260:   /* the next four bytes are for the revision: */
                    261:   data
                    262:     = _tme_scsi_device_make_inquiry_string(data,
                    263:                                           scsi_device->tme_scsi_device_revision,
                    264:                                           4);
                    265: 
                    266:   /* fill in the additional length byte: */
                    267:   scsi_device->tme_scsi_device_data[4]
                    268:     = (data
                    269:        - &scsi_device->tme_scsi_device_data[5]);
                    270: 
                    271:   return (data);
                    272: }

unix.superglobalmegacorp.com

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