|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.