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