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