1 /* $Id: scsi-device.h,v 1.8 2007/01/19 00:41:43 fredette Exp $ */ 2 3 /* tme/scsi/scsi-device.h - header file for generic SCSI device 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 #ifndef _TME_SCSI_SCSI_DEVICE_H 37 #define _TME_SCSI_SCSI_DEVICE_H 38 39 #include <tme/common.h> 40 _TME_RCSID("$Id: scsi-device.h,v 1.8 2007/01/19 00:41:43 fredette Exp $"); 41 42 /* includes: */ 43 #include <tme/threads.h> 44 #include <tme/generic/scsi.h> 45 46 /* macros: */ 47 48 /* the maximum number of logical units: */ 49 #define TME_SCSI_DEVICE_LUN_COUNT (8) 50 51 /* this makes a prototype for a message handler: */ 52 #define _TME_SCSI_DEVICE_MSG_P(sym) \ 53 void sym _TME_P((struct tme_scsi_device *, \ 54 tme_scsi_control_t, \ 55 tme_scsi_control_t)) 56 57 /* this declares a message handler: */ 58 #ifdef __STDC__ 59 #define _TME_SCSI_DEVICE_MSG_DECL(sym) \ 60 void sym(struct tme_scsi_device *scsi_device, tme_scsi_control_t control_old, tme_scsi_control_t control_new) 61 #else /* !__STDC__ */ 62 #define _TME_ELEMENT_NEW_DECL(sym) \ 63 void sym(scsi_device, control_old, control_new) \ 64 struct tme_scsi_device *scsi_device; \ 65 tme_scsi_control_t control_old; \ 66 tme_scsi_control_t control_new; 67 #endif /* !__STDC__ */ 68 69 /* this sets a message handler: */ 70 #define TME_SCSI_DEVICE_DO_MSG(dev, code, sym) \ 71 do { \ 72 (dev)->tme_scsi_device_do_msg[code] = (sym); \ 73 } while (/* CONSTCOND */ 0) 74 75 /* this sets an extended message handler: */ 76 #define TME_SCSI_DEVICE_DO_MSG_EXT(dev, code, sym)\ 77 do { \ 78 (dev)->tme_scsi_device_do_msg_ext[code] = (sym);\ 79 } while (/* CONSTCOND */ 0) 80 81 /* this makes a prototype for a CDB handler: */ 82 #define _TME_SCSI_DEVICE_CDB_P(sym) \ 83 _TME_SCSI_DEVICE_MSG_P(sym) 84 85 /* this declares a message handler: */ 86 #define _TME_SCSI_DEVICE_CDB_DECL(sym) \ 87 _TME_SCSI_DEVICE_MSG_DECL(sym) 88 89 /* this sets a CDB handler: */ 90 #define TME_SCSI_DEVICE_DO_CDB(dev, code, sym) \ 91 do { \ 92 (dev)->tme_scsi_device_do_cdb[code] = (sym); \ 93 } while (/* CONSTCOND */ 0) 94 95 /* this makes a prototype for a phase handler: */ 96 #define _TME_SCSI_DEVICE_PHASE_P(sym) \ 97 _TME_SCSI_DEVICE_MSG_P(sym) 98 99 /* this declares a phase handler: */ 100 #define _TME_SCSI_DEVICE_PHASE_DECL(sym) \ 101 _TME_SCSI_DEVICE_MSG_DECL(sym) 102 103 /* when a device is the target, this completes a command by 104 running the STATUS phase, followed by the MESSAGE IN 105 phase, followed by a BUS FREE phase: */ 106 #define tme_scsi_device_target_do_smf(d, s, m) \ 107 do { \ 108 (d)->tme_scsi_device_status = (s); \ 109 (d)->tme_scsi_device_msg[0] = (m); \ 110 tme_scsi_device_target_smf(d, 0, 0); \ 111 } while (/* CONSTCOND */ 0) 112 113 /* when a device is the target, this completes a command by running 114 the DATA IN or DATA OUT phase, followed by STATUS phase, followed 115 by the MESSAGE IN phase, followed by a BUS FREE phase: */ 116 #define tme_scsi_device_target_do_dsmf(d, s, m) \ 117 do { \ 118 (d)->tme_scsi_device_status = (s); \ 119 (d)->tme_scsi_device_msg[0] = (m); \ 120 tme_scsi_device_target_dsmf(d, 0, 0); \ 121 } while (/* CONSTCOND */ 0) 122 123 /* types: */ 124 125 /* a SCSI device: */ 126 struct tme_scsi_device { 127 128 /* the mutex protecting the device: */ 129 tme_mutex_t tme_scsi_device_mutex; 130 131 /* backpointer to the device's element: */ 132 struct tme_element *tme_scsi_device_element; 133 134 /* this device's SCSI connection: */ 135 struct tme_scsi_connection *tme_scsi_device_connection; 136 137 /* the callout flags: */ 138 int tme_scsi_device_callout_flags; 139 140 /* the SCSI ID for this device: */ 141 tme_scsi_data_t tme_scsi_device_id; 142 143 /* a mask of SCSI LUNs defined on this device: */ 144 tme_uint32_t tme_scsi_device_luns; 145 146 /* the device vendor, product, and revision strings: */ 147 char *tme_scsi_device_vendor; 148 char *tme_scsi_device_product; 149 char *tme_scsi_device_revision; 150 151 /* the SCSI control signals currently asserted: */ 152 tme_scsi_control_t tme_scsi_device_control; 153 154 /* the current SCSI DMA structure: */ 155 struct tme_scsi_dma tme_scsi_device_dma; 156 157 /* the current addressed LUN, or -1 if no LUN is selected: */ 158 int tme_scsi_device_addressed_lun; 159 160 /* the SCSI message buffer. this buffer is big enough for 161 the largest possible SCSI extended message: */ 162 tme_uint8_t tme_scsi_device_msg[258]; 163 164 /* the SCSI CDB. this buffer is big enough for a Group 4 (16-byte) 165 CDB: */ 166 tme_uint8_t tme_scsi_device_cdb[16]; 167 168 /* the SCSI data buffer. this buffer is big enough for a large 169 MODE SELECT parameter list: */ 170 tme_uint8_t tme_scsi_device_data[256]; 171 172 /* the SCSI status byte: */ 173 tme_uint8_t tme_scsi_device_status; 174 175 /* the SCSI LUN handler: */ 176 int (*tme_scsi_device_address_lun) _TME_P((struct tme_scsi_device *)); 177 178 /* the SCSI sense buffers. these buffers are large enough for a 179 large extended sense: */ 180 /* see section 6.1.3 for details about preserving/clearing sense: */ 181 struct tme_scsi_device_sense { 182 tme_uint8_t tme_scsi_device_sense_data[128]; 183 unsigned int tme_scsi_device_sense_valid; 184 } tme_scsi_device_sense[TME_SCSI_DEVICE_LUN_COUNT]; 185 int tme_scsi_device_sense_no_extended; 186 187 /* the SCSI message handlers. not counting extended messages, there 188 are 129 possible messages (counting all 128 possible IDENTIFY 189 messages as one): */ 190 void (*tme_scsi_device_do_msg[129]) _TME_P((struct tme_scsi_device *, 191 tme_scsi_control_t, 192 tme_scsi_control_t)); 193 void (*tme_scsi_device_do_msg_ext[256]) _TME_P((struct tme_scsi_device *, 194 tme_scsi_control_t, 195 tme_scsi_control_t)); 196 197 /* the SCSI CDB handlers. there are 256 possible commands: */ 198 void (*tme_scsi_device_do_cdb[256]) _TME_P((struct tme_scsi_device *, 199 tme_scsi_control_t, 200 tme_scsi_control_t)); 201 202 /* the generic SCSI phase handler: */ 203 void (*tme_scsi_device_phase) _TME_P((struct tme_scsi_device *, 204 tme_scsi_control_t, 205 tme_scsi_control_t)); 206 }; 207 208 /* prototypes: */ 209 int tme_scsi_device_new _TME_P((struct tme_scsi_device *, int)); 210 void tme_scsi_device_target_phase _TME_P((struct tme_scsi_device *, tme_scsi_control_t)); 211 int tme_scsi_device_connection_make _TME_P((struct tme_connection *, unsigned int)); 212 int tme_scsi_device_connection_break _TME_P((struct tme_connection *, unsigned int)); 213 int tme_scsi_device_connections_new _TME_P((struct tme_element *, _tme_const char * _tme_const *, struct tme_connection **, char **)); 214 _TME_SCSI_DEVICE_PHASE_P(tme_scsi_device_target_f); 215 _TME_SCSI_DEVICE_PHASE_P(tme_scsi_device_target_mf); 216 _TME_SCSI_DEVICE_PHASE_P(tme_scsi_device_target_smf); 217 _TME_SCSI_DEVICE_PHASE_P(tme_scsi_device_target_dsmf); 218 _TME_SCSI_DEVICE_PHASE_P(tme_scsi_device_target_mc); 219 void tme_scsi_device_check_condition _TME_P((struct tme_scsi_device *, tme_uint8_t, tme_uint16_t)); 220 int tme_scsi_device_address_lun_aware _TME_P((struct tme_scsi_device *)); 221 int tme_scsi_device_address_lun_unaware _TME_P((struct tme_scsi_device *)); 222 223 #endif /* !_TME_SCSI_SCSI_DEVICE_H */ 224