1 /* $Id: scsi.h,v 1.4 2007/01/07 23:59:59 fredette Exp $ */ 2 3 /* tme/generic/scsi.h - header file for generic SCSI 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_GENERIC_SCSI_H 37 #define _TME_GENERIC_SCSI_H 38 39 #include <tme/common.h> 40 _TME_RCSID("$Id: scsi.h,v 1.4 2007/01/07 23:59:59 fredette Exp $"); 41 42 /* includes: */ 43 #include <tme/element.h> 44 #include <tme/memory.h> 45 46 /* macros: */ 47 48 /* the SCSI control signals. the parity signals are really data 49 signals, but it's easiest to keep them here: */ 50 #define TME_SCSI_SIGNAL_BSY TME_BIT(0) 51 #define TME_SCSI_SIGNAL_SEL TME_BIT(1) 52 #define TME_SCSI_SIGNAL_C_D TME_BIT(2) 53 #define TME_SCSI_SIGNAL_I_O TME_BIT(3) 54 #define TME_SCSI_SIGNAL_MSG TME_BIT(4) 55 #define TME_SCSI_SIGNAL_REQ TME_BIT(5) 56 #define TME_SCSI_SIGNAL_ACK TME_BIT(6) 57 #define TME_SCSI_SIGNAL_ATN TME_BIT(7) 58 #define TME_SCSI_SIGNAL_RST TME_BIT(8) 59 #define TME_SCSI_SIGNAL_DBP TME_BIT(9) 60 #define TME_SCSI_SIGNAL_DBP1 TME_BIT(10) 61 62 /* this evaluates to nonzero if only one of the bits in mask is set in data: */ 63 #define _TME_SCSI_ID_SET(ids, data) \ 64 (((data) & (ids)) != 0 && (((data) & (ids)) & (((data) & (ids)) - 1)) == 0) 65 66 /* "In all systems, the target shall determine that it is selected 67 when SEL and its SCSI ID bit are true and BSY and I/O are false for 68 at least a bus settle delay." */ 69 #define TME_SCSI_ID_SELECTED(ids, control, data)\ 70 ((((control) \ 71 & (TME_SCSI_SIGNAL_BSY \ 72 | TME_SCSI_SIGNAL_SEL \ 73 | TME_SCSI_SIGNAL_I_O)) \ 74 == TME_SCSI_SIGNAL_SEL) \ 75 && _TME_SCSI_ID_SET(ids, data)) 76 77 /* "The initiator shall determine that it is reselected when SEL, I/O, 78 and its SCSI ID bit are true and BSY is false for at least a bus 79 settle delay." */ 80 #define TME_SCSI_ID_RESELECTED(ids, control, data)\ 81 ((((control) \ 82 & (TME_SCSI_SIGNAL_BSY \ 83 | TME_SCSI_SIGNAL_SEL \ 84 | TME_SCSI_SIGNAL_I_O)) \ 85 == (TME_SCSI_SIGNAL_SEL \ 86 | TME_SCSI_SIGNAL_I_O)) \ 87 && _TME_SCSI_ID_SET(ids, data)) 88 89 /* this gets the current SCSI bus information transfer phase from a 90 set of control signals: */ 91 #define TME_SCSI_PHASE(c) \ 92 ((c) & (TME_SCSI_SIGNAL_MSG \ 93 | TME_SCSI_SIGNAL_C_D \ 94 | TME_SCSI_SIGNAL_I_O)) 95 96 /* the SCSI bus information transfer phases. these are always tied to 97 definite configurations of SCSI control signals after selection: */ 98 #define TME_SCSI_PHASE_DATA_OUT (0) 99 #define TME_SCSI_PHASE_DATA_IN (TME_SCSI_SIGNAL_I_O) 100 #define TME_SCSI_PHASE_COMMAND (TME_SCSI_SIGNAL_C_D) 101 #define TME_SCSI_PHASE_STATUS (TME_SCSI_SIGNAL_C_D \ 102 | TME_SCSI_SIGNAL_I_O) 103 #define TME_SCSI_PHASE_MESSAGE_OUT (TME_SCSI_SIGNAL_MSG \ 104 | TME_SCSI_SIGNAL_C_D) 105 #define TME_SCSI_PHASE_MESSAGE_IN (TME_SCSI_SIGNAL_MSG \ 106 | TME_SCSI_SIGNAL_C_D \ 107 | TME_SCSI_SIGNAL_I_O) 108 109 /* the SCSI DMA flags: */ 110 #define TME_SCSI_DMA_WIDTH (0x03) 111 #define TME_SCSI_DMA_8BIT (0x00) 112 #define TME_SCSI_DMA_16BIT (0x01) 113 #define TME_SCSI_DMA_PARITY (0x04) 114 115 /* the SCSI events: */ 116 #define TME_SCSI_EVENT_NONE (0) 117 #define TME_SCSI_EVENT_IDS_SELF(ids) (ids) 118 #define TME_SCSI_EVENT_IDS_WHICH(event) ((event) & 0xffff) 119 #define TME_SCSI_EVENT_SELECTED (TME_BIT(16)) 120 #define TME_SCSI_EVENT_RESELECTED (TME_BIT(17)) 121 #define TME_SCSI_EVENT_BUS_FREE (TME_BIT(18)) 122 #define TME_SCSI_EVENT_BUS_CHANGE (TME_BIT(19)) 123 #define TME_SCSI_EVENT_BUS_RESET (TME_BIT(20)) 124 125 /* the SCSI actions. these are deliberately ordered such that actions 126 that have to be taken earlier have a larger value than those that 127 have to be taken later: */ 128 #define TME_SCSI_ACTION_NONE (0) 129 #define TME_SCSI_ACTION_ID_SELF(id) ((id) << 0) 130 #define TME_SCSI_ACTION_ID_SELF_WHICH(actions) (((actions) >> 0) & 0xf) 131 #define TME_SCSI_ACTION_ID_OTHER(id) ((id) << 4) 132 #define TME_SCSI_ACTION_ID_OTHER_WHICH(actions) (((actions) >> 4) & 0xf) 133 #define TME_SCSI_ACTION_CYCLE_MARKER (TME_BIT(8)) 134 #define TME_SCSI_ACTION_DMA_INITIATOR (TME_BIT(13)) 135 #define TME_SCSI_ACTION_DMA_INITIATOR_HOLD_ACK (TME_BIT(14) | TME_SCSI_ACTION_DMA_INITIATOR) 136 #define TME_SCSI_ACTION_DMA_TARGET (TME_BIT(15)) 137 #define TME_SCSI_ACTION_RESPOND_SELECTED (TME_BIT(16)) 138 #define TME_SCSI_ACTION_RESPOND_RESELECTED (TME_BIT(17)) 139 #define TME_SCSI_ACTION_SELECT (TME_BIT(18)) 140 #define TME_SCSI_ACTION_SELECT_WITH_ATN (TME_BIT(19) | TME_SCSI_ACTION_SELECT) 141 #define TME_SCSI_ACTION_SELECT_SINGLE_INITIATOR (TME_BIT(20) | TME_SCSI_ACTION_SELECT) 142 #define TME_SCSI_ACTION_RESELECT (TME_BIT(21)) 143 #define TME_SCSI_ACTION_ARBITRATE_HALF (TME_BIT(22)) 144 #define TME_SCSI_ACTION_ARBITRATE_FULL (TME_BIT(23) | TME_SCSI_ACTION_ARBITRATE_HALF) 145 146 /* this evaluates to nonzero if any of the actions in the mask are 147 selected, and no more significant actions are also selected: */ 148 #define TME_SCSI_ACTIONS_SELECTED(actions, actions_mask) \ 149 (((actions) & (actions_mask)) != 0 && (((actions) & ~(actions_mask)) < (actions_mask))) 150 151 /* types: */ 152 153 /* the SCSI control signals: */ 154 typedef tme_uint32_t tme_scsi_control_t; 155 156 /* the SCSI data signals: */ 157 typedef tme_uint32_t tme_scsi_data_t; 158 159 /* a SCSI DMA buffer: */ 160 struct tme_scsi_dma { 161 162 /* the flags: */ 163 unsigned char tme_scsi_dma_flags; 164 165 /* how many bytes remain in the buffer: */ 166 unsigned long tme_scsi_dma_resid; 167 168 /* the input buffer. this is used for an initiator when I/O is 169 true, and for a target when I/O is false: */ 170 tme_uint8_t *tme_scsi_dma_in; 171 172 /* the output buffer. this is used for an initiator when I/O is 173 false, and for a target when I/O is true: */ 174 _tme_const tme_uint8_t *tme_scsi_dma_out; 175 176 /* any synchronous transfer REQ/ACK offset. zero implies 177 asynchronous transfer: */ 178 unsigned short tme_scsi_dma_sync_offset; 179 180 /* any synchronous transfer period, in nanoseconds: */ 181 unsigned short tme_scsi_dma_sync_period; 182 }; 183 184 /* a SCSI connection: */ 185 struct tme_scsi_connection { 186 187 /* the generic connection side: */ 188 struct tme_connection tme_scsi_connection; 189 190 /* this is called for a SCSI bus cycle: */ 191 int (*tme_scsi_connection_cycle) _TME_P((struct tme_scsi_connection *, 192 tme_scsi_control_t, 193 tme_scsi_data_t, 194 tme_uint32_t, 195 tme_uint32_t, 196 const struct tme_scsi_dma *)); 197 }; 198 199 /* prototypes: */ 200 int tme_scsi_connection_score _TME_P((struct tme_connection *, unsigned int *)); 201 int tme_scsi_id_parse _TME_P((const char *)); 202 #define tme_scsi_lun_parse tme_scsi_id_parse 203 204 /* this implements state machines that determine the residual in a 205 SCSI command or message phase: */ 206 tme_uint32_t tme_scsi_phase_resid _TME_P((tme_scsi_control_t, 207 tme_uint32_t *, 208 const tme_shared tme_uint8_t *bytes, 209 unsigned long)); 210 211 #endif /* !_TME_GENERIC_SCSI_H */ 212