1 /* $OpenBSD: aacvar.h,v 1.4 2003/10/21 18:58:48 jmc Exp $ */
2
3 /*-
4 * Copyright (c) 2000 Michael Smith
5 * Copyright (c) 2000 BSDi
6 * Copyright (c) 2000 Niklas Hallqvist
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 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $FreeBSD: /c/ncvs/src/sys/dev/aac/aacvar.h,v 1.1 2000/09/13 03:20:34 msmith Exp $
31 */
32
33 /*
34 * This driver would not have rewritten for OpenBSD if it was not for the
35 * hardware donation from Nocom. I want to thank them for their support.
36 * Of course, credit should go to Mike Smith for the original work he did
37 * in the FreeBSD driver where I found lots of inspiration.
38 * - Niklas Hallqvist
39 */
40
41 /* Debugging */
42 #ifdef AAC_DEBUG
43 #define AAC_DPRINTF(mask, args) if (aac_debug & (mask)) printf args
44 #define AAC_D_INTR 0x01
45 #define AAC_D_MISC 0x02
46 #define AAC_D_CMD 0x04
47 #define AAC_D_QUEUE 0x08
48 #define AAC_D_IO 0x10
49 extern int aac_debug;
50
51 #define AAC_PRINT_FIB(sc, fib) aac_print_fib((sc), (fib), __func__)
52 #else
53 #define AAC_DPRINTF(mask, args)
54 #define AAC_PRINT_FIB(sc, fib)
55 #endif
56
57 struct aac_code_lookup {
58 char *string;
59 u_int32_t code;
60 };
61
62 struct aac_softc;
63
64 /*
65 * We allocate a small set of FIBs for the adapter to use to send us messages.
66 */
67 #define AAC_ADAPTER_FIBS 8
68
69 /*
70 * Firmware messages are passed in the printf buffer.
71 */
72 #define AAC_PRINTF_BUFSIZE 256
73
74 /*
75 * We wait this many seconds for the adapter to come ready if it is still
76 * booting.
77 */
78 #define AAC_BOOT_TIMEOUT (3 * 60)
79
80 /*
81 * Wait this long for a lost interrupt to get detected.
82 */
83 #define AAC_WATCH_TIMEOUT 10000 /* 10000 * 1ms = 10s */
84
85 /*
86 * Timeout for immediate commands.
87 */
88 #define AAC_IMMEDIATE_TIMEOUT 30
89
90 /*
91 * Delay 20ms after the qnotify in sync operations. Experimentally deduced.
92 */
93 #define AAC_SYNC_DELAY 20000
94
95 /*
96 * The firmware interface allows for a 16-bit s/g list length. We limit
97 * ourselves to a reasonable maximum and ensure alignment.
98 */
99 #define AAC_MAXSGENTRIES 64 /* max S/G entries, limit 65535 */
100 /*
101 * We gather a number of adapter-visible items into a single structure.
102 *
103 * The ordering of this structure may be important; we copy the Linux driver:
104 *
105 * Adapter FIBs
106 * Init struct
107 * Queue headers (Comm Area)
108 * Printf buffer
109 *
110 * In addition, we add:
111 * Sync Fib
112 */
113 struct aac_common {
114 /* fibs for the controller to send us messages */
115 struct aac_fib ac_fibs[AAC_ADAPTER_FIBS];
116
117 /* the init structure */
118 struct aac_adapter_init ac_init;
119
120 /* arena within which the queue structures are kept */
121 u_int8_t ac_qbuf[sizeof(struct aac_queue_table) + AAC_QUEUE_ALIGN];
122
123 /* buffer for text messages from the controller */
124 char ac_printf[AAC_PRINTF_BUFSIZE];
125
126 /* fib for synchronous commands */
127 struct aac_fib ac_sync_fib;
128 };
129
130 /*
131 * Interface operations
132 */
133 struct aac_interface {
134 int (*aif_get_fwstatus)(struct aac_softc *);
135 void (*aif_qnotify)(struct aac_softc *, int);
136 int (*aif_get_istatus)(struct aac_softc *);
137 void (*aif_set_istatus)(struct aac_softc *, int);
138 void (*aif_set_mailbox)(struct aac_softc *, u_int32_t,
139 u_int32_t, u_int32_t, u_int32_t, u_int32_t);
140 int (*aif_get_mailboxstatus)(struct aac_softc *);
141 void (*aif_set_interrupts)(struct aac_softc *, int);
142 };
143 extern struct aac_interface aac_rx_interface;
144 extern struct aac_interface aac_sa_interface;
145
146 #define AAC_GET_FWSTATUS(sc) ((sc)->sc_if.aif_get_fwstatus(sc))
147 #define AAC_QNOTIFY(sc, qbit) \
148 ((sc)->sc_if.aif_qnotify((sc), (qbit)))
149 #define AAC_GET_ISTATUS(sc) ((sc)->sc_if.aif_get_istatus(sc))
150 #define AAC_CLEAR_ISTATUS(sc, mask) \
151 ((sc)->sc_if.aif_set_istatus((sc), (mask)))
152 #define AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3) \
153 do { \
154 ((sc)->sc_if.aif_set_mailbox((sc), (command), (arg0), \
155 (arg1), (arg2), (arg3))); \
156 } while(0)
157 #define AAC_GET_MAILBOXSTATUS(sc) \
158 ((sc)->sc_if.aif_get_mailboxstatus(sc))
159 #define AAC_MASK_INTERRUPTS(sc) \
160 ((sc)->sc_if.aif_set_interrupts((sc), 0))
161 #define AAC_UNMASK_INTERRUPTS(sc) \
162 ((sc)->sc_if.aif_set_interrupts((sc), 1))
163
164 #define AAC_SETREG4(sc, reg, val) \
165 bus_space_write_4((sc)->sc_memt, (sc)->sc_memh, (reg), (val))
166 #define AAC_GETREG4(sc, reg) \
167 bus_space_read_4((sc)->sc_memt, (sc)->sc_memh, (reg))
168 #define AAC_SETREG2(sc, reg, val) \
169 bus_space_write_2((sc)->sc_memt, (sc)->sc_memh, (reg), (val))
170 #define AAC_GETREG2(sc, reg) \
171 bus_space_read_2((sc)->sc_memt, (sc)->sc_memh, (reg))
172 #define AAC_SETREG1(sc, reg, val) \
173 bus_space_write_1((sc)->sc_memt, (sc)->sc_memh, (reg), (val))
174 #define AAC_GETREG1(sc, reg) \
175 bus_space_read_1((sc)->sc_memt, (sc)->sc_memh, (reg))
176
177 /*
178 * Per-container data structure
179 */
180 struct aac_container
181 {
182 struct aac_mntobj co_mntobj;
183 struct device co_disk;
184 };
185
186 /*
187 * A command contol block, one for each corresponding command index of the
188 * controller.
189 */
190 struct aac_ccb {
191 TAILQ_ENTRY(aac_ccb) ac_chain;
192 struct scsi_xfer *ac_xs;
193 struct aac_fib *ac_fib; /* FIB associated with this command */
194 bus_addr_t ac_fibphys; /* bus address of the FIB */
195 bus_dmamap_t ac_dmamap_xfer;
196 struct aac_sg_table *ac_sgtable;/* pointer to s/g table in command */
197 int ac_timeout;
198 u_int32_t ac_blockno;
199 u_int32_t ac_blockcnt;
200 u_int8_t ac_flags;
201 #define AAC_ACF_WATCHDOG 0x1
202 #define AAC_ACF_COMPLETED 0x2
203 };
204
205 /*
206 * Per-controller structure.
207 */
208 struct aac_softc {
209 struct device sc_dev;
210 void *sc_ih;
211 struct scsi_link sc_link; /* Virtual SCSI bus for cache devs */
212
213 bus_space_tag_t sc_memt;
214 bus_space_handle_t sc_memh;
215 bus_dma_tag_t sc_dmat; /* parent DMA tag */
216
217 /* controller features, limits and status */
218 int sc_state;
219 #define AAC_STATE_SUSPEND (1<<0)
220 #define AAC_STATE_OPEN (1<<1)
221 #define AAC_STATE_INTERRUPTS_ON (1<<2)
222 #define AAC_STATE_AIF_SLEEPER (1<<3)
223 struct FsaRevision sc_revision;
224
225 int sc_hwif; /* controller hardware interface */
226 #define AAC_HWIF_I960RX 0
227 #define AAC_HWIF_STRONGARM 1
228
229 struct aac_common *sc_common;
230 u_int32_t sc_common_busaddr;
231 struct aac_interface sc_if;
232
233 /* XXX This should really be dynamic. It is very wasteful now. */
234 struct aac_ccb sc_ccbs[AAC_ADAP_NORM_CMD_ENTRIES];
235 TAILQ_HEAD(, aac_ccb) sc_free_ccb, sc_ccbq;
236 /* commands on hold for controller resources */
237 TAILQ_HEAD(, aac_ccb) sc_ready;
238 /* commands which have been returned by the controller */
239 TAILQ_HEAD(, aac_ccb) sc_completed;
240 LIST_HEAD(, scsi_xfer) sc_queue;
241 struct scsi_xfer *sc_queuelast;
242
243 /* command management */
244 struct aac_queue_table *sc_queues;
245 struct aac_queue_entry *sc_qentries[AAC_QUEUE_COUNT];
246
247 struct {
248 u_int8_t hd_present;
249 u_int8_t hd_is_logdrv;
250 u_int8_t hd_is_arraydrv;
251 u_int8_t hd_is_master;
252 u_int8_t hd_is_parity;
253 u_int8_t hd_is_hotfix;
254 u_int8_t hd_master_no;
255 u_int8_t hd_lock;
256 u_int8_t hd_heads;
257 u_int8_t hd_secs;
258 u_int16_t hd_devtype;
259 u_int32_t hd_size;
260 u_int8_t hd_ldr_no;
261 u_int8_t hd_rw_attribs;
262 u_int32_t hd_start_sec;
263 } sc_hdr[AAC_MAX_CONTAINERS];
264 };
265
266 /* XXX These have to become spinlocks in case of SMP */
267 #define AAC_LOCK(sc) splbio()
268 #define AAC_UNLOCK(sc, lock) splx(lock)
269 typedef int aac_lock_t;
270
271 void aacminphys(struct buf *);
272 int aac_attach(struct aac_softc *);
273 int aac_intr(void *);
274
275 #ifdef __GNUC__
276 /* These all require correctly aligned buffers */
277 static __inline__ void aac_enc16(u_int8_t *, u_int16_t);
278 static __inline__ void aac_enc32(u_int8_t *, u_int32_t);
279 static __inline__ u_int16_t aac_dec16(u_int8_t *);
280 static __inline__ u_int32_t aac_dec32(u_int8_t *);
281
282 static __inline__ void
aac_enc16(addr,value)283 aac_enc16(addr, value)
284 u_int8_t *addr;
285 u_int16_t value;
286 {
287 *(u_int16_t *)addr = htole16(value);
288 }
289
290 static __inline__ void
aac_enc32(addr,value)291 aac_enc32(addr, value)
292 u_int8_t *addr;
293 u_int32_t value;
294 {
295 *(u_int32_t *)addr = htole32(value);
296 }
297
298 static __inline__ u_int16_t
aac_dec16(addr)299 aac_dec16(addr)
300 u_int8_t *addr;
301 {
302 return letoh16(*(u_int16_t *)addr);
303 }
304
305 static __inline__ u_int32_t
aac_dec32(addr)306 aac_dec32(addr)
307 u_int8_t *addr;
308 {
309 return letoh32(*(u_int32_t *)addr);
310 }
311
312 /*
313 * Queue primitives
314 *
315 * These are broken out individually to make statistics gathering easier.
316 */
317
318 static __inline__ void
aac_enqueue_completed(struct aac_ccb * ccb)319 aac_enqueue_completed(struct aac_ccb *ccb)
320 {
321 struct aac_softc *sc = ccb->ac_xs->sc_link->adapter_softc;
322 aac_lock_t lock;
323
324 lock = AAC_LOCK(sc);
325 TAILQ_INSERT_TAIL(&sc->sc_completed, ccb, ac_chain);
326 AAC_UNLOCK(sc, lock);
327 }
328
329 static __inline__ struct aac_ccb *
aac_dequeue_completed(struct aac_softc * sc)330 aac_dequeue_completed(struct aac_softc *sc)
331 {
332 struct aac_ccb *ccb;
333 aac_lock_t lock;
334
335 lock = AAC_LOCK(sc);
336 if ((ccb = TAILQ_FIRST(&sc->sc_completed)) != NULL)
337 TAILQ_REMOVE(&sc->sc_completed, ccb, ac_chain);
338 AAC_UNLOCK(sc, lock);
339 return (ccb);
340 }
341 #endif
342