aac.c revision 1.21.2.3 1 1.21.2.3 yamt /* $NetBSD: aac.c,v 1.21.2.3 2007/09/03 14:34:09 yamt Exp $ */
2 1.1 ad
3 1.1 ad /*-
4 1.21.2.3 yamt * Copyright (c) 2002, 2007 The NetBSD Foundation, Inc.
5 1.1 ad * All rights reserved.
6 1.1 ad *
7 1.1 ad * This code is derived from software contributed to The NetBSD Foundation
8 1.1 ad * by Andrew Doran.
9 1.1 ad *
10 1.1 ad * Redistribution and use in source and binary forms, with or without
11 1.1 ad * modification, are permitted provided that the following conditions
12 1.1 ad * are met:
13 1.1 ad * 1. Redistributions of source code must retain the above copyright
14 1.1 ad * notice, this list of conditions and the following disclaimer.
15 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 ad * notice, this list of conditions and the following disclaimer in the
17 1.1 ad * documentation and/or other materials provided with the distribution.
18 1.1 ad * 3. All advertising materials mentioning features or use of this software
19 1.1 ad * must display the following acknowledgement:
20 1.1 ad * This product includes software developed by the NetBSD
21 1.1 ad * Foundation, Inc. and its contributors.
22 1.1 ad * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 ad * contributors may be used to endorse or promote products derived
24 1.1 ad * from this software without specific prior written permission.
25 1.1 ad *
26 1.1 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 ad * POSSIBILITY OF SUCH DAMAGE.
37 1.1 ad */
38 1.1 ad
39 1.1 ad /*-
40 1.1 ad * Copyright (c) 2001 Scott Long
41 1.1 ad * Copyright (c) 2001 Adaptec, Inc.
42 1.1 ad * Copyright (c) 2000 Michael Smith
43 1.1 ad * Copyright (c) 2000 BSDi
44 1.1 ad * Copyright (c) 2000 Niklas Hallqvist
45 1.1 ad * All rights reserved.
46 1.1 ad *
47 1.1 ad * Redistribution and use in source and binary forms, with or without
48 1.1 ad * modification, are permitted provided that the following conditions
49 1.1 ad * are met:
50 1.1 ad * 1. Redistributions of source code must retain the above copyright
51 1.1 ad * notice, this list of conditions and the following disclaimer.
52 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright
53 1.1 ad * notice, this list of conditions and the following disclaimer in the
54 1.1 ad * documentation and/or other materials provided with the distribution.
55 1.1 ad *
56 1.1 ad * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
57 1.1 ad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 1.1 ad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 1.1 ad * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
60 1.1 ad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 1.1 ad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 1.1 ad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 1.1 ad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 1.1 ad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 1.1 ad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 1.1 ad * SUCH DAMAGE.
67 1.1 ad */
68 1.1 ad
69 1.1 ad /*
70 1.1 ad * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
71 1.1 ad *
72 1.1 ad * TODO:
73 1.1 ad *
74 1.1 ad * o Management interface.
75 1.1 ad * o Look again at some of the portability issues.
76 1.1 ad * o Handle various AIFs (e.g., notification that a container is going away).
77 1.1 ad */
78 1.1 ad
79 1.1 ad #include <sys/cdefs.h>
80 1.21.2.3 yamt __KERNEL_RCSID(0, "$NetBSD: aac.c,v 1.21.2.3 2007/09/03 14:34:09 yamt Exp $");
81 1.1 ad
82 1.1 ad #include <sys/param.h>
83 1.1 ad #include <sys/systm.h>
84 1.1 ad #include <sys/buf.h>
85 1.1 ad #include <sys/device.h>
86 1.1 ad #include <sys/kernel.h>
87 1.1 ad #include <sys/malloc.h>
88 1.21.2.3 yamt #include <sys/proc.h>
89 1.1 ad
90 1.1 ad #include <machine/bus.h>
91 1.1 ad
92 1.1 ad #include <uvm/uvm_extern.h>
93 1.1 ad
94 1.1 ad #include <dev/ic/aacreg.h>
95 1.1 ad #include <dev/ic/aacvar.h>
96 1.1 ad #include <dev/ic/aac_tables.h>
97 1.1 ad
98 1.13 drochner #include "locators.h"
99 1.13 drochner
100 1.21.2.3 yamt static int aac_new_intr(void *);
101 1.21.2.3 yamt static int aac_alloc_commands(struct aac_softc *);
102 1.21.2.3 yamt #ifdef notyet
103 1.21.2.3 yamt static void aac_free_commands(struct aac_softc *);
104 1.21.2.3 yamt #endif
105 1.12 thorpej static int aac_check_firmware(struct aac_softc *);
106 1.12 thorpej static void aac_describe_controller(struct aac_softc *);
107 1.12 thorpej static int aac_dequeue_fib(struct aac_softc *, int, u_int32_t *,
108 1.12 thorpej struct aac_fib **);
109 1.21.2.3 yamt static int aac_enqueue_fib(struct aac_softc *, int, struct aac_ccb *);
110 1.21.2.3 yamt static int aac_enqueue_response(struct aac_softc *, int, struct aac_fib *);
111 1.12 thorpej static void aac_host_command(struct aac_softc *);
112 1.12 thorpej static void aac_host_response(struct aac_softc *);
113 1.12 thorpej static int aac_init(struct aac_softc *);
114 1.12 thorpej static int aac_print(void *, const char *);
115 1.12 thorpej static void aac_shutdown(void *);
116 1.12 thorpej static void aac_startup(struct aac_softc *);
117 1.12 thorpej static int aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
118 1.12 thorpej u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
119 1.12 thorpej static int aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *,
120 1.12 thorpej u_int16_t, void *, u_int16_t *);
121 1.1 ad
122 1.1 ad #ifdef AAC_DEBUG
123 1.21.2.1 yamt static void aac_print_fib(struct aac_softc *, struct aac_fib *, const char *);
124 1.1 ad #endif
125 1.1 ad
126 1.1 ad /*
127 1.1 ad * Adapter-space FIB queue manipulation.
128 1.1 ad *
129 1.1 ad * Note that the queue implementation here is a little funky; neither the PI or
130 1.1 ad * CI will ever be zero. This behaviour is a controller feature.
131 1.1 ad */
132 1.1 ad static struct {
133 1.1 ad int size;
134 1.1 ad int notify;
135 1.1 ad } const aac_qinfo[] = {
136 1.1 ad { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
137 1.1 ad { AAC_HOST_HIGH_CMD_ENTRIES, 0 },
138 1.1 ad { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
139 1.1 ad { AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
140 1.1 ad { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
141 1.1 ad { AAC_HOST_HIGH_RESP_ENTRIES, 0 },
142 1.1 ad { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
143 1.1 ad { AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
144 1.1 ad };
145 1.1 ad
146 1.1 ad #ifdef AAC_DEBUG
147 1.1 ad int aac_debug = AAC_DEBUG;
148 1.1 ad #endif
149 1.1 ad
150 1.21.2.3 yamt MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for aac(4)");
151 1.21.2.3 yamt
152 1.12 thorpej static void *aac_sdh;
153 1.1 ad
154 1.1 ad extern struct cfdriver aac_cd;
155 1.1 ad
156 1.1 ad int
157 1.1 ad aac_attach(struct aac_softc *sc)
158 1.1 ad {
159 1.1 ad struct aac_attach_args aaca;
160 1.21.2.3 yamt int i, rv;
161 1.21.2.1 yamt int locs[AACCF_NLOCS];
162 1.1 ad
163 1.1 ad SIMPLEQ_INIT(&sc->sc_ccb_free);
164 1.1 ad SIMPLEQ_INIT(&sc->sc_ccb_queue);
165 1.1 ad SIMPLEQ_INIT(&sc->sc_ccb_complete);
166 1.1 ad
167 1.1 ad /*
168 1.1 ad * Disable interrupts before we do anything.
169 1.1 ad */
170 1.1 ad AAC_MASK_INTERRUPTS(sc);
171 1.1 ad
172 1.1 ad /*
173 1.1 ad * Initialise the adapter.
174 1.1 ad */
175 1.1 ad if (aac_check_firmware(sc))
176 1.1 ad return (EINVAL);
177 1.1 ad
178 1.1 ad if ((rv = aac_init(sc)) != 0)
179 1.1 ad return (rv);
180 1.21.2.3 yamt
181 1.21.2.3 yamt if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
182 1.21.2.3 yamt rv = sc->sc_intr_set(sc, aac_new_intr, sc);
183 1.21.2.3 yamt if (rv)
184 1.21.2.3 yamt return (rv);
185 1.21.2.3 yamt }
186 1.21.2.3 yamt
187 1.1 ad aac_startup(sc);
188 1.1 ad
189 1.16 perry /*
190 1.1 ad * Print a little information about the controller.
191 1.1 ad */
192 1.1 ad aac_describe_controller(sc);
193 1.1 ad
194 1.1 ad /*
195 1.21.2.3 yamt * Attach devices.
196 1.1 ad */
197 1.21.2.3 yamt for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
198 1.21.2.3 yamt if (!sc->sc_hdr[i].hd_present)
199 1.21.2.3 yamt continue;
200 1.21.2.3 yamt aaca.aaca_unit = i;
201 1.21.2.3 yamt
202 1.21.2.3 yamt locs[AACCF_UNIT] = i;
203 1.21.2.3 yamt
204 1.21.2.3 yamt config_found_sm_loc(&sc->sc_dv, "aac", locs, &aaca,
205 1.21.2.3 yamt aac_print, config_stdsubmatch);
206 1.1 ad }
207 1.1 ad
208 1.21.2.3 yamt /*
209 1.21.2.3 yamt * Enable interrupts, and register our shutdown hook.
210 1.21.2.3 yamt */
211 1.21.2.3 yamt sc->sc_flags |= AAC_ONLINE;
212 1.21.2.3 yamt AAC_UNMASK_INTERRUPTS(sc);
213 1.21.2.3 yamt if (aac_sdh != NULL)
214 1.21.2.3 yamt shutdownhook_establish(aac_shutdown, NULL);
215 1.21.2.3 yamt return (0);
216 1.21.2.3 yamt }
217 1.21.2.3 yamt
218 1.21.2.3 yamt static int
219 1.21.2.3 yamt aac_alloc_commands(struct aac_softc *sc)
220 1.21.2.3 yamt {
221 1.21.2.3 yamt struct aac_fibmap *fm;
222 1.21.2.3 yamt struct aac_ccb *ac;
223 1.21.2.3 yamt bus_addr_t fibpa;
224 1.21.2.3 yamt int size, nsegs;
225 1.21.2.3 yamt int i, error;
226 1.21.2.3 yamt int state;
227 1.21.2.3 yamt
228 1.21.2.3 yamt if (sc->sc_total_fibs + sc->sc_max_fibs_alloc > sc->sc_max_fibs)
229 1.21.2.3 yamt return ENOMEM;
230 1.21.2.3 yamt
231 1.21.2.3 yamt fm = malloc(sizeof(struct aac_fibmap), M_AACBUF, M_NOWAIT|M_ZERO);
232 1.21.2.3 yamt if (fm == NULL)
233 1.21.2.3 yamt return ENOMEM;
234 1.21.2.3 yamt
235 1.21.2.3 yamt size = sc->sc_max_fibs_alloc * sc->sc_max_fib_size;
236 1.21.2.3 yamt
237 1.21.2.3 yamt state = 0;
238 1.21.2.3 yamt error = bus_dmamap_create(sc->sc_dmat, size, 1, size,
239 1.21.2.3 yamt 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &fm->fm_fibmap);
240 1.21.2.3 yamt if (error != 0) {
241 1.21.2.3 yamt aprint_error("%s: cannot create fibs dmamap (%d)\n",
242 1.21.2.3 yamt sc->sc_dv.dv_xname, error);
243 1.1 ad goto bail_out;
244 1.1 ad }
245 1.1 ad state++;
246 1.21.2.3 yamt error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
247 1.21.2.3 yamt &fm->fm_fibseg, 1, &nsegs, BUS_DMA_NOWAIT);
248 1.21.2.3 yamt if (error != 0) {
249 1.21.2.3 yamt aprint_error("%s: can't allocate fibs structure (%d)\n",
250 1.21.2.3 yamt sc->sc_dv.dv_xname, error);
251 1.1 ad goto bail_out;
252 1.1 ad }
253 1.1 ad state++;
254 1.21.2.3 yamt error = bus_dmamem_map(sc->sc_dmat, &fm->fm_fibseg, nsegs, size,
255 1.21.2.3 yamt (void **)&fm->fm_fibs, 0);
256 1.21.2.3 yamt if (error != 0) {
257 1.21.2.3 yamt aprint_error("%s: can't map fibs structure (%d)\n",
258 1.21.2.3 yamt sc->sc_dv.dv_xname, error);
259 1.1 ad goto bail_out;
260 1.1 ad }
261 1.1 ad state++;
262 1.21.2.3 yamt error = bus_dmamap_load(sc->sc_dmat, fm->fm_fibmap, fm->fm_fibs,
263 1.21.2.3 yamt size, NULL, BUS_DMA_NOWAIT);
264 1.21.2.3 yamt if (error != 0) {
265 1.21.2.3 yamt aprint_error("%s: cannot load fibs dmamap (%d)\n",
266 1.21.2.3 yamt sc->sc_dv.dv_xname, error);
267 1.1 ad goto bail_out;
268 1.1 ad }
269 1.1 ad
270 1.21.2.3 yamt fm->fm_ccbs = sc->sc_ccbs + sc->sc_total_fibs;
271 1.21.2.3 yamt fibpa = fm->fm_fibseg.ds_addr;
272 1.21.2.3 yamt
273 1.21.2.3 yamt memset(fm->fm_fibs, 0, size);
274 1.21.2.3 yamt for (i = 0; i < sc->sc_max_fibs_alloc; i++) {
275 1.21.2.3 yamt ac = fm->fm_ccbs + i;
276 1.21.2.3 yamt
277 1.21.2.3 yamt error = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER(sc),
278 1.21.2.3 yamt sc->sc_max_sgs, AAC_MAX_XFER(sc), 0,
279 1.1 ad BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer);
280 1.21.2.3 yamt if (error) {
281 1.21.2.3 yamt while (--i >= 0) {
282 1.21.2.3 yamt ac = fm->fm_ccbs + i;
283 1.1 ad bus_dmamap_destroy(sc->sc_dmat,
284 1.1 ad ac->ac_dmamap_xfer);
285 1.21.2.3 yamt sc->sc_total_fibs--;
286 1.21.2.3 yamt }
287 1.8 thorpej aprint_error("%s: cannot create ccb dmamap (%d)",
288 1.21.2.3 yamt sc->sc_dv.dv_xname, error);
289 1.1 ad goto bail_out;
290 1.1 ad }
291 1.1 ad
292 1.21.2.3 yamt ac->ac_fibmap = fm;
293 1.21.2.3 yamt ac->ac_fib = (struct aac_fib *)
294 1.21.2.3 yamt ((char *) fm->fm_fibs + i * sc->sc_max_fib_size);
295 1.21.2.3 yamt ac->ac_fibphys = fibpa + i * sc->sc_max_fib_size;
296 1.1 ad aac_ccb_free(sc, ac);
297 1.21.2.3 yamt sc->sc_total_fibs++;
298 1.1 ad }
299 1.1 ad
300 1.21.2.3 yamt TAILQ_INSERT_TAIL(&sc->sc_fibmap_tqh, fm, fm_link);
301 1.13 drochner
302 1.21.2.3 yamt return 0;
303 1.21.2.3 yamt bail_out:
304 1.21.2.3 yamt if (state > 3)
305 1.21.2.3 yamt bus_dmamap_unload(sc->sc_dmat, fm->fm_fibmap);
306 1.21.2.3 yamt if (state > 2)
307 1.21.2.3 yamt bus_dmamem_unmap(sc->sc_dmat, (void *) fm->fm_fibs, size);
308 1.21.2.3 yamt if (state > 1)
309 1.21.2.3 yamt bus_dmamem_free(sc->sc_dmat, &fm->fm_fibseg, 1);
310 1.1 ad
311 1.21.2.3 yamt bus_dmamap_destroy(sc->sc_dmat, fm->fm_fibmap);
312 1.1 ad
313 1.21.2.3 yamt free(fm, M_AACBUF);
314 1.1 ad
315 1.21.2.3 yamt return error;
316 1.21.2.3 yamt }
317 1.1 ad
318 1.21.2.3 yamt #ifdef notyet
319 1.21.2.3 yamt static void
320 1.21.2.3 yamt aac_free_commands(struct aac_softc *sc)
321 1.21.2.3 yamt {
322 1.1 ad }
323 1.21.2.3 yamt #endif
324 1.1 ad
325 1.1 ad /*
326 1.1 ad * Print autoconfiguration message for a sub-device.
327 1.1 ad */
328 1.12 thorpej static int
329 1.1 ad aac_print(void *aux, const char *pnp)
330 1.1 ad {
331 1.1 ad struct aac_attach_args *aaca;
332 1.1 ad
333 1.1 ad aaca = aux;
334 1.1 ad
335 1.1 ad if (pnp != NULL)
336 1.7 thorpej aprint_normal("block device at %s", pnp);
337 1.7 thorpej aprint_normal(" unit %d", aaca->aaca_unit);
338 1.1 ad return (UNCONF);
339 1.1 ad }
340 1.1 ad
341 1.1 ad /*
342 1.1 ad * Look up a text description of a numeric error code and return a pointer to
343 1.1 ad * same.
344 1.1 ad */
345 1.1 ad const char *
346 1.1 ad aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
347 1.1 ad {
348 1.1 ad int i;
349 1.1 ad
350 1.1 ad for (i = 0; table[i].string != NULL; i++)
351 1.1 ad if (table[i].code == code)
352 1.1 ad return (table[i].string);
353 1.1 ad
354 1.1 ad return (table[i + 1].string);
355 1.1 ad }
356 1.1 ad
357 1.17 briggs /*
358 1.17 briggs * bitmask_snprintf(9) format string for the adapter options.
359 1.17 briggs */
360 1.19 christos static const char *optfmt =
361 1.17 briggs "\20\1SNAPSHOT\2CLUSTERS\3WCACHE\4DATA64\5HOSTTIME\6RAID50"
362 1.17 briggs "\7WINDOW4GB"
363 1.17 briggs "\10SCSIUPGD\11SOFTERR\12NORECOND\13SGMAP64\14ALARM\15NONDASD";
364 1.17 briggs
365 1.12 thorpej static void
366 1.1 ad aac_describe_controller(struct aac_softc *sc)
367 1.1 ad {
368 1.17 briggs u_int8_t fmtbuf[256];
369 1.19 christos u_int8_t tbuf[AAC_FIB_DATASIZE];
370 1.1 ad u_int16_t bufsize;
371 1.1 ad struct aac_adapter_info *info;
372 1.1 ad u_int8_t arg;
373 1.1 ad
374 1.1 ad arg = 0;
375 1.19 christos if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &tbuf,
376 1.1 ad &bufsize)) {
377 1.8 thorpej aprint_error("%s: RequestAdapterInfo failed\n",
378 1.8 thorpej sc->sc_dv.dv_xname);
379 1.1 ad return;
380 1.1 ad }
381 1.1 ad if (bufsize != sizeof(*info)) {
382 1.8 thorpej aprint_error("%s: "
383 1.21.2.1 yamt "RequestAdapterInfo returned wrong data size (%d != %zu)\n",
384 1.21.2.1 yamt sc->sc_dv.dv_xname, bufsize, sizeof(*info));
385 1.1 ad return;
386 1.1 ad }
387 1.19 christos info = (struct aac_adapter_info *)&tbuf[0];
388 1.1 ad
389 1.15 briggs aprint_normal("%s: %s at %dMHz, %dMB mem (%dMB cache), %s\n",
390 1.1 ad sc->sc_dv.dv_xname,
391 1.1 ad aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)),
392 1.1 ad le32toh(info->ClockSpeed),
393 1.15 briggs le32toh(info->TotalMem) / (1024 * 1024),
394 1.1 ad le32toh(info->BufferMem) / (1024 * 1024),
395 1.1 ad aac_describe_code(aac_battery_platform,
396 1.15 briggs le32toh(info->batteryPlatform)));
397 1.15 briggs
398 1.15 briggs aprint_verbose("%s: Kernel %d.%d-%d [Build %d], ",
399 1.15 briggs sc->sc_dv.dv_xname,
400 1.1 ad info->KernelRevision.external.comp.major,
401 1.1 ad info->KernelRevision.external.comp.minor,
402 1.15 briggs info->KernelRevision.external.comp.dash,
403 1.15 briggs info->KernelRevision.buildNumber);
404 1.15 briggs
405 1.15 briggs aprint_verbose("Monitor %d.%d-%d [Build %d], S/N %6X\n",
406 1.15 briggs info->MonitorRevision.external.comp.major,
407 1.15 briggs info->MonitorRevision.external.comp.minor,
408 1.15 briggs info->MonitorRevision.external.comp.dash,
409 1.15 briggs info->MonitorRevision.buildNumber,
410 1.15 briggs ((u_int32_t)info->SerialNumber & 0xffffff));
411 1.1 ad
412 1.17 briggs aprint_verbose("%s: Controller supports: %s\n",
413 1.17 briggs sc->sc_dv.dv_xname,
414 1.17 briggs bitmask_snprintf(sc->sc_supported_options, optfmt, fmtbuf,
415 1.17 briggs sizeof(fmtbuf)));
416 1.17 briggs
417 1.1 ad /* Save the kernel revision structure for later use. */
418 1.1 ad sc->sc_revision = info->KernelRevision;
419 1.1 ad }
420 1.1 ad
421 1.1 ad /*
422 1.1 ad * Retrieve the firmware version numbers. Dell PERC2/QC cards with firmware
423 1.1 ad * version 1.x are not compatible with this driver.
424 1.1 ad */
425 1.12 thorpej static int
426 1.1 ad aac_check_firmware(struct aac_softc *sc)
427 1.1 ad {
428 1.21.2.3 yamt u_int32_t major, minor, opts, atusize = 0, status = 0;
429 1.21.2.3 yamt u_int32_t calcsgs;
430 1.1 ad
431 1.1 ad if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) {
432 1.1 ad if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
433 1.1 ad NULL)) {
434 1.8 thorpej aprint_error("%s: error reading firmware version\n",
435 1.1 ad sc->sc_dv.dv_xname);
436 1.1 ad return (1);
437 1.1 ad }
438 1.1 ad
439 1.1 ad /* These numbers are stored as ASCII! */
440 1.17 briggs major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
441 1.17 briggs minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
442 1.1 ad if (major == 1) {
443 1.8 thorpej aprint_error(
444 1.8 thorpej "%s: firmware version %d.%d not supported.\n",
445 1.1 ad sc->sc_dv.dv_xname, major, minor);
446 1.1 ad return (1);
447 1.1 ad }
448 1.1 ad }
449 1.1 ad
450 1.21.2.3 yamt if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status)) {
451 1.21.2.3 yamt if (status != AAC_SRB_STS_INVALID_REQUEST) {
452 1.21.2.3 yamt aprint_error("%s: GETINFO failed, status 0x%08x\n",
453 1.21.2.3 yamt sc->sc_dv.dv_xname, status);
454 1.21.2.3 yamt return (1);
455 1.21.2.3 yamt }
456 1.21.2.3 yamt } else {
457 1.21.2.3 yamt opts = AAC_GET_MAILBOX(sc, 1);
458 1.21.2.3 yamt atusize = AAC_GET_MAILBOX(sc, 2);
459 1.21.2.3 yamt sc->sc_supported_options = opts;
460 1.21.2.3 yamt
461 1.21.2.3 yamt if (((opts & AAC_SUPPORTED_4GB_WINDOW) != 0) &&
462 1.21.2.3 yamt ((sc->sc_quirks & AAC_QUIRK_NO4GB) == 0) )
463 1.21.2.3 yamt sc->sc_quirks |= AAC_QUIRK_4GB_WINDOW;
464 1.21.2.3 yamt
465 1.21.2.3 yamt if (((opts & AAC_SUPPORTED_SGMAP_HOST64) != 0) &&
466 1.21.2.3 yamt (sizeof(bus_addr_t) > 4)) {
467 1.21.2.3 yamt aprint_normal("%s: Enabling 64-bit address support\n",
468 1.21.2.3 yamt sc->sc_dv.dv_xname);
469 1.21.2.3 yamt sc->sc_quirks |= AAC_QUIRK_SG_64BIT;
470 1.21.2.3 yamt }
471 1.21.2.3 yamt if ((opts & AAC_SUPPORTED_NEW_COMM) &&
472 1.21.2.3 yamt (sc->sc_if.aif_send_command != NULL)) {
473 1.21.2.3 yamt sc->sc_quirks |= AAC_QUIRK_NEW_COMM;
474 1.21.2.3 yamt }
475 1.21.2.3 yamt #ifdef notyet
476 1.21.2.3 yamt if (opts & AAC_SUPPORTED_64BIT_ARRAYSIZE)
477 1.21.2.3 yamt sc->sc_quirks |= AAC_QUIRK_ARRAY_64BIT;
478 1.21.2.3 yamt #endif
479 1.21.2.3 yamt }
480 1.21.2.3 yamt
481 1.21.2.3 yamt sc->sc_max_fibs = (sc->sc_quirks & AAC_QUIRK_256FIBS) ? 256 : 512;
482 1.21.2.3 yamt
483 1.21.2.3 yamt if ( (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
484 1.21.2.3 yamt && (sc->sc_regsize < atusize)) {
485 1.21.2.3 yamt aprint_error("%s: Not enabling new comm i/f -- "
486 1.21.2.3 yamt "atusize 0x%08x, regsize 0x%08x\n",
487 1.21.2.3 yamt sc->sc_dv.dv_xname, atusize,
488 1.21.2.3 yamt (u_int32_t) sc->sc_regsize);
489 1.21.2.3 yamt sc->sc_quirks &= ~AAC_QUIRK_NEW_COMM;
490 1.21.2.3 yamt }
491 1.21.2.3 yamt #if 0
492 1.21.2.3 yamt if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
493 1.21.2.3 yamt aprint_error("%s: Not enabling new comm i/f -- "
494 1.21.2.3 yamt "driver not ready yet\n",
495 1.21.2.3 yamt sc->sc_dv.dv_xname);
496 1.21.2.3 yamt sc->sc_quirks &= ~AAC_QUIRK_NEW_COMM;
497 1.17 briggs }
498 1.21.2.3 yamt #endif
499 1.17 briggs
500 1.21.2.3 yamt sc->sc_max_fib_size = sizeof(struct aac_fib);
501 1.21.2.3 yamt sc->sc_max_sectors = 128; /* 64KB */
502 1.21.2.3 yamt if (sc->sc_quirks & AAC_QUIRK_SG_64BIT)
503 1.21.2.3 yamt sc->sc_max_sgs = (sc->sc_max_fib_size
504 1.21.2.3 yamt - sizeof(struct aac_blockwrite64)
505 1.21.2.3 yamt + sizeof(struct aac_sg_table64))
506 1.21.2.3 yamt / sizeof(struct aac_sg_table64);
507 1.21.2.3 yamt else
508 1.21.2.3 yamt sc->sc_max_sgs = (sc->sc_max_fib_size
509 1.21.2.3 yamt - sizeof(struct aac_blockwrite)
510 1.21.2.3 yamt + sizeof(struct aac_sg_table))
511 1.21.2.3 yamt / sizeof(struct aac_sg_table);
512 1.21.2.3 yamt
513 1.21.2.3 yamt if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) {
514 1.21.2.3 yamt u_int32_t opt1, opt2, opt3;
515 1.21.2.3 yamt u_int32_t tmpval;
516 1.21.2.3 yamt
517 1.21.2.3 yamt opt1 = AAC_GET_MAILBOX(sc, 1);
518 1.21.2.3 yamt opt2 = AAC_GET_MAILBOX(sc, 2);
519 1.21.2.3 yamt opt3 = AAC_GET_MAILBOX(sc, 3);
520 1.21.2.3 yamt if (!opt1 || !opt2 || !opt3) {
521 1.21.2.3 yamt aprint_verbose("%s: GETCOMMPREF appears untrustworthy."
522 1.21.2.3 yamt " Ignoring.\n", sc->sc_dv.dv_xname);
523 1.21.2.3 yamt } else {
524 1.21.2.3 yamt sc->sc_max_fib_size = le32toh(opt1) & 0xffff;
525 1.21.2.3 yamt sc->sc_max_sectors = (le32toh(opt1) >> 16) << 1;
526 1.21.2.3 yamt tmpval = (le32toh(opt2) >> 16);
527 1.21.2.3 yamt if (tmpval < sc->sc_max_sgs) {
528 1.21.2.3 yamt sc->sc_max_sgs = tmpval;
529 1.21.2.3 yamt }
530 1.21.2.3 yamt tmpval = (le32toh(opt3) & 0xffff);
531 1.21.2.3 yamt if (tmpval < sc->sc_max_fibs) {
532 1.21.2.3 yamt sc->sc_max_fibs = tmpval;
533 1.21.2.3 yamt }
534 1.21.2.3 yamt }
535 1.21.2.3 yamt }
536 1.21.2.3 yamt if (sc->sc_max_fib_size > PAGE_SIZE)
537 1.21.2.3 yamt sc->sc_max_fib_size = PAGE_SIZE;
538 1.21.2.3 yamt
539 1.21.2.3 yamt if (sc->sc_quirks & AAC_QUIRK_SG_64BIT)
540 1.21.2.3 yamt calcsgs = (sc->sc_max_fib_size
541 1.21.2.3 yamt - sizeof(struct aac_blockwrite64)
542 1.21.2.3 yamt + sizeof(struct aac_sg_table64))
543 1.21.2.3 yamt / sizeof(struct aac_sg_table64);
544 1.21.2.3 yamt else
545 1.21.2.3 yamt calcsgs = (sc->sc_max_fib_size
546 1.21.2.3 yamt - sizeof(struct aac_blockwrite)
547 1.21.2.3 yamt + sizeof(struct aac_sg_table))
548 1.21.2.3 yamt / sizeof(struct aac_sg_table);
549 1.21.2.3 yamt
550 1.21.2.3 yamt if (calcsgs < sc->sc_max_sgs) {
551 1.21.2.3 yamt sc->sc_max_sgs = calcsgs;
552 1.21.2.3 yamt }
553 1.21.2.3 yamt
554 1.21.2.3 yamt sc->sc_max_fibs_alloc = PAGE_SIZE / sc->sc_max_fib_size;
555 1.17 briggs
556 1.1 ad return (0);
557 1.1 ad }
558 1.1 ad
559 1.12 thorpej static int
560 1.1 ad aac_init(struct aac_softc *sc)
561 1.1 ad {
562 1.1 ad int nsegs, i, rv, state, norm, high;
563 1.1 ad struct aac_adapter_init *ip;
564 1.21 darcy u_int32_t code, qoff;
565 1.1 ad
566 1.1 ad state = 0;
567 1.1 ad
568 1.1 ad /*
569 1.1 ad * First wait for the adapter to come ready.
570 1.1 ad */
571 1.1 ad for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
572 1.1 ad code = AAC_GET_FWSTATUS(sc);
573 1.1 ad if ((code & AAC_SELF_TEST_FAILED) != 0) {
574 1.8 thorpej aprint_error("%s: FATAL: selftest failed\n",
575 1.1 ad sc->sc_dv.dv_xname);
576 1.1 ad return (ENXIO);
577 1.1 ad }
578 1.1 ad if ((code & AAC_KERNEL_PANIC) != 0) {
579 1.8 thorpej aprint_error("%s: FATAL: controller kernel panic\n",
580 1.1 ad sc->sc_dv.dv_xname);
581 1.1 ad return (ENXIO);
582 1.1 ad }
583 1.1 ad if ((code & AAC_UP_AND_RUNNING) != 0)
584 1.1 ad break;
585 1.1 ad DELAY(1000);
586 1.1 ad }
587 1.1 ad if (i == AAC_BOOT_TIMEOUT * 1000) {
588 1.8 thorpej aprint_error(
589 1.8 thorpej "%s: FATAL: controller not coming ready, status %x\n",
590 1.1 ad sc->sc_dv.dv_xname, code);
591 1.1 ad return (ENXIO);
592 1.1 ad }
593 1.1 ad
594 1.21.2.3 yamt sc->sc_aif_fib = malloc(sizeof(struct aac_fib), M_AACBUF,
595 1.21.2.3 yamt M_NOWAIT | M_ZERO);
596 1.21.2.3 yamt if (sc->sc_aif_fib == NULL) {
597 1.21.2.3 yamt aprint_error("%s: cannot alloc fib structure\n",
598 1.21.2.3 yamt sc->sc_dv.dv_xname);
599 1.21.2.3 yamt return (ENOMEM);
600 1.21.2.3 yamt }
601 1.1 ad if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1,
602 1.1 ad sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
603 1.1 ad &sc->sc_common_dmamap)) != 0) {
604 1.8 thorpej aprint_error("%s: cannot create common dmamap\n",
605 1.1 ad sc->sc_dv.dv_xname);
606 1.21.2.3 yamt goto bail_out;
607 1.1 ad }
608 1.21.2.3 yamt state++;
609 1.1 ad if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common),
610 1.1 ad PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs,
611 1.1 ad BUS_DMA_NOWAIT)) != 0) {
612 1.8 thorpej aprint_error("%s: can't allocate common structure\n",
613 1.1 ad sc->sc_dv.dv_xname);
614 1.1 ad goto bail_out;
615 1.1 ad }
616 1.1 ad state++;
617 1.1 ad if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs,
618 1.21.2.3 yamt sizeof(*sc->sc_common), (void **)&sc->sc_common, 0)) != 0) {
619 1.8 thorpej aprint_error("%s: can't map common structure\n",
620 1.1 ad sc->sc_dv.dv_xname);
621 1.1 ad goto bail_out;
622 1.1 ad }
623 1.1 ad state++;
624 1.1 ad if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap,
625 1.1 ad sc->sc_common, sizeof(*sc->sc_common), NULL,
626 1.1 ad BUS_DMA_NOWAIT)) != 0) {
627 1.8 thorpej aprint_error("%s: cannot load common dmamap\n",
628 1.8 thorpej sc->sc_dv.dv_xname);
629 1.1 ad goto bail_out;
630 1.1 ad }
631 1.1 ad state++;
632 1.1 ad
633 1.1 ad memset(sc->sc_common, 0, sizeof(*sc->sc_common));
634 1.1 ad
635 1.21.2.3 yamt TAILQ_INIT(&sc->sc_fibmap_tqh);
636 1.21.2.3 yamt sc->sc_ccbs = malloc(sizeof(struct aac_ccb) * sc->sc_max_fibs, M_AACBUF,
637 1.21.2.3 yamt M_NOWAIT | M_ZERO);
638 1.21.2.3 yamt if (sc->sc_ccbs == NULL) {
639 1.21.2.3 yamt aprint_error("%s: memory allocation failure getting ccbs\n",
640 1.21.2.3 yamt sc->sc_dv.dv_xname);
641 1.21.2.3 yamt rv = ENOMEM;
642 1.21.2.3 yamt goto bail_out;
643 1.21.2.3 yamt }
644 1.21.2.3 yamt state++;
645 1.21.2.3 yamt while (sc->sc_total_fibs < AAC_PREALLOCATE_FIBS) {
646 1.21.2.3 yamt if (aac_alloc_commands(sc) != 0)
647 1.21.2.3 yamt break;
648 1.21.2.3 yamt }
649 1.21.2.3 yamt if (sc->sc_total_fibs == 0)
650 1.21.2.3 yamt goto bail_out;
651 1.21.2.3 yamt
652 1.1 ad /*
653 1.1 ad * Fill in the init structure. This tells the adapter about the
654 1.1 ad * physical location of various important shared data structures.
655 1.1 ad */
656 1.1 ad ip = &sc->sc_common->ac_init;
657 1.1 ad ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION);
658 1.21.2.3 yamt if (sc->sc_max_fib_size > sizeof(struct aac_fib)) {
659 1.21.2.3 yamt ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION_4);
660 1.21.2.3 yamt sc->sc_quirks |= AAC_QUIRK_RAW_IO;
661 1.21.2.3 yamt }
662 1.21.2.3 yamt ip->MiniPortRevision = htole32(AAC_INIT_STRUCT_MINIPORT_REVISION);
663 1.1 ad
664 1.1 ad ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr +
665 1.1 ad offsetof(struct aac_common, ac_fibs));
666 1.21.2.3 yamt ip->AdapterFibsVirtualAddress = 0;
667 1.1 ad ip->AdapterFibsSize =
668 1.1 ad htole32(AAC_ADAPTER_FIBS * sizeof(struct aac_fib));
669 1.1 ad ip->AdapterFibAlign = htole32(sizeof(struct aac_fib));
670 1.1 ad
671 1.1 ad ip->PrintfBufferAddress = htole32(sc->sc_common_seg.ds_addr +
672 1.1 ad offsetof(struct aac_common, ac_printf));
673 1.1 ad ip->PrintfBufferSize = htole32(AAC_PRINTF_BUFSIZE);
674 1.1 ad
675 1.21.2.3 yamt /*
676 1.21.2.3 yamt * The adapter assumes that pages are 4K in size, except on some
677 1.21.2.3 yamt * broken firmware versions that do the page->byte conversion twice,
678 1.21.2.3 yamt * therefore 'assuming' that this value is in 16MB units (2^24).
679 1.21.2.3 yamt * Round up since the granularity is so high.
680 1.21.2.3 yamt */
681 1.21.2.3 yamt ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE;
682 1.21.2.3 yamt if (sc->sc_quirks & AAC_QUIRK_BROKEN_MMAP) {
683 1.21.2.3 yamt ip->HostPhysMemPages =
684 1.21.2.3 yamt (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE;
685 1.21.2.3 yamt }
686 1.1 ad ip->HostElapsedSeconds = 0; /* reset later if invalid */
687 1.1 ad
688 1.21.2.3 yamt ip->InitFlags = 0;
689 1.21.2.3 yamt if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
690 1.21.2.3 yamt ip->InitFlags = htole32(AAC_INITFLAGS_NEW_COMM_SUPPORTED);
691 1.21.2.3 yamt aprint_normal("%s: New comm. interface enabled\n",
692 1.21.2.3 yamt sc->sc_dv.dv_xname);
693 1.21.2.3 yamt }
694 1.21.2.3 yamt
695 1.21.2.3 yamt ip->MaxIoCommands = htole32(sc->sc_max_fibs);
696 1.21.2.3 yamt ip->MaxIoSize = htole32(sc->sc_max_sectors << 9);
697 1.21.2.3 yamt ip->MaxFibSize = htole32(sc->sc_max_fib_size);
698 1.21.2.3 yamt
699 1.1 ad /*
700 1.1 ad * Initialise FIB queues. Note that it appears that the layout of
701 1.1 ad * the indexes and the segmentation of the entries is mandated by
702 1.1 ad * the adapter, which is only told about the base of the queue index
703 1.1 ad * fields.
704 1.1 ad *
705 1.1 ad * The initial values of the indices are assumed to inform the
706 1.1 ad * adapter of the sizes of the respective queues.
707 1.1 ad *
708 1.1 ad * The Linux driver uses a much more complex scheme whereby several
709 1.1 ad * header records are kept for each queue. We use a couple of
710 1.1 ad * generic list manipulation functions which 'know' the size of each
711 1.1 ad * list by virtue of a table.
712 1.1 ad */
713 1.21 darcy qoff = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
714 1.21 darcy qoff &= ~(AAC_QUEUE_ALIGN - 1);
715 1.21 darcy sc->sc_queues = (struct aac_queue_table *)((uintptr_t)sc->sc_common + qoff);
716 1.1 ad ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr +
717 1.21.2.3 yamt ((char *)sc->sc_queues - (char *)sc->sc_common));
718 1.1 ad memset(sc->sc_queues, 0, sizeof(struct aac_queue_table));
719 1.1 ad
720 1.1 ad norm = htole32(AAC_HOST_NORM_CMD_ENTRIES);
721 1.1 ad high = htole32(AAC_HOST_HIGH_CMD_ENTRIES);
722 1.1 ad
723 1.1 ad sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
724 1.1 ad norm;
725 1.1 ad sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
726 1.1 ad norm;
727 1.1 ad sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
728 1.1 ad high;
729 1.1 ad sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
730 1.1 ad high;
731 1.1 ad
732 1.1 ad norm = htole32(AAC_ADAP_NORM_CMD_ENTRIES);
733 1.1 ad high = htole32(AAC_ADAP_HIGH_CMD_ENTRIES);
734 1.1 ad
735 1.1 ad sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
736 1.1 ad norm;
737 1.1 ad sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
738 1.1 ad norm;
739 1.1 ad sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
740 1.1 ad high;
741 1.1 ad sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
742 1.1 ad high;
743 1.1 ad
744 1.1 ad norm = htole32(AAC_HOST_NORM_RESP_ENTRIES);
745 1.1 ad high = htole32(AAC_HOST_HIGH_RESP_ENTRIES);
746 1.1 ad
747 1.1 ad sc->sc_queues->
748 1.1 ad qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
749 1.1 ad sc->sc_queues->
750 1.1 ad qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
751 1.1 ad sc->sc_queues->
752 1.1 ad qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
753 1.1 ad sc->sc_queues->
754 1.1 ad qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
755 1.1 ad
756 1.1 ad norm = htole32(AAC_ADAP_NORM_RESP_ENTRIES);
757 1.1 ad high = htole32(AAC_ADAP_HIGH_RESP_ENTRIES);
758 1.1 ad
759 1.1 ad sc->sc_queues->
760 1.1 ad qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
761 1.1 ad sc->sc_queues->
762 1.1 ad qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
763 1.1 ad sc->sc_queues->
764 1.1 ad qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
765 1.1 ad sc->sc_queues->
766 1.1 ad qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
767 1.1 ad
768 1.1 ad sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] =
769 1.1 ad &sc->sc_queues->qt_HostNormCmdQueue[0];
770 1.1 ad sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
771 1.1 ad &sc->sc_queues->qt_HostHighCmdQueue[0];
772 1.1 ad sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
773 1.1 ad &sc->sc_queues->qt_AdapNormCmdQueue[0];
774 1.1 ad sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
775 1.1 ad &sc->sc_queues->qt_AdapHighCmdQueue[0];
776 1.1 ad sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] =
777 1.1 ad &sc->sc_queues->qt_HostNormRespQueue[0];
778 1.1 ad sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
779 1.1 ad &sc->sc_queues->qt_HostHighRespQueue[0];
780 1.1 ad sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
781 1.1 ad &sc->sc_queues->qt_AdapNormRespQueue[0];
782 1.1 ad sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
783 1.1 ad &sc->sc_queues->qt_AdapHighRespQueue[0];
784 1.1 ad
785 1.1 ad /*
786 1.1 ad * Do controller-type-specific initialisation
787 1.1 ad */
788 1.1 ad switch (sc->sc_hwif) {
789 1.1 ad case AAC_HWIF_I960RX:
790 1.1 ad AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
791 1.1 ad break;
792 1.1 ad }
793 1.1 ad
794 1.1 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 0,
795 1.1 ad sizeof(*sc->sc_common),
796 1.1 ad BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
797 1.1 ad
798 1.1 ad /*
799 1.1 ad * Give the init structure to the controller.
800 1.1 ad */
801 1.16 perry if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
802 1.1 ad sc->sc_common_seg.ds_addr + offsetof(struct aac_common, ac_init),
803 1.1 ad 0, 0, 0, NULL)) {
804 1.8 thorpej aprint_error("%s: error establishing init structure\n",
805 1.1 ad sc->sc_dv.dv_xname);
806 1.1 ad rv = EIO;
807 1.1 ad goto bail_out;
808 1.1 ad }
809 1.1 ad
810 1.1 ad return (0);
811 1.1 ad
812 1.1 ad bail_out:
813 1.21.2.3 yamt if (state > 4)
814 1.21.2.3 yamt free(sc->sc_ccbs, M_AACBUF);
815 1.21.2.3 yamt if (state > 3)
816 1.1 ad bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
817 1.21.2.3 yamt if (state > 2)
818 1.21.2.3 yamt bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_common,
819 1.1 ad sizeof(*sc->sc_common));
820 1.21.2.3 yamt if (state > 1)
821 1.1 ad bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
822 1.21.2.3 yamt if (state > 0)
823 1.21.2.3 yamt bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
824 1.21.2.3 yamt
825 1.21.2.3 yamt free(sc->sc_aif_fib, M_AACBUF);
826 1.1 ad
827 1.1 ad return (rv);
828 1.1 ad }
829 1.1 ad
830 1.1 ad /*
831 1.1 ad * Probe for containers, create disks.
832 1.1 ad */
833 1.12 thorpej static void
834 1.1 ad aac_startup(struct aac_softc *sc)
835 1.1 ad {
836 1.1 ad struct aac_mntinfo mi;
837 1.1 ad struct aac_mntinforesponse mir;
838 1.1 ad struct aac_drive *hd;
839 1.1 ad u_int16_t rsize;
840 1.1 ad int i;
841 1.1 ad
842 1.1 ad /*
843 1.1 ad * Loop over possible containers.
844 1.1 ad */
845 1.1 ad hd = sc->sc_hdr;
846 1.1 ad
847 1.1 ad for (i = 0; i < AAC_MAX_CONTAINERS; i++, hd++) {
848 1.1 ad /*
849 1.1 ad * Request information on this container.
850 1.1 ad */
851 1.10 ad memset(&mi, 0, sizeof(mi));
852 1.10 ad mi.Command = htole32(VM_NameServe);
853 1.10 ad mi.MntType = htole32(FT_FILESYS);
854 1.1 ad mi.MntCount = htole32(i);
855 1.1 ad if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), &mir,
856 1.1 ad &rsize)) {
857 1.8 thorpej aprint_error("%s: error probing container %d\n",
858 1.1 ad sc->sc_dv.dv_xname, i);
859 1.1 ad continue;
860 1.1 ad }
861 1.1 ad if (rsize != sizeof(mir)) {
862 1.8 thorpej aprint_error("%s: container info response wrong size "
863 1.21.2.1 yamt "(%d should be %zu)\n",
864 1.21.2.1 yamt sc->sc_dv.dv_xname, rsize, sizeof(mir));
865 1.1 ad continue;
866 1.1 ad }
867 1.1 ad
868 1.16 perry /*
869 1.1 ad * Check container volume type for validity. Note that many
870 1.1 ad * of the possible types may never show up.
871 1.1 ad */
872 1.1 ad if (le32toh(mir.Status) != ST_OK ||
873 1.1 ad le32toh(mir.MntTable[0].VolType) == CT_NONE)
874 1.1 ad continue;
875 1.1 ad
876 1.1 ad hd->hd_present = 1;
877 1.1 ad hd->hd_size = le32toh(mir.MntTable[0].Capacity);
878 1.1 ad hd->hd_devtype = le32toh(mir.MntTable[0].VolType);
879 1.1 ad hd->hd_size &= ~0x1f;
880 1.1 ad sc->sc_nunits++;
881 1.1 ad }
882 1.1 ad }
883 1.1 ad
884 1.12 thorpej static void
885 1.1 ad aac_shutdown(void *cookie)
886 1.1 ad {
887 1.1 ad struct aac_softc *sc;
888 1.1 ad struct aac_close_command cc;
889 1.1 ad u_int32_t i;
890 1.1 ad
891 1.1 ad for (i = 0; i < aac_cd.cd_ndevs; i++) {
892 1.1 ad if ((sc = device_lookup(&aac_cd, i)) == NULL)
893 1.1 ad continue;
894 1.1 ad if ((sc->sc_flags & AAC_ONLINE) == 0)
895 1.1 ad continue;
896 1.1 ad
897 1.1 ad AAC_MASK_INTERRUPTS(sc);
898 1.1 ad
899 1.16 perry /*
900 1.1 ad * Send a Container shutdown followed by a HostShutdown FIB
901 1.1 ad * to the controller to convince it that we don't want to
902 1.1 ad * talk to it anymore. We've been closed and all I/O
903 1.1 ad * completed already
904 1.1 ad */
905 1.10 ad memset(&cc, 0, sizeof(cc));
906 1.1 ad cc.Command = htole32(VM_CloseAll);
907 1.1 ad cc.ContainerId = 0xffffffff;
908 1.1 ad if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc),
909 1.1 ad NULL, NULL)) {
910 1.1 ad printf("%s: unable to halt controller\n",
911 1.1 ad sc->sc_dv.dv_xname);
912 1.1 ad continue;
913 1.1 ad }
914 1.1 ad
915 1.1 ad /*
916 1.1 ad * Note that issuing this command to the controller makes it
917 1.1 ad * shut down but also keeps it from coming back up without a
918 1.1 ad * reset of the PCI bus.
919 1.1 ad */
920 1.1 ad if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
921 1.1 ad &i, sizeof(i), NULL, NULL))
922 1.1 ad printf("%s: unable to halt controller\n",
923 1.1 ad sc->sc_dv.dv_xname);
924 1.17 briggs
925 1.17 briggs sc->sc_flags &= ~AAC_ONLINE;
926 1.1 ad }
927 1.1 ad }
928 1.1 ad
929 1.21.2.3 yamt static int
930 1.21.2.3 yamt aac_new_intr(void *cookie)
931 1.21.2.3 yamt {
932 1.21.2.3 yamt struct aac_softc *sc;
933 1.21.2.3 yamt u_int32_t index, fast;
934 1.21.2.3 yamt struct aac_ccb *ac;
935 1.21.2.3 yamt struct aac_fib *fib;
936 1.21.2.3 yamt struct aac_fibmap *fm;
937 1.21.2.3 yamt int i;
938 1.21.2.3 yamt
939 1.21.2.3 yamt sc = (struct aac_softc *) cookie;
940 1.21.2.3 yamt
941 1.21.2.3 yamt for (;;) {
942 1.21.2.3 yamt index = AAC_GET_OUTB_QUEUE(sc);
943 1.21.2.3 yamt if (index == 0xffffffff)
944 1.21.2.3 yamt index = AAC_GET_OUTB_QUEUE(sc);
945 1.21.2.3 yamt if (index == 0xffffffff)
946 1.21.2.3 yamt break;
947 1.21.2.3 yamt if (index & 2) {
948 1.21.2.3 yamt if (index == 0xfffffffe) {
949 1.21.2.3 yamt /* XXX This means that the controller wants
950 1.21.2.3 yamt * more work. Ignore it for now.
951 1.21.2.3 yamt */
952 1.21.2.3 yamt continue;
953 1.21.2.3 yamt }
954 1.21.2.3 yamt /* AIF */
955 1.21.2.3 yamt index &= ~2;
956 1.21.2.3 yamt fib = sc->sc_aif_fib;
957 1.21.2.3 yamt for (i = 0; i < sizeof(struct aac_fib)/4; i++) {
958 1.21.2.3 yamt ((u_int32_t*)fib)[i] =
959 1.21.2.3 yamt AAC_GETREG4(sc, index + i*4);
960 1.21.2.3 yamt }
961 1.21.2.3 yamt #ifdef notyet
962 1.21.2.3 yamt aac_handle_aif(sc, &fib);
963 1.21.2.3 yamt #endif
964 1.21.2.3 yamt
965 1.21.2.3 yamt AAC_SET_OUTB_QUEUE(sc, index);
966 1.21.2.3 yamt AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
967 1.21.2.3 yamt } else {
968 1.21.2.3 yamt fast = index & 1;
969 1.21.2.3 yamt ac = sc->sc_ccbs + (index >> 2);
970 1.21.2.3 yamt fib = ac->ac_fib;
971 1.21.2.3 yamt fm = ac->ac_fibmap;
972 1.21.2.3 yamt if (fast) {
973 1.21.2.3 yamt bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
974 1.21.2.3 yamt (char *)fib - (char *)fm->fm_fibs,
975 1.21.2.3 yamt sc->sc_max_fib_size,
976 1.21.2.3 yamt BUS_DMASYNC_POSTWRITE |
977 1.21.2.3 yamt BUS_DMASYNC_POSTREAD);
978 1.21.2.3 yamt fib->Header.XferState |=
979 1.21.2.3 yamt htole32(AAC_FIBSTATE_DONEADAP);
980 1.21.2.3 yamt *((u_int32_t *)(fib->data)) =
981 1.21.2.3 yamt htole32(AAC_ERROR_NORMAL);
982 1.21.2.3 yamt }
983 1.21.2.3 yamt ac->ac_flags |= AAC_CCB_COMPLETED;
984 1.21.2.3 yamt
985 1.21.2.3 yamt if (ac->ac_intr != NULL)
986 1.21.2.3 yamt (*ac->ac_intr)(ac);
987 1.21.2.3 yamt else
988 1.21.2.3 yamt wakeup(ac);
989 1.21.2.3 yamt }
990 1.21.2.3 yamt }
991 1.21.2.3 yamt
992 1.21.2.3 yamt /*
993 1.21.2.3 yamt * Try to submit more commands.
994 1.21.2.3 yamt */
995 1.21.2.3 yamt if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
996 1.21.2.3 yamt aac_ccb_enqueue(sc, NULL);
997 1.21.2.3 yamt
998 1.21.2.3 yamt return 1;
999 1.21.2.3 yamt }
1000 1.21.2.3 yamt
1001 1.1 ad /*
1002 1.1 ad * Take an interrupt.
1003 1.1 ad */
1004 1.1 ad int
1005 1.1 ad aac_intr(void *cookie)
1006 1.1 ad {
1007 1.1 ad struct aac_softc *sc;
1008 1.1 ad u_int16_t reason;
1009 1.1 ad int claimed;
1010 1.1 ad
1011 1.1 ad sc = cookie;
1012 1.1 ad claimed = 0;
1013 1.1 ad
1014 1.1 ad AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc));
1015 1.1 ad
1016 1.1 ad reason = AAC_GET_ISTATUS(sc);
1017 1.21.2.3 yamt AAC_CLEAR_ISTATUS(sc, reason);
1018 1.21.2.3 yamt
1019 1.1 ad AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason));
1020 1.1 ad
1021 1.1 ad /*
1022 1.1 ad * Controller wants to talk to the log. XXX Should we defer this?
1023 1.1 ad */
1024 1.1 ad if ((reason & AAC_DB_PRINTF) != 0) {
1025 1.21.2.3 yamt if (sc->sc_common->ac_printf[0] == '\0')
1026 1.21.2.3 yamt sc->sc_common->ac_printf[0] = ' ';
1027 1.21.2.3 yamt printf("%s: WARNING: adapter logged message:\n",
1028 1.21.2.3 yamt sc->sc_dv.dv_xname);
1029 1.21.2.3 yamt printf("%s: %.*s", sc->sc_dv.dv_xname,
1030 1.21.2.3 yamt AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
1031 1.21.2.3 yamt sc->sc_common->ac_printf[0] = '\0';
1032 1.1 ad AAC_QNOTIFY(sc, AAC_DB_PRINTF);
1033 1.1 ad claimed = 1;
1034 1.1 ad }
1035 1.1 ad
1036 1.1 ad /*
1037 1.1 ad * Controller has a message for us?
1038 1.1 ad */
1039 1.1 ad if ((reason & AAC_DB_COMMAND_READY) != 0) {
1040 1.1 ad aac_host_command(sc);
1041 1.1 ad claimed = 1;
1042 1.1 ad }
1043 1.1 ad
1044 1.1 ad /*
1045 1.1 ad * Controller has a response for us?
1046 1.1 ad */
1047 1.1 ad if ((reason & AAC_DB_RESPONSE_READY) != 0) {
1048 1.1 ad aac_host_response(sc);
1049 1.1 ad claimed = 1;
1050 1.1 ad }
1051 1.1 ad
1052 1.1 ad /*
1053 1.1 ad * Spurious interrupts that we don't use - reset the mask and clear
1054 1.1 ad * the interrupts.
1055 1.1 ad */
1056 1.1 ad if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL |
1057 1.1 ad AAC_DB_RESPONSE_NOT_FULL)) != 0) {
1058 1.1 ad AAC_UNMASK_INTERRUPTS(sc);
1059 1.1 ad AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND |
1060 1.1 ad AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
1061 1.1 ad claimed = 1;
1062 1.1 ad }
1063 1.1 ad
1064 1.1 ad return (claimed);
1065 1.1 ad }
1066 1.1 ad
1067 1.1 ad /*
1068 1.1 ad * Handle notification of one or more FIBs coming from the controller.
1069 1.1 ad */
1070 1.12 thorpej static void
1071 1.1 ad aac_host_command(struct aac_softc *sc)
1072 1.1 ad {
1073 1.1 ad struct aac_fib *fib;
1074 1.1 ad u_int32_t fib_size;
1075 1.1 ad
1076 1.1 ad for (;;) {
1077 1.1 ad if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size,
1078 1.1 ad &fib))
1079 1.1 ad break; /* nothing to do */
1080 1.1 ad
1081 1.1 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1082 1.21.2.3 yamt (char *)fib - (char *)sc->sc_common, sizeof(*fib),
1083 1.1 ad BUS_DMASYNC_POSTREAD);
1084 1.1 ad
1085 1.1 ad switch (le16toh(fib->Header.Command)) {
1086 1.1 ad case AifRequest:
1087 1.1 ad #ifdef notyet
1088 1.1 ad aac_handle_aif(sc,
1089 1.1 ad (struct aac_aif_command *)&fib->data[0]);
1090 1.1 ad #endif
1091 1.21.2.3 yamt AAC_PRINT_FIB(sc, fib);
1092 1.1 ad break;
1093 1.1 ad default:
1094 1.1 ad printf("%s: unknown command from controller\n",
1095 1.1 ad sc->sc_dv.dv_xname);
1096 1.1 ad AAC_PRINT_FIB(sc, fib);
1097 1.1 ad break;
1098 1.1 ad }
1099 1.1 ad
1100 1.1 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1101 1.21.2.3 yamt (char *)fib - (char *)sc->sc_common, sizeof(*fib),
1102 1.1 ad BUS_DMASYNC_PREREAD);
1103 1.1 ad
1104 1.21.2.3 yamt if ((fib->Header.XferState == 0) ||
1105 1.21.2.3 yamt (fib->Header.StructType != AAC_FIBTYPE_TFIB)) {
1106 1.21.2.3 yamt break; // continue; ???
1107 1.21.2.3 yamt }
1108 1.21.2.3 yamt
1109 1.1 ad /* XXX reply to FIBs requesting responses ?? */
1110 1.21.2.3 yamt
1111 1.21.2.3 yamt /* Return the AIF/FIB to the controller */
1112 1.21.2.3 yamt if (le32toh(fib->Header.XferState) & AAC_FIBSTATE_FROMADAP) {
1113 1.21.2.3 yamt u_int16_t size;
1114 1.21.2.3 yamt
1115 1.21.2.3 yamt fib->Header.XferState |=
1116 1.21.2.3 yamt htole32(AAC_FIBSTATE_DONEHOST);
1117 1.21.2.3 yamt *(u_int32_t*)fib->data = htole32(ST_OK);
1118 1.21.2.3 yamt
1119 1.21.2.3 yamt /* XXX Compute the Size field? */
1120 1.21.2.3 yamt size = le16toh(fib->Header.Size);
1121 1.21.2.3 yamt if (size > sizeof(struct aac_fib)) {
1122 1.21.2.3 yamt size = sizeof(struct aac_fib);
1123 1.21.2.3 yamt fib->Header.Size = htole16(size);
1124 1.21.2.3 yamt }
1125 1.21.2.3 yamt
1126 1.21.2.3 yamt /*
1127 1.21.2.3 yamt * Since we didn't generate this command, it can't
1128 1.21.2.3 yamt * go through the normal process.
1129 1.21.2.3 yamt */
1130 1.21.2.3 yamt aac_enqueue_response(sc,
1131 1.21.2.3 yamt AAC_ADAP_NORM_RESP_QUEUE, fib);
1132 1.21.2.3 yamt }
1133 1.1 ad }
1134 1.1 ad }
1135 1.1 ad
1136 1.1 ad /*
1137 1.1 ad * Handle notification of one or more FIBs completed by the controller
1138 1.1 ad */
1139 1.12 thorpej static void
1140 1.1 ad aac_host_response(struct aac_softc *sc)
1141 1.1 ad {
1142 1.1 ad struct aac_ccb *ac;
1143 1.1 ad struct aac_fib *fib;
1144 1.1 ad u_int32_t fib_size;
1145 1.1 ad
1146 1.1 ad /*
1147 1.1 ad * Look for completed FIBs on our queue.
1148 1.1 ad */
1149 1.1 ad for (;;) {
1150 1.1 ad if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
1151 1.1 ad &fib))
1152 1.1 ad break; /* nothing to do */
1153 1.1 ad
1154 1.1 ad if ((fib->Header.SenderData & 0x80000000) == 0) {
1155 1.1 ad /* Not valid; not sent by us. */
1156 1.1 ad AAC_PRINT_FIB(sc, fib);
1157 1.1 ad } else {
1158 1.21.2.3 yamt ac = (struct aac_ccb *)(sc->sc_ccbs +
1159 1.1 ad (fib->Header.SenderData & 0x7fffffff));
1160 1.1 ad fib->Header.SenderData = 0;
1161 1.1 ad SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain);
1162 1.1 ad }
1163 1.1 ad }
1164 1.1 ad
1165 1.1 ad /*
1166 1.1 ad * Deal with any completed commands.
1167 1.1 ad */
1168 1.1 ad while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) {
1169 1.3 lukem SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac_chain);
1170 1.1 ad ac->ac_flags |= AAC_CCB_COMPLETED;
1171 1.1 ad
1172 1.1 ad if (ac->ac_intr != NULL)
1173 1.1 ad (*ac->ac_intr)(ac);
1174 1.21.2.3 yamt else
1175 1.21.2.3 yamt wakeup(ac);
1176 1.1 ad }
1177 1.1 ad
1178 1.1 ad /*
1179 1.1 ad * Try to submit more commands.
1180 1.1 ad */
1181 1.3 lukem if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
1182 1.1 ad aac_ccb_enqueue(sc, NULL);
1183 1.1 ad }
1184 1.1 ad
1185 1.1 ad /*
1186 1.1 ad * Send a synchronous command to the controller and wait for a result.
1187 1.1 ad */
1188 1.12 thorpej static int
1189 1.1 ad aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
1190 1.1 ad u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp)
1191 1.1 ad {
1192 1.1 ad int i;
1193 1.1 ad u_int32_t status;
1194 1.1 ad int s;
1195 1.1 ad
1196 1.1 ad s = splbio();
1197 1.1 ad
1198 1.1 ad /* Populate the mailbox. */
1199 1.1 ad AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
1200 1.1 ad
1201 1.1 ad /* Ensure the sync command doorbell flag is cleared. */
1202 1.1 ad AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1203 1.1 ad
1204 1.1 ad /* ... then set it to signal the adapter. */
1205 1.1 ad AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
1206 1.1 ad DELAY(AAC_SYNC_DELAY);
1207 1.1 ad
1208 1.1 ad /* Spin waiting for the command to complete. */
1209 1.1 ad for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
1210 1.11 christos if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)
1211 1.1 ad break;
1212 1.1 ad DELAY(1000);
1213 1.1 ad }
1214 1.1 ad if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
1215 1.1 ad splx(s);
1216 1.1 ad return (EIO);
1217 1.1 ad }
1218 1.1 ad
1219 1.1 ad /* Clear the completion flag. */
1220 1.1 ad AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1221 1.1 ad
1222 1.1 ad /* Get the command status. */
1223 1.1 ad status = AAC_GET_MAILBOXSTATUS(sc);
1224 1.1 ad splx(s);
1225 1.1 ad if (sp != NULL)
1226 1.1 ad *sp = status;
1227 1.1 ad
1228 1.1 ad return (0); /* XXX Check command return status? */
1229 1.1 ad }
1230 1.1 ad
1231 1.1 ad /*
1232 1.1 ad * Send a synchronous FIB to the controller and wait for a result.
1233 1.1 ad */
1234 1.12 thorpej static int
1235 1.1 ad aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
1236 1.1 ad void *data, u_int16_t datasize, void *result,
1237 1.1 ad u_int16_t *resultsize)
1238 1.1 ad {
1239 1.1 ad struct aac_fib *fib;
1240 1.1 ad u_int32_t fibpa, status;
1241 1.1 ad
1242 1.1 ad fib = &sc->sc_common->ac_sync_fib;
1243 1.1 ad fibpa = sc->sc_common_seg.ds_addr +
1244 1.1 ad offsetof(struct aac_common, ac_sync_fib);
1245 1.1 ad
1246 1.1 ad if (datasize > AAC_FIB_DATASIZE)
1247 1.1 ad return (EINVAL);
1248 1.1 ad
1249 1.1 ad /*
1250 1.1 ad * Set up the sync FIB.
1251 1.1 ad */
1252 1.1 ad fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED |
1253 1.1 ad AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate);
1254 1.1 ad fib->Header.Command = htole16(command);
1255 1.1 ad fib->Header.StructType = AAC_FIBTYPE_TFIB;
1256 1.1 ad fib->Header.Size = htole16(sizeof(*fib) + datasize);
1257 1.1 ad fib->Header.SenderSize = htole16(sizeof(*fib));
1258 1.21.2.3 yamt fib->Header.SenderFibAddress = 0; /* not needed */
1259 1.1 ad fib->Header.ReceiverFibAddress = htole32(fibpa);
1260 1.1 ad
1261 1.1 ad /*
1262 1.1 ad * Copy in data.
1263 1.1 ad */
1264 1.1 ad if (data != NULL) {
1265 1.1 ad memcpy(fib->data, data, datasize);
1266 1.1 ad fib->Header.XferState |=
1267 1.1 ad htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM);
1268 1.1 ad }
1269 1.1 ad
1270 1.1 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1271 1.21.2.3 yamt (char *)fib - (char *)sc->sc_common, sizeof(*fib),
1272 1.1 ad BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1273 1.1 ad
1274 1.1 ad /*
1275 1.1 ad * Give the FIB to the controller, wait for a response.
1276 1.1 ad */
1277 1.1 ad if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status))
1278 1.1 ad return (EIO);
1279 1.17 briggs if (status != 1) {
1280 1.17 briggs printf("%s: syncfib command %04x status %08x\n",
1281 1.17 briggs sc->sc_dv.dv_xname, command, status);
1282 1.17 briggs }
1283 1.1 ad
1284 1.1 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1285 1.21.2.3 yamt (char *)fib - (char *)sc->sc_common, sizeof(*fib),
1286 1.1 ad BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1287 1.1 ad
1288 1.16 perry /*
1289 1.1 ad * Copy out the result
1290 1.1 ad */
1291 1.1 ad if (result != NULL) {
1292 1.1 ad *resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header);
1293 1.1 ad memcpy(result, fib->data, *resultsize);
1294 1.1 ad }
1295 1.1 ad
1296 1.1 ad return (0);
1297 1.1 ad }
1298 1.1 ad
1299 1.1 ad struct aac_ccb *
1300 1.1 ad aac_ccb_alloc(struct aac_softc *sc, int flags)
1301 1.1 ad {
1302 1.1 ad struct aac_ccb *ac;
1303 1.1 ad int s;
1304 1.1 ad
1305 1.1 ad AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags));
1306 1.1 ad
1307 1.1 ad s = splbio();
1308 1.1 ad ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
1309 1.21.2.3 yamt if (ac == NULL) {
1310 1.21.2.3 yamt if (aac_alloc_commands(sc)) {
1311 1.21.2.3 yamt splx(s);
1312 1.21.2.3 yamt return NULL;
1313 1.21.2.3 yamt }
1314 1.21.2.3 yamt ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
1315 1.21.2.3 yamt }
1316 1.1 ad #ifdef DIAGNOSTIC
1317 1.1 ad if (ac == NULL)
1318 1.1 ad panic("aac_ccb_get: no free CCBS");
1319 1.1 ad #endif
1320 1.3 lukem SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac_chain);
1321 1.1 ad splx(s);
1322 1.1 ad
1323 1.1 ad ac->ac_flags = flags;
1324 1.1 ad return (ac);
1325 1.1 ad }
1326 1.1 ad
1327 1.1 ad void
1328 1.1 ad aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac)
1329 1.1 ad {
1330 1.1 ad int s;
1331 1.1 ad
1332 1.1 ad AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac));
1333 1.1 ad
1334 1.1 ad ac->ac_flags = 0;
1335 1.1 ad ac->ac_intr = NULL;
1336 1.1 ad ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY);
1337 1.1 ad ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB;
1338 1.1 ad ac->ac_fib->Header.Flags = 0;
1339 1.21.2.3 yamt ac->ac_fib->Header.SenderSize = htole16(sc->sc_max_fib_size);
1340 1.1 ad
1341 1.1 ad #ifdef AAC_DEBUG
1342 1.16 perry /*
1343 1.1 ad * These are duplicated in aac_ccb_submit() to cover the case where
1344 1.1 ad * an intermediate stage may have destroyed them. They're left
1345 1.1 ad * initialised here for debugging purposes only.
1346 1.1 ad */
1347 1.21.2.3 yamt ac->ac_fib->Header.SenderFibAddress =
1348 1.21.2.3 yamt htole32(((u_int32_t) (ac - sc->sc_ccbs)) << 2);
1349 1.1 ad ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
1350 1.1 ad #endif
1351 1.1 ad
1352 1.1 ad s = splbio();
1353 1.1 ad SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain);
1354 1.1 ad splx(s);
1355 1.1 ad }
1356 1.1 ad
1357 1.1 ad int
1358 1.1 ad aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac)
1359 1.1 ad {
1360 1.1 ad int error;
1361 1.1 ad
1362 1.1 ad AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac));
1363 1.1 ad
1364 1.1 ad #ifdef DIAGNOSTIC
1365 1.1 ad if ((ac->ac_flags & AAC_CCB_MAPPED) != 0)
1366 1.1 ad panic("aac_ccb_map: already mapped");
1367 1.1 ad #endif
1368 1.1 ad
1369 1.1 ad error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data,
1370 1.1 ad ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
1371 1.1 ad ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
1372 1.1 ad if (error) {
1373 1.1 ad printf("%s: aac_ccb_map: ", sc->sc_dv.dv_xname);
1374 1.1 ad if (error == EFBIG)
1375 1.21.2.3 yamt printf("more than %d DMA segs\n", sc->sc_max_sgs);
1376 1.1 ad else
1377 1.9 wiz printf("error %d loading DMA map\n", error);
1378 1.1 ad return (error);
1379 1.1 ad }
1380 1.1 ad
1381 1.1 ad bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
1382 1.1 ad (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD :
1383 1.1 ad BUS_DMASYNC_PREWRITE);
1384 1.1 ad
1385 1.1 ad #ifdef DIAGNOSTIC
1386 1.1 ad ac->ac_flags |= AAC_CCB_MAPPED;
1387 1.1 ad #endif
1388 1.1 ad return (0);
1389 1.1 ad }
1390 1.1 ad
1391 1.1 ad void
1392 1.1 ad aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac)
1393 1.1 ad {
1394 1.1 ad
1395 1.1 ad AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac));
1396 1.1 ad
1397 1.1 ad #ifdef DIAGNOSTIC
1398 1.1 ad if ((ac->ac_flags & AAC_CCB_MAPPED) == 0)
1399 1.1 ad panic("aac_ccb_unmap: not mapped");
1400 1.1 ad #endif
1401 1.1 ad
1402 1.1 ad bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
1403 1.1 ad (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD :
1404 1.1 ad BUS_DMASYNC_POSTWRITE);
1405 1.1 ad bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer);
1406 1.1 ad
1407 1.1 ad #ifdef DIAGNOSTIC
1408 1.1 ad ac->ac_flags &= ~AAC_CCB_MAPPED;
1409 1.1 ad #endif
1410 1.1 ad }
1411 1.1 ad
1412 1.1 ad void
1413 1.1 ad aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac)
1414 1.1 ad {
1415 1.1 ad int s;
1416 1.1 ad
1417 1.1 ad AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac));
1418 1.1 ad
1419 1.1 ad s = splbio();
1420 1.1 ad
1421 1.1 ad if (ac != NULL)
1422 1.1 ad SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain);
1423 1.1 ad
1424 1.1 ad while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) {
1425 1.1 ad if (aac_ccb_submit(sc, ac))
1426 1.1 ad break;
1427 1.3 lukem SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac_chain);
1428 1.1 ad }
1429 1.1 ad
1430 1.1 ad splx(s);
1431 1.1 ad }
1432 1.1 ad
1433 1.1 ad int
1434 1.1 ad aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac)
1435 1.1 ad {
1436 1.21.2.3 yamt struct aac_fibmap *fm;
1437 1.21.2.3 yamt u_int32_t acidx;
1438 1.1 ad
1439 1.1 ad AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac));
1440 1.1 ad
1441 1.21.2.3 yamt acidx = (u_int32_t) (ac - sc->sc_ccbs);
1442 1.1 ad /* Fix up the address values. */
1443 1.21.2.3 yamt ac->ac_fib->Header.SenderFibAddress = htole32(acidx << 2);
1444 1.1 ad ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
1445 1.1 ad
1446 1.1 ad /* Save a pointer to the command for speedy reverse-lookup. */
1447 1.21.2.3 yamt ac->ac_fib->Header.SenderData = acidx | 0x80000000;
1448 1.1 ad
1449 1.21.2.3 yamt fm = ac->ac_fibmap;
1450 1.21.2.3 yamt bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
1451 1.21.2.3 yamt (char *)ac->ac_fib - (char *)fm->fm_fibs, sc->sc_max_fib_size,
1452 1.1 ad BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1453 1.1 ad
1454 1.1 ad /* Put the FIB on the outbound queue. */
1455 1.21.2.3 yamt if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
1456 1.21.2.3 yamt int count = 10000000L;
1457 1.21.2.3 yamt while (AAC_SEND_COMMAND(sc, ac) != 0) {
1458 1.21.2.3 yamt if (--count == 0) {
1459 1.21.2.3 yamt panic("aac: fixme!");
1460 1.21.2.3 yamt return EAGAIN;
1461 1.21.2.3 yamt }
1462 1.21.2.3 yamt DELAY(5);
1463 1.21.2.3 yamt }
1464 1.21.2.3 yamt return 0;
1465 1.21.2.3 yamt } else {
1466 1.21.2.3 yamt return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac));
1467 1.21.2.3 yamt }
1468 1.1 ad }
1469 1.1 ad
1470 1.1 ad int
1471 1.1 ad aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo)
1472 1.1 ad {
1473 1.1 ad int rv, s;
1474 1.1 ad
1475 1.1 ad AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo));
1476 1.1 ad
1477 1.1 ad s = splbio();
1478 1.1 ad
1479 1.1 ad if ((rv = aac_ccb_submit(sc, ac)) != 0) {
1480 1.1 ad splx(s);
1481 1.1 ad return (rv);
1482 1.1 ad }
1483 1.1 ad
1484 1.1 ad for (timo *= 1000; timo != 0; timo--) {
1485 1.21.2.3 yamt if (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
1486 1.21.2.3 yamt aac_new_intr(sc);
1487 1.21.2.3 yamt else
1488 1.21.2.3 yamt aac_intr(sc);
1489 1.1 ad if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0)
1490 1.1 ad break;
1491 1.1 ad DELAY(100);
1492 1.1 ad }
1493 1.1 ad
1494 1.1 ad splx(s);
1495 1.1 ad return (timo == 0);
1496 1.1 ad }
1497 1.1 ad
1498 1.1 ad /*
1499 1.1 ad * Atomically insert an entry into the nominated queue, returns 0 on success
1500 1.1 ad * or EBUSY if the queue is full.
1501 1.1 ad *
1502 1.1 ad * XXX Note that it would be more efficient to defer notifying the
1503 1.1 ad * controller in the case where we may be inserting several entries in rapid
1504 1.1 ad * succession, but implementing this usefully is difficult.
1505 1.1 ad */
1506 1.12 thorpej static int
1507 1.21.2.3 yamt aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_ccb *ac)
1508 1.1 ad {
1509 1.1 ad u_int32_t fib_size, fib_addr, pi, ci;
1510 1.1 ad
1511 1.21.2.3 yamt fib_size = le16toh(ac->ac_fib->Header.Size);
1512 1.21.2.3 yamt fib_addr = le32toh(ac->ac_fib->Header.ReceiverFibAddress);
1513 1.1 ad
1514 1.1 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1515 1.21.2.3 yamt (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1516 1.1 ad sizeof(sc->sc_common->ac_qbuf),
1517 1.1 ad BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1518 1.1 ad
1519 1.1 ad /* Get the producer/consumer indices. */
1520 1.1 ad pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1521 1.1 ad ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1522 1.1 ad
1523 1.1 ad /* Wrap the queue? */
1524 1.1 ad if (pi >= aac_qinfo[queue].size)
1525 1.1 ad pi = 0;
1526 1.1 ad
1527 1.1 ad /* Check for queue full. */
1528 1.1 ad if ((pi + 1) == ci)
1529 1.1 ad return (EAGAIN);
1530 1.1 ad
1531 1.1 ad /* Populate queue entry. */
1532 1.1 ad (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
1533 1.1 ad (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
1534 1.1 ad
1535 1.1 ad /* Update producer index. */
1536 1.1 ad sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
1537 1.1 ad
1538 1.1 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1539 1.21.2.3 yamt (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1540 1.1 ad sizeof(sc->sc_common->ac_qbuf),
1541 1.1 ad BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1542 1.1 ad
1543 1.1 ad /* Notify the adapter if we know how. */
1544 1.1 ad if (aac_qinfo[queue].notify != 0)
1545 1.1 ad AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1546 1.1 ad
1547 1.1 ad return (0);
1548 1.1 ad }
1549 1.1 ad
1550 1.1 ad /*
1551 1.1 ad * Atomically remove one entry from the nominated queue, returns 0 on success
1552 1.1 ad * or ENOENT if the queue is empty.
1553 1.1 ad */
1554 1.12 thorpej static int
1555 1.1 ad aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
1556 1.1 ad struct aac_fib **fib_addr)
1557 1.1 ad {
1558 1.21.2.3 yamt struct aac_fibmap *fm;
1559 1.21.2.3 yamt struct aac_ccb *ac;
1560 1.21.2.3 yamt u_int32_t pi, ci, idx;
1561 1.1 ad int notify;
1562 1.1 ad
1563 1.1 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1564 1.21.2.3 yamt (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1565 1.1 ad sizeof(sc->sc_common->ac_qbuf),
1566 1.1 ad BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1567 1.1 ad
1568 1.1 ad /* Get the producer/consumer indices. */
1569 1.1 ad pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1570 1.1 ad ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1571 1.1 ad
1572 1.1 ad /* Check for queue empty. */
1573 1.1 ad if (ci == pi)
1574 1.1 ad return (ENOENT);
1575 1.1 ad
1576 1.1 ad notify = 0;
1577 1.1 ad if (ci == pi + 1)
1578 1.1 ad notify = 1;
1579 1.1 ad
1580 1.1 ad /* Wrap the queue? */
1581 1.1 ad if (ci >= aac_qinfo[queue].size)
1582 1.1 ad ci = 0;
1583 1.1 ad
1584 1.1 ad /* Fetch the entry. */
1585 1.1 ad *fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size);
1586 1.21.2.3 yamt
1587 1.21.2.3 yamt switch (queue) {
1588 1.21.2.3 yamt case AAC_HOST_NORM_CMD_QUEUE:
1589 1.21.2.3 yamt case AAC_HOST_HIGH_CMD_QUEUE:
1590 1.21.2.3 yamt idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
1591 1.21.2.3 yamt idx /= sizeof(struct aac_fib);
1592 1.21.2.3 yamt *fib_addr = &sc->sc_common->ac_fibs[idx];
1593 1.21.2.3 yamt break;
1594 1.21.2.3 yamt case AAC_HOST_NORM_RESP_QUEUE:
1595 1.21.2.3 yamt case AAC_HOST_HIGH_RESP_QUEUE:
1596 1.21.2.3 yamt idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
1597 1.21.2.3 yamt ac = sc->sc_ccbs + (idx >> 2);
1598 1.21.2.3 yamt *fib_addr = ac->ac_fib;
1599 1.21.2.3 yamt if (idx & 0x01) {
1600 1.21.2.3 yamt fm = ac->ac_fibmap;
1601 1.21.2.3 yamt bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
1602 1.21.2.3 yamt (char *)ac->ac_fib - (char *)fm->fm_fibs,
1603 1.21.2.3 yamt sc->sc_max_fib_size,
1604 1.21.2.3 yamt BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1605 1.21.2.3 yamt ac->ac_fib->Header.XferState |=
1606 1.21.2.3 yamt htole32(AAC_FIBSTATE_DONEADAP);
1607 1.21.2.3 yamt *((u_int32_t*)(ac->ac_fib->data)) =
1608 1.21.2.3 yamt htole32(AAC_ERROR_NORMAL);
1609 1.21.2.3 yamt }
1610 1.21.2.3 yamt break;
1611 1.21.2.3 yamt default:
1612 1.21.2.3 yamt panic("Invalid queue in aac_dequeue_fib()");
1613 1.21.2.3 yamt break;
1614 1.21.2.3 yamt }
1615 1.1 ad
1616 1.1 ad /* Update consumer index. */
1617 1.1 ad sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
1618 1.1 ad
1619 1.1 ad bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1620 1.21.2.3 yamt (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1621 1.1 ad sizeof(sc->sc_common->ac_qbuf),
1622 1.1 ad BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1623 1.1 ad
1624 1.1 ad /* If we have made the queue un-full, notify the adapter. */
1625 1.1 ad if (notify && (aac_qinfo[queue].notify != 0))
1626 1.1 ad AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1627 1.1 ad
1628 1.1 ad return (0);
1629 1.1 ad }
1630 1.1 ad
1631 1.21.2.3 yamt /*
1632 1.21.2.3 yamt * Put our response to an adapter-initiated fib (AIF) on the response queue.
1633 1.21.2.3 yamt */
1634 1.21.2.3 yamt static int
1635 1.21.2.3 yamt aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
1636 1.21.2.3 yamt {
1637 1.21.2.3 yamt u_int32_t fib_size, fib_addr, pi, ci;
1638 1.21.2.3 yamt
1639 1.21.2.3 yamt fib_size = le16toh(fib->Header.Size);
1640 1.21.2.3 yamt fib_addr = fib->Header.SenderFibAddress;
1641 1.21.2.3 yamt fib->Header.ReceiverFibAddress = fib_addr;
1642 1.21.2.3 yamt
1643 1.21.2.3 yamt bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1644 1.21.2.3 yamt (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1645 1.21.2.3 yamt sizeof(sc->sc_common->ac_qbuf),
1646 1.21.2.3 yamt BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1647 1.21.2.3 yamt
1648 1.21.2.3 yamt /* Get the producer/consumer indices. */
1649 1.21.2.3 yamt pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1650 1.21.2.3 yamt ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1651 1.21.2.3 yamt
1652 1.21.2.3 yamt /* Wrap the queue? */
1653 1.21.2.3 yamt if (pi >= aac_qinfo[queue].size)
1654 1.21.2.3 yamt pi = 0;
1655 1.21.2.3 yamt
1656 1.21.2.3 yamt /* Check for queue full. */
1657 1.21.2.3 yamt if ((pi + 1) == ci)
1658 1.21.2.3 yamt return (EAGAIN);
1659 1.21.2.3 yamt
1660 1.21.2.3 yamt /* Populate queue entry. */
1661 1.21.2.3 yamt (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
1662 1.21.2.3 yamt (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
1663 1.21.2.3 yamt
1664 1.21.2.3 yamt /* Update producer index. */
1665 1.21.2.3 yamt sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
1666 1.21.2.3 yamt
1667 1.21.2.3 yamt bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1668 1.21.2.3 yamt (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1669 1.21.2.3 yamt sizeof(sc->sc_common->ac_qbuf),
1670 1.21.2.3 yamt BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1671 1.21.2.3 yamt
1672 1.21.2.3 yamt /* Notify the adapter if we know how. */
1673 1.21.2.3 yamt if (aac_qinfo[queue].notify != 0)
1674 1.21.2.3 yamt AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1675 1.21.2.3 yamt
1676 1.21.2.3 yamt return (0);
1677 1.21.2.3 yamt }
1678 1.21.2.3 yamt
1679 1.1 ad #ifdef AAC_DEBUG
1680 1.1 ad /*
1681 1.1 ad * Print a FIB
1682 1.1 ad */
1683 1.12 thorpej static void
1684 1.21.2.2 yamt aac_print_fib(struct aac_softc *sc, struct aac_fib *fib,
1685 1.21.2.2 yamt const char *caller)
1686 1.1 ad {
1687 1.1 ad struct aac_blockread *br;
1688 1.1 ad struct aac_blockwrite *bw;
1689 1.1 ad struct aac_sg_table *sg;
1690 1.19 christos char tbuf[512];
1691 1.1 ad int i;
1692 1.1 ad
1693 1.1 ad printf("%s: FIB @ %p\n", caller, fib);
1694 1.1 ad bitmask_snprintf(le32toh(fib->Header.XferState),
1695 1.1 ad "\20"
1696 1.1 ad "\1HOSTOWNED"
1697 1.1 ad "\2ADAPTEROWNED"
1698 1.1 ad "\3INITIALISED"
1699 1.1 ad "\4EMPTY"
1700 1.1 ad "\5FROMPOOL"
1701 1.1 ad "\6FROMHOST"
1702 1.1 ad "\7FROMADAP"
1703 1.1 ad "\10REXPECTED"
1704 1.1 ad "\11RNOTEXPECTED"
1705 1.1 ad "\12DONEADAP"
1706 1.1 ad "\13DONEHOST"
1707 1.1 ad "\14HIGH"
1708 1.1 ad "\15NORM"
1709 1.1 ad "\16ASYNC"
1710 1.1 ad "\17PAGEFILEIO"
1711 1.1 ad "\20SHUTDOWN"
1712 1.1 ad "\21LAZYWRITE"
1713 1.1 ad "\22ADAPMICROFIB"
1714 1.1 ad "\23BIOSFIB"
1715 1.1 ad "\24FAST_RESPONSE"
1716 1.1 ad "\25APIFIB\n",
1717 1.19 christos tbuf,
1718 1.19 christos sizeof(tbuf));
1719 1.1 ad
1720 1.19 christos printf(" XferState %s\n", tbuf);
1721 1.1 ad printf(" Command %d\n", le16toh(fib->Header.Command));
1722 1.1 ad printf(" StructType %d\n", fib->Header.StructType);
1723 1.1 ad printf(" Flags 0x%x\n", fib->Header.Flags);
1724 1.1 ad printf(" Size %d\n", le16toh(fib->Header.Size));
1725 1.1 ad printf(" SenderSize %d\n", le16toh(fib->Header.SenderSize));
1726 1.1 ad printf(" SenderAddress 0x%x\n",
1727 1.1 ad le32toh(fib->Header.SenderFibAddress));
1728 1.1 ad printf(" ReceiverAddress 0x%x\n",
1729 1.1 ad le32toh(fib->Header.ReceiverFibAddress));
1730 1.1 ad printf(" SenderData 0x%x\n", fib->Header.SenderData);
1731 1.1 ad
1732 1.1 ad switch (fib->Header.Command) {
1733 1.1 ad case ContainerCommand: {
1734 1.1 ad br = (struct aac_blockread *)fib->data;
1735 1.1 ad bw = (struct aac_blockwrite *)fib->data;
1736 1.1 ad sg = NULL;
1737 1.1 ad
1738 1.1 ad if (le32toh(br->Command) == VM_CtBlockRead) {
1739 1.16 perry printf(" BlockRead: container %d 0x%x/%d\n",
1740 1.1 ad le32toh(br->ContainerId), le32toh(br->BlockNumber),
1741 1.1 ad le32toh(br->ByteCount));
1742 1.1 ad sg = &br->SgMap;
1743 1.1 ad }
1744 1.1 ad if (le32toh(bw->Command) == VM_CtBlockWrite) {
1745 1.16 perry printf(" BlockWrite: container %d 0x%x/%d (%s)\n",
1746 1.1 ad le32toh(bw->ContainerId), le32toh(bw->BlockNumber),
1747 1.1 ad le32toh(bw->ByteCount),
1748 1.1 ad le32toh(bw->Stable) == CSTABLE ?
1749 1.1 ad "stable" : "unstable");
1750 1.1 ad sg = &bw->SgMap;
1751 1.1 ad }
1752 1.1 ad if (sg != NULL) {
1753 1.1 ad printf(" %d s/g entries\n", le32toh(sg->SgCount));
1754 1.1 ad for (i = 0; i < le32toh(sg->SgCount); i++)
1755 1.1 ad printf(" 0x%08x/%d\n",
1756 1.1 ad le32toh(sg->SgEntry[i].SgAddress),
1757 1.1 ad le32toh(sg->SgEntry[i].SgByteCount));
1758 1.1 ad }
1759 1.1 ad break;
1760 1.1 ad }
1761 1.1 ad default:
1762 1.21.2.1 yamt // dump first 32 bytes of fib->data
1763 1.21.2.1 yamt printf(" Raw data:");
1764 1.21.2.1 yamt for (i = 0; i < 32; i++)
1765 1.21.2.1 yamt printf(" %02x", fib->data[i]);
1766 1.21.2.1 yamt printf("\n");
1767 1.1 ad break;
1768 1.1 ad }
1769 1.1 ad }
1770 1.12 thorpej #endif /* AAC_DEBUG */
1771