Annotation of tme/scsi/scsi-cdb.c, revision 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.