Clean up the namespace of <sys/timeb.h>.
[dragonfly.git] / sys / dev / raid / aac / aac.c
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 2000 Michael Smith
3 * Copyright (c) 2001 Scott Long
4 * Copyright (c) 2000 BSDi
5 * Copyright (c) 2001 Adaptec, Inc.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
b4df2201 29 * $FreeBSD: head/sys/dev/aac/aac.c 260044 2013-12-29 17:37:32Z marius $
984263bc
MD
30 */
31
32/*
33 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
34 */
d9773475 35#define AAC_DRIVERNAME "aac"
984263bc
MD
36
37#include "opt_aac.h"
38
39/* #include <stddef.h> */
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/malloc.h>
43#include <sys/kernel.h>
44#include <sys/kthread.h>
e9ae7f4f 45#include <sys/poll.h>
984263bc
MD
46
47#include <sys/bus.h>
48#include <sys/conf.h>
984263bc
MD
49#include <sys/signalvar.h>
50#include <sys/time.h>
51#include <sys/eventhandler.h>
d9773475
PA
52#include <sys/rman.h>
53
e9ae7f4f
SW
54#include <sys/bus_dma.h>
55#include <sys/device.h>
684a93c4
MD
56#include <sys/mplock2.h>
57
d9773475
PA
58#include <bus/pci/pcireg.h>
59#include <bus/pci/pcivar.h>
984263bc 60
e9ae7f4f
SW
61#include <dev/raid/aac/aacreg.h>
62#include <dev/raid/aac/aac_ioctl.h>
63#include <dev/raid/aac/aacvar.h>
64#include <dev/raid/aac/aac_tables.h>
984263bc
MD
65
66static void aac_startup(void *arg);
67static void aac_add_container(struct aac_softc *sc,
68 struct aac_mntinforesp *mir, int f);
69static void aac_get_bus_info(struct aac_softc *sc);
e9ae7f4f 70static void aac_daemon(void *arg);
984263bc
MD
71
72/* Command Processing */
e9ae7f4f 73static void aac_timeout(struct aac_softc *sc);
984263bc
MD
74static void aac_complete(void *context, int pending);
75static int aac_bio_command(struct aac_softc *sc, struct aac_command **cmp);
76static void aac_bio_complete(struct aac_command *cm);
d9773475 77static int aac_wait_command(struct aac_command *cm);
cd8ab232 78static void aac_command_thread(void *arg);
984263bc
MD
79
80/* Command Buffer Management */
d9773475
PA
81static void aac_map_command_sg(void *arg, bus_dma_segment_t *segs,
82 int nseg, int error);
984263bc
MD
83static void aac_map_command_helper(void *arg, bus_dma_segment_t *segs,
84 int nseg, int error);
85static int aac_alloc_commands(struct aac_softc *sc);
86static void aac_free_commands(struct aac_softc *sc);
984263bc
MD
87static void aac_unmap_command(struct aac_command *cm);
88
89/* Hardware Interface */
e9ae7f4f 90static int aac_alloc(struct aac_softc *sc);
984263bc
MD
91static void aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg,
92 int error);
93static int aac_check_firmware(struct aac_softc *sc);
94static int aac_init(struct aac_softc *sc);
95static int aac_sync_command(struct aac_softc *sc, u_int32_t command,
96 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
97 u_int32_t arg3, u_int32_t *sp);
e9ae7f4f 98static int aac_setup_intr(struct aac_softc *sc);
984263bc
MD
99static int aac_enqueue_fib(struct aac_softc *sc, int queue,
100 struct aac_command *cm);
101static int aac_dequeue_fib(struct aac_softc *sc, int queue,
102 u_int32_t *fib_size, struct aac_fib **fib_addr);
103static int aac_enqueue_response(struct aac_softc *sc, int queue,
104 struct aac_fib *fib);
105
984263bc
MD
106/* StrongARM interface */
107static int aac_sa_get_fwstatus(struct aac_softc *sc);
108static void aac_sa_qnotify(struct aac_softc *sc, int qbit);
109static int aac_sa_get_istatus(struct aac_softc *sc);
110static void aac_sa_clear_istatus(struct aac_softc *sc, int mask);
111static void aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
112 u_int32_t arg0, u_int32_t arg1,
113 u_int32_t arg2, u_int32_t arg3);
114static int aac_sa_get_mailbox(struct aac_softc *sc, int mb);
115static void aac_sa_set_interrupts(struct aac_softc *sc, int enable);
116
b4df2201 117const struct aac_interface aac_sa_interface = {
984263bc
MD
118 aac_sa_get_fwstatus,
119 aac_sa_qnotify,
120 aac_sa_get_istatus,
121 aac_sa_clear_istatus,
122 aac_sa_set_mailbox,
123 aac_sa_get_mailbox,
d9773475
PA
124 aac_sa_set_interrupts,
125 NULL, NULL, NULL
984263bc
MD
126};
127
d9773475 128/* i960Rx interface */
984263bc
MD
129static int aac_rx_get_fwstatus(struct aac_softc *sc);
130static void aac_rx_qnotify(struct aac_softc *sc, int qbit);
131static int aac_rx_get_istatus(struct aac_softc *sc);
132static void aac_rx_clear_istatus(struct aac_softc *sc, int mask);
133static void aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command,
134 u_int32_t arg0, u_int32_t arg1,
135 u_int32_t arg2, u_int32_t arg3);
136static int aac_rx_get_mailbox(struct aac_softc *sc, int mb);
137static void aac_rx_set_interrupts(struct aac_softc *sc, int enable);
d9773475
PA
138static int aac_rx_send_command(struct aac_softc *sc, struct aac_command *cm);
139static int aac_rx_get_outb_queue(struct aac_softc *sc);
140static void aac_rx_set_outb_queue(struct aac_softc *sc, int index);
984263bc 141
b4df2201 142const struct aac_interface aac_rx_interface = {
984263bc
MD
143 aac_rx_get_fwstatus,
144 aac_rx_qnotify,
145 aac_rx_get_istatus,
146 aac_rx_clear_istatus,
147 aac_rx_set_mailbox,
148 aac_rx_get_mailbox,
d9773475
PA
149 aac_rx_set_interrupts,
150 aac_rx_send_command,
151 aac_rx_get_outb_queue,
152 aac_rx_set_outb_queue
153};
154
155/* Rocket/MIPS interface */
156static int aac_rkt_get_fwstatus(struct aac_softc *sc);
157static void aac_rkt_qnotify(struct aac_softc *sc, int qbit);
158static int aac_rkt_get_istatus(struct aac_softc *sc);
159static void aac_rkt_clear_istatus(struct aac_softc *sc, int mask);
160static void aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command,
161 u_int32_t arg0, u_int32_t arg1,
162 u_int32_t arg2, u_int32_t arg3);
163static int aac_rkt_get_mailbox(struct aac_softc *sc, int mb);
164static void aac_rkt_set_interrupts(struct aac_softc *sc, int enable);
165static int aac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm);
166static int aac_rkt_get_outb_queue(struct aac_softc *sc);
167static void aac_rkt_set_outb_queue(struct aac_softc *sc, int index);
168
b4df2201 169const struct aac_interface aac_rkt_interface = {
d9773475
PA
170 aac_rkt_get_fwstatus,
171 aac_rkt_qnotify,
172 aac_rkt_get_istatus,
173 aac_rkt_clear_istatus,
174 aac_rkt_set_mailbox,
175 aac_rkt_get_mailbox,
176 aac_rkt_set_interrupts,
177 aac_rkt_send_command,
178 aac_rkt_get_outb_queue,
179 aac_rkt_set_outb_queue
984263bc
MD
180};
181
182/* Debugging and Diagnostics */
b4df2201
SW
183static void aac_describe_controller(struct aac_softc *sc);
184static const char *aac_describe_code(const struct aac_code_lookup *table,
984263bc
MD
185 u_int32_t code);
186
187/* Management Interface */
188static d_open_t aac_open;
189static d_close_t aac_close;
190static d_ioctl_t aac_ioctl;
eda1a08c
SG
191static d_kqfilter_t aac_kqfilter;
192static void aac_filter_detach(struct knote *kn);
e9ae7f4f
SW
193static int aac_filter_read(struct knote *kn, long hint);
194static int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib);
195static int aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg);
984263bc
MD
196static void aac_handle_aif(struct aac_softc *sc,
197 struct aac_fib *fib);
198static int aac_rev_check(struct aac_softc *sc, caddr_t udata);
e9ae7f4f
SW
199static int aac_open_aif(struct aac_softc *sc, caddr_t arg);
200static int aac_close_aif(struct aac_softc *sc, caddr_t arg);
984263bc 201static int aac_getnext_aif(struct aac_softc *sc, caddr_t arg);
e9ae7f4f
SW
202static int aac_return_aif(struct aac_softc *sc,
203 struct aac_fib_context *ctx, caddr_t uptr);
984263bc 204static int aac_query_disk(struct aac_softc *sc, caddr_t uptr);
d9773475 205static int aac_get_pci_info(struct aac_softc *sc, caddr_t uptr);
e9ae7f4f 206static int aac_supported_features(struct aac_softc *sc, caddr_t uptr);
d9773475 207static void aac_ioctl_event(struct aac_softc *sc,
e9ae7f4f
SW
208 struct aac_event *event, void *arg);
209static struct aac_mntinforesp *
210 aac_get_container_info(struct aac_softc *sc, struct aac_fib *fib, int cid);
211
fef8985e 212static struct dev_ops aac_ops = {
88abd8b5 213 { "aac", 0, 0 },
fef8985e
MD
214 .d_open = aac_open,
215 .d_close = aac_close,
216 .d_ioctl = aac_ioctl,
eda1a08c 217 .d_kqfilter = aac_kqfilter
984263bc
MD
218};
219
7f8935d3 220static MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for the AAC driver");
984263bc
MD
221
222/* sysctl node */
b4df2201 223SYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters");
984263bc
MD
224
225/*
226 * Device Interface
227 */
228
229/*
e9ae7f4f 230 * Initialize the controller and softc
984263bc
MD
231 */
232int
233aac_attach(struct aac_softc *sc)
234{
235 int error, unit;
236
e9ae7f4f 237 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
238
239 /*
e9ae7f4f 240 * Initialize per-controller queues.
984263bc
MD
241 */
242 aac_initq_free(sc);
243 aac_initq_ready(sc);
244 aac_initq_busy(sc);
984263bc
MD
245 aac_initq_bio(sc);
246
984263bc 247 /*
e9ae7f4f 248 * Initialize command-completion task.
984263bc
MD
249 */
250 TASK_INIT(&sc->aac_task_complete, 0, aac_complete, sc);
984263bc
MD
251
252 /* mark controller as suspended until we get ourselves organised */
253 sc->aac_state |= AAC_STATE_SUSPEND;
254
255 /*
256 * Check that the firmware on the card is supported.
257 */
258 if ((error = aac_check_firmware(sc)) != 0)
259 return(error);
260
d9773475
PA
261 /*
262 * Initialize locks
263 */
e9ae7f4f
SW
264 lockinit(&sc->aac_aifq_lock, "AAC AIF lock", 0, LK_CANRECURSE);
265 lockinit(&sc->aac_io_lock, "AAC I/O lock", 0, LK_CANRECURSE);
266 lockinit(&sc->aac_container_lock, "AAC container lock", 0, LK_CANRECURSE);
d9773475
PA
267 TAILQ_INIT(&sc->aac_container_tqh);
268 TAILQ_INIT(&sc->aac_ev_cmfree);
269
e9ae7f4f 270 /* Initialize the clock daemon callout. */
b4df2201 271 callout_init_mp(&sc->aac_daemontime);
984263bc
MD
272
273 /*
e9ae7f4f 274 * Initialize the adapter.
984263bc 275 */
e9ae7f4f
SW
276 if ((error = aac_alloc(sc)) != 0)
277 return(error);
984263bc
MD
278 if ((error = aac_init(sc)) != 0)
279 return(error);
280
d9773475
PA
281 /*
282 * Allocate and connect our interrupt.
984263bc 283 */
e9ae7f4f
SW
284 if ((error = aac_setup_intr(sc)) != 0)
285 return(error);
984263bc
MD
286
287 /*
d9773475 288 * Print a little information about the controller.
984263bc 289 */
d9773475 290 aac_describe_controller(sc);
984263bc 291
7f8935d3
SW
292 /*
293 * Add sysctls.
294 */
26595b18
SW
295 SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->aac_dev),
296 SYSCTL_CHILDREN(device_get_sysctl_tree(sc->aac_dev)),
7f8935d3
SW
297 OID_AUTO, "firmware_build", CTLFLAG_RD,
298 &sc->aac_revision.buildNumber, 0,
299 "firmware build number");
300
984263bc 301 /*
d9773475 302 * Register to probe our containers later.
984263bc 303 */
984263bc
MD
304 sc->aac_ich.ich_func = aac_startup;
305 sc->aac_ich.ich_arg = sc;
52800c9d 306 sc->aac_ich.ich_desc = "aac";
984263bc
MD
307 if (config_intrhook_establish(&sc->aac_ich) != 0) {
308 device_printf(sc->aac_dev,
309 "can't establish configuration hook\n");
310 return(ENXIO);
311 }
312
313 /*
314 * Make the control device.
315 */
316 unit = device_get_unit(sc->aac_dev);
3e82b46c
MD
317 sc->aac_dev_t = make_dev(&aac_ops, unit, UID_ROOT, GID_OPERATOR,
318 0640, "aac%d", unit);
e9ae7f4f
SW
319 (void)make_dev_alias(sc->aac_dev_t, "afa%d", unit);
320 (void)make_dev_alias(sc->aac_dev_t, "hpn%d", unit);
984263bc
MD
321 sc->aac_dev_t->si_drv1 = sc;
322
323 /* Create the AIF thread */
cd8ab232 324 if (kthread_create(aac_command_thread, sc,
984263bc 325 &sc->aifthread, "aac%daif", unit))
e9ae7f4f 326 panic("Could not create AIF thread");
984263bc
MD
327
328 /* Register the shutdown method to only be called post-dump */
e9ae7f4f
SW
329 if ((sc->eh = EVENTHANDLER_REGISTER(shutdown_final, aac_shutdown,
330 sc->aac_dev, SHUTDOWN_PRI_DEFAULT)) == NULL)
d9773475
PA
331 device_printf(sc->aac_dev,
332 "shutdown event registration failed\n");
984263bc
MD
333
334 /* Register with CAM for the non-DASD devices */
d9773475
PA
335 if ((sc->flags & AAC_FLAGS_ENABLE_CAM) != 0) {
336 TAILQ_INIT(&sc->aac_sim_tqh);
984263bc 337 aac_get_bus_info(sc);
d9773475 338 }
984263bc 339
e9ae7f4f
SW
340 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
341 callout_reset(&sc->aac_daemontime, 60 * hz, aac_daemon, sc);
342 lockmgr(&sc->aac_io_lock, LK_RELEASE);
343
984263bc
MD
344 return(0);
345}
346
e9ae7f4f
SW
347static void
348aac_daemon(void *arg)
349{
350 struct timeval tv;
351 struct aac_softc *sc;
352 struct aac_fib *fib;
353
354 sc = arg;
355 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
356
357 if (callout_pending(&sc->aac_daemontime) ||
1487a3d5
SW
358 callout_active(&sc->aac_daemontime) == 0) {
359 lockmgr(&sc->aac_io_lock, LK_RELEASE);
e9ae7f4f 360 return;
1487a3d5 361 }
e9ae7f4f
SW
362 getmicrotime(&tv);
363 aac_alloc_sync_fib(sc, &fib);
364 *(uint32_t *)fib->data = tv.tv_sec;
365 aac_sync_fib(sc, SendHostTime, 0, fib, sizeof(uint32_t));
366 aac_release_sync_fib(sc);
e9ae7f4f 367 callout_reset(&sc->aac_daemontime, 30 * 60 * hz, aac_daemon, sc);
b4df2201 368 lockmgr(&sc->aac_io_lock, LK_RELEASE);
e9ae7f4f
SW
369}
370
d9773475
PA
371void
372aac_add_event(struct aac_softc *sc, struct aac_event *event)
373{
374
375 switch (event->ev_type & AAC_EVENT_MASK) {
376 case AAC_EVENT_CMFREE:
377 TAILQ_INSERT_TAIL(&sc->aac_ev_cmfree, event, ev_links);
378 break;
379 default:
380 device_printf(sc->aac_dev, "aac_add event: unknown event %d\n",
381 event->ev_type);
382 break;
383 }
d9773475
PA
384}
385
e9ae7f4f
SW
386/*
387 * Request information of container #cid
388 */
389static struct aac_mntinforesp *
390aac_get_container_info(struct aac_softc *sc, struct aac_fib *fib, int cid)
391{
392 struct aac_mntinfo *mi;
393
394 mi = (struct aac_mntinfo *)&fib->data[0];
395 /* use 64-bit LBA if enabled */
396 mi->Command = (sc->flags & AAC_FLAGS_LBA_64BIT) ?
397 VM_NameServe64 : VM_NameServe;
398 mi->MntType = FT_FILESYS;
399 mi->MntCount = cid;
400
401 if (aac_sync_fib(sc, ContainerCommand, 0, fib,
402 sizeof(struct aac_mntinfo))) {
403 device_printf(sc->aac_dev, "Error probing container %d\n", cid);
404 return (NULL);
405 }
406
407 return ((struct aac_mntinforesp *)&fib->data[0]);
408}
409
984263bc
MD
410/*
411 * Probe for containers, create disks.
412 */
413static void
414aac_startup(void *arg)
415{
416 struct aac_softc *sc;
417 struct aac_fib *fib;
e9ae7f4f 418 struct aac_mntinforesp *mir;
158dbeb8 419 int count = 0, i = 0;
984263bc
MD
420
421 sc = (struct aac_softc *)arg;
e9ae7f4f 422 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
423
424 /* disconnect ourselves from the intrhook chain */
425 config_intrhook_disestablish(&sc->aac_ich);
426
e9ae7f4f 427 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
d9773475 428 aac_alloc_sync_fib(sc, &fib);
984263bc
MD
429
430 /* loop over possible containers */
431 do {
e9ae7f4f 432 if ((mir = aac_get_container_info(sc, fib, i)) == NULL)
984263bc 433 continue;
e9ae7f4f
SW
434 if (i == 0)
435 count = mir->MntRespCount;
984263bc
MD
436 aac_add_container(sc, mir, 0);
437 i++;
158dbeb8 438 } while ((i < count) && (i < AAC_MAX_CONTAINERS));
984263bc
MD
439
440 aac_release_sync_fib(sc);
e9ae7f4f 441 lockmgr(&sc->aac_io_lock, LK_RELEASE);
984263bc
MD
442
443 /* poke the bus to actually attach the child devices */
444 if (bus_generic_attach(sc->aac_dev))
445 device_printf(sc->aac_dev, "bus_generic_attach failed\n");
446
447 /* mark the controller up */
448 sc->aac_state &= ~AAC_STATE_SUSPEND;
449
450 /* enable interrupts now */
451 AAC_UNMASK_INTERRUPTS(sc);
984263bc
MD
452}
453
454/*
e9ae7f4f 455 * Create a device to represent a new container
984263bc
MD
456 */
457static void
458aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f)
459{
460 struct aac_container *co;
461 device_t child;
462
d9773475 463 /*
984263bc
MD
464 * Check container volume type for validity. Note that many of
465 * the possible types may never show up.
466 */
467 if ((mir->Status == ST_OK) && (mir->MntTable[0].VolType != CT_NONE)) {
d9773475
PA
468 co = (struct aac_container *)kmalloc(sizeof *co, M_AACBUF,
469 M_INTWAIT | M_ZERO);
e9ae7f4f 470 fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "id %x name '%.16s' size %u type %d",
984263bc
MD
471 mir->MntTable[0].ObjectId,
472 mir->MntTable[0].FileSystemName,
473 mir->MntTable[0].Capacity, mir->MntTable[0].VolType);
d9773475 474
984263bc
MD
475 if ((child = device_add_child(sc->aac_dev, "aacd", -1)) == NULL)
476 device_printf(sc->aac_dev, "device_add_child failed\n");
477 else
478 device_set_ivars(child, co);
479 device_set_desc(child, aac_describe_code(aac_container_types,
480 mir->MntTable[0].VolType));
481 co->co_disk = child;
482 co->co_found = f;
483 bcopy(&mir->MntTable[0], &co->co_mntobj,
484 sizeof(struct aac_mntobj));
e9ae7f4f 485 lockmgr(&sc->aac_container_lock, LK_EXCLUSIVE);
984263bc 486 TAILQ_INSERT_TAIL(&sc->aac_container_tqh, co, co_link);
e9ae7f4f
SW
487 lockmgr(&sc->aac_container_lock, LK_RELEASE);
488 }
489}
490
491/*
492 * Allocate resources associated with (sc)
493 */
494static int
495aac_alloc(struct aac_softc *sc)
496{
497
498 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
499
500 /*
501 * Create DMA tag for mapping buffers into controller-addressable space.
502 */
503 if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */
504 1, 0, /* algnmnt, boundary */
505 (sc->flags & AAC_FLAGS_SG_64BIT) ?
506 BUS_SPACE_MAXADDR :
507 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
508 BUS_SPACE_MAXADDR, /* highaddr */
509 NULL, NULL, /* filter, filterarg */
510 MAXBSIZE, /* maxsize */
511 sc->aac_sg_tablesize, /* nsegments */
512 MAXBSIZE, /* maxsegsize */
513 BUS_DMA_ALLOCNOW, /* flags */
514 &sc->aac_buffer_dmat)) {
515 device_printf(sc->aac_dev, "can't allocate buffer DMA tag\n");
516 return (ENOMEM);
517 }
518
519 /*
520 * Create DMA tag for mapping FIBs into controller-addressable space..
521 */
522 if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */
523 1, 0, /* algnmnt, boundary */
524 (sc->flags & AAC_FLAGS_4GB_WINDOW) ?
525 BUS_SPACE_MAXADDR_32BIT :
526 0x7fffffff, /* lowaddr */
527 BUS_SPACE_MAXADDR, /* highaddr */
528 NULL, NULL, /* filter, filterarg */
529 sc->aac_max_fibs_alloc *
530 sc->aac_max_fib_size, /* maxsize */
531 1, /* nsegments */
532 sc->aac_max_fibs_alloc *
533 sc->aac_max_fib_size, /* maxsize */
534 0, /* flags */
535 &sc->aac_fib_dmat)) {
536 device_printf(sc->aac_dev, "can't allocate FIB DMA tag\n");
537 return (ENOMEM);
984263bc 538 }
e9ae7f4f
SW
539
540 /*
541 * Create DMA tag for the common structure and allocate it.
542 */
543 if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */
544 1, 0, /* algnmnt, boundary */
545 (sc->flags & AAC_FLAGS_4GB_WINDOW) ?
546 BUS_SPACE_MAXADDR_32BIT :
547 0x7fffffff, /* lowaddr */
548 BUS_SPACE_MAXADDR, /* highaddr */
549 NULL, NULL, /* filter, filterarg */
550 8192 + sizeof(struct aac_common), /* maxsize */
551 1, /* nsegments */
552 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
553 0, /* flags */
554 &sc->aac_common_dmat)) {
555 device_printf(sc->aac_dev,
556 "can't allocate common structure DMA tag\n");
557 return (ENOMEM);
558 }
559 if (bus_dmamem_alloc(sc->aac_common_dmat, (void **)&sc->aac_common,
560 BUS_DMA_NOWAIT, &sc->aac_common_dmamap)) {
561 device_printf(sc->aac_dev, "can't allocate common structure\n");
562 return (ENOMEM);
563 }
564
565 /*
566 * Work around a bug in the 2120 and 2200 that cannot DMA commands
567 * below address 8192 in physical memory.
568 * XXX If the padding is not needed, can it be put to use instead
569 * of ignored?
570 */
571 (void)bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap,
572 sc->aac_common, 8192 + sizeof(*sc->aac_common),
573 aac_common_map, sc, 0);
574
575 if (sc->aac_common_busaddr < 8192) {
576 sc->aac_common = (struct aac_common *)
577 ((uint8_t *)sc->aac_common + 8192);
578 sc->aac_common_busaddr += 8192;
579 }
580 bzero(sc->aac_common, sizeof(*sc->aac_common));
581
582 /* Allocate some FIBs and associated command structs */
583 TAILQ_INIT(&sc->aac_fibmap_tqh);
584 sc->aac_commands = kmalloc(sc->aac_max_fibs * sizeof(struct aac_command),
585 M_AACBUF, M_WAITOK|M_ZERO);
586 while (sc->total_fibs < sc->aac_max_fibs) {
587 if (aac_alloc_commands(sc) != 0)
588 break;
589 }
590 if (sc->total_fibs == 0)
591 return (ENOMEM);
592
593 return (0);
984263bc
MD
594}
595
596/*
597 * Free all of the resources associated with (sc)
598 *
599 * Should not be called if the controller is active.
600 */
601void
602aac_free(struct aac_softc *sc)
603{
d9773475 604
e9ae7f4f 605 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
606
607 /* remove the control device */
608 if (sc->aac_dev_t != NULL)
609 destroy_dev(sc->aac_dev_t);
610
611 /* throw away any FIB buffers, discard the FIB DMA tag */
d9773475 612 aac_free_commands(sc);
984263bc
MD
613 if (sc->aac_fib_dmat)
614 bus_dma_tag_destroy(sc->aac_fib_dmat);
615
d9773475
PA
616 kfree(sc->aac_commands, M_AACBUF);
617
984263bc
MD
618 /* destroy the common area */
619 if (sc->aac_common) {
620 bus_dmamap_unload(sc->aac_common_dmat, sc->aac_common_dmamap);
621 bus_dmamem_free(sc->aac_common_dmat, sc->aac_common,
622 sc->aac_common_dmamap);
623 }
624 if (sc->aac_common_dmat)
625 bus_dma_tag_destroy(sc->aac_common_dmat);
626
627 /* disconnect the interrupt handler */
628 if (sc->aac_intr)
629 bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr);
b4df2201
SW
630 if (sc->aac_irq != NULL) {
631 bus_release_resource(sc->aac_dev, SYS_RES_IRQ,
632 rman_get_rid(sc->aac_irq), sc->aac_irq);
633 if (sc->aac_irq_type == PCI_INTR_TYPE_MSI)
634 pci_release_msi(sc->aac_dev);
635 }
984263bc
MD
636
637 /* destroy data-transfer DMA tag */
638 if (sc->aac_buffer_dmat)
639 bus_dma_tag_destroy(sc->aac_buffer_dmat);
640
641 /* destroy the parent DMA tag */
642 if (sc->aac_parent_dmat)
643 bus_dma_tag_destroy(sc->aac_parent_dmat);
644
645 /* release the register window mapping */
e9ae7f4f 646 if (sc->aac_regs_res0 != NULL)
984263bc 647 bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
b4df2201 648 rman_get_rid(sc->aac_regs_res0), sc->aac_regs_res0);
e9ae7f4f
SW
649 if (sc->aac_hwif == AAC_HWIF_NARK && sc->aac_regs_res1 != NULL)
650 bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
b4df2201 651 rman_get_rid(sc->aac_regs_res1), sc->aac_regs_res1);
cd29885a 652 dev_ops_remove_minor(&aac_ops, device_get_unit(sc->aac_dev));
984263bc
MD
653}
654
655/*
656 * Disconnect from the controller completely, in preparation for unload.
657 */
658int
659aac_detach(device_t dev)
660{
661 struct aac_softc *sc;
d9773475
PA
662 struct aac_container *co;
663 struct aac_sim *sim;
984263bc 664 int error;
984263bc 665
984263bc 666 sc = device_get_softc(dev);
e9ae7f4f 667 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 668
eb67213a 669 callout_terminate(&sc->aac_daemontime);
7f8935d3
SW
670
671 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
672 while (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
673 sc->aifflags |= AAC_AIFFLAGS_EXIT;
674 wakeup(sc->aifthread);
675 lksleep(sc->aac_dev, &sc->aac_io_lock, 0, "aacdch", 0);
676 }
677 lockmgr(&sc->aac_io_lock, LK_RELEASE);
678 KASSERT((sc->aifflags & AAC_AIFFLAGS_RUNNING) == 0,
679 ("%s: invalid detach state", __func__));
d9773475
PA
680
681 /* Remove the child containers */
682 while ((co = TAILQ_FIRST(&sc->aac_container_tqh)) != NULL) {
683 error = device_delete_child(dev, co->co_disk);
684 if (error)
685 return (error);
686 TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link);
687 kfree(co, M_AACBUF);
688 }
689
690 /* Remove the CAM SIMs */
691 while ((sim = TAILQ_FIRST(&sc->aac_sim_tqh)) != NULL) {
692 TAILQ_REMOVE(&sc->aac_sim_tqh, sim, sim_link);
693 error = device_delete_child(dev, sim->sim_dev);
694 if (error)
695 return (error);
696 kfree(sim, M_AACBUF);
697 }
984263bc 698
984263bc
MD
699 if ((error = aac_shutdown(dev)))
700 return(error);
701
e9ae7f4f 702 EVENTHANDLER_DEREGISTER(shutdown_final, sc->eh);
d9773475 703
984263bc
MD
704 aac_free(sc);
705
d9773475
PA
706 lockuninit(&sc->aac_aifq_lock);
707 lockuninit(&sc->aac_io_lock);
708 lockuninit(&sc->aac_container_lock);
709
984263bc 710 return(0);
984263bc
MD
711}
712
713/*
714 * Bring the controller down to a dormant state and detach all child devices.
715 *
716 * This function is called before detach or system shutdown.
717 *
718 * Note that we can assume that the bioq on the controller is empty, as we won't
719 * allow shutdown if any device is open.
720 */
e9ae7f4f 721int
984263bc
MD
722aac_shutdown(device_t dev)
723{
724 struct aac_softc *sc;
725 struct aac_fib *fib;
726 struct aac_close_command *cc;
984263bc 727
984263bc 728 sc = device_get_softc(dev);
e9ae7f4f 729 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 730
984263bc
MD
731 sc->aac_state |= AAC_STATE_SUSPEND;
732
d9773475 733 /*
984263bc
MD
734 * Send a Container shutdown followed by a HostShutdown FIB to the
735 * controller to convince it that we don't want to talk to it anymore.
736 * We've been closed and all I/O completed already
737 */
738 device_printf(sc->aac_dev, "shutting down controller...");
739
e9ae7f4f 740 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
d9773475 741 aac_alloc_sync_fib(sc, &fib);
984263bc
MD
742 cc = (struct aac_close_command *)&fib->data[0];
743
744 bzero(cc, sizeof(struct aac_close_command));
745 cc->Command = VM_CloseAll;
746 cc->ContainerId = 0xffffffff;
747 if (aac_sync_fib(sc, ContainerCommand, 0, fib,
748 sizeof(struct aac_close_command)))
e3869ec7 749 kprintf("FAILED.\n");
d9773475
PA
750 else
751 kprintf("done\n");
752#if 0
984263bc
MD
753 else {
754 fib->data[0] = 0;
755 /*
756 * XXX Issuing this command to the controller makes it shut down
757 * but also keeps it from coming back up without a reset of the
758 * PCI bus. This is not desirable if you are just unloading the
759 * driver module with the intent to reload it later.
760 */
761 if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
762 fib, 1)) {
e3869ec7 763 kprintf("FAILED.\n");
984263bc 764 } else {
e3869ec7 765 kprintf("done.\n");
984263bc
MD
766 }
767 }
d9773475 768#endif
984263bc
MD
769
770 AAC_MASK_INTERRUPTS(sc);
d9773475 771 aac_release_sync_fib(sc);
e9ae7f4f 772 lockmgr(&sc->aac_io_lock, LK_RELEASE);
984263bc 773
984263bc
MD
774 return(0);
775}
776
777/*
778 * Bring the controller to a quiescent state, ready for system suspend.
779 */
780int
781aac_suspend(device_t dev)
782{
783 struct aac_softc *sc;
984263bc 784
984263bc
MD
785 sc = device_get_softc(dev);
786
e9ae7f4f 787 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 788 sc->aac_state |= AAC_STATE_SUSPEND;
d9773475 789
984263bc 790 AAC_MASK_INTERRUPTS(sc);
984263bc
MD
791 return(0);
792}
793
794/*
795 * Bring the controller back to a state ready for operation.
796 */
797int
798aac_resume(device_t dev)
799{
800 struct aac_softc *sc;
801
984263bc
MD
802 sc = device_get_softc(dev);
803
e9ae7f4f 804 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
805 sc->aac_state &= ~AAC_STATE_SUSPEND;
806 AAC_UNMASK_INTERRUPTS(sc);
807 return(0);
808}
809
810/*
d9773475 811 * Interrupt handler for NEW_COMM interface.
984263bc
MD
812 */
813void
d9773475
PA
814aac_new_intr(void *arg)
815{
816 struct aac_softc *sc;
817 u_int32_t index, fast;
818 struct aac_command *cm;
819 struct aac_fib *fib;
820 int i;
821
d9773475
PA
822 sc = (struct aac_softc *)arg;
823
e9ae7f4f
SW
824 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
825 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
d9773475
PA
826 while (1) {
827 index = AAC_GET_OUTB_QUEUE(sc);
828 if (index == 0xffffffff)
829 index = AAC_GET_OUTB_QUEUE(sc);
830 if (index == 0xffffffff)
831 break;
832 if (index & 2) {
833 if (index == 0xfffffffe) {
834 /* XXX This means that the controller wants
835 * more work. Ignore it for now.
836 */
837 continue;
838 }
839 /* AIF */
840 fib = (struct aac_fib *)kmalloc(sizeof *fib, M_AACBUF,
841 M_INTWAIT | M_ZERO);
842 index &= ~2;
843 for (i = 0; i < sizeof(struct aac_fib)/4; ++i)
e9ae7f4f 844 ((u_int32_t *)fib)[i] = AAC_MEM1_GETREG4(sc, index + i*4);
d9773475
PA
845 aac_handle_aif(sc, fib);
846 kfree(fib, M_AACBUF);
847
848 /*
849 * AIF memory is owned by the adapter, so let it
850 * know that we are done with it.
851 */
852 AAC_SET_OUTB_QUEUE(sc, index);
853 AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
854 } else {
855 fast = index & 1;
856 cm = sc->aac_commands + (index >> 2);
857 fib = cm->cm_fib;
858 if (fast) {
859 fib->Header.XferState |= AAC_FIBSTATE_DONEADAP;
860 *((u_int32_t *)(fib->data)) = AAC_ERROR_NORMAL;
861 }
862 aac_remove_busy(cm);
863 aac_unmap_command(cm);
864 cm->cm_flags |= AAC_CMD_COMPLETED;
865
866 /* is there a completion handler? */
867 if (cm->cm_complete != NULL) {
868 cm->cm_complete(cm);
869 } else {
870 /* assume that someone is sleeping on this
871 * command
872 */
873 wakeup(cm);
874 }
875 sc->flags &= ~AAC_QUEUE_FRZN;
876 }
877 }
878 /* see if we can start some more I/O */
879 if ((sc->flags & AAC_QUEUE_FRZN) == 0)
880 aac_startio(sc);
881
e9ae7f4f 882 lockmgr(&sc->aac_io_lock, LK_RELEASE);
d9773475
PA
883}
884
e9ae7f4f
SW
885/*
886 * Interrupt filter for !NEW_COMM interface.
887 */
d9773475 888void
e9ae7f4f 889aac_filter(void *arg)
984263bc
MD
890{
891 struct aac_softc *sc;
892 u_int16_t reason;
984263bc 893
984263bc
MD
894 sc = (struct aac_softc *)arg;
895
e9ae7f4f 896 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 897 /*
d9773475
PA
898 * Read the status register directly. This is faster than taking the
899 * driver lock and reading the queues directly. It also saves having
900 * to turn parts of the driver lock into a spin mutex, which would be
901 * ugly.
984263bc 902 */
d9773475 903 reason = AAC_GET_ISTATUS(sc);
984263bc 904 AAC_CLEAR_ISTATUS(sc, reason);
984263bc 905
d9773475 906 /* handle completion processing */
984263bc 907 if (reason & AAC_DB_RESPONSE_READY)
d9773475 908 taskqueue_enqueue(taskqueue_swi, &sc->aac_task_complete);
984263bc 909
d9773475
PA
910 /* controller wants to talk to us */
911 if (reason & (AAC_DB_PRINTF | AAC_DB_COMMAND_READY)) {
912 /*
913 * XXX Make sure that we don't get fooled by strange messages
914 * that start with a NULL.
915 */
916 if ((reason & AAC_DB_PRINTF) &&
917 (sc->aac_common->ac_printf[0] == 0))
918 sc->aac_common->ac_printf[0] = 32;
984263bc 919
d9773475
PA
920 /*
921 * This might miss doing the actual wakeup. However, the
e9ae7f4f 922 * lksleep that this is waking up has a timeout, so it will
d9773475
PA
923 * wake up eventually. AIFs and printfs are low enough
924 * priority that they can handle hanging out for a few seconds
925 * if needed.
926 */
927 wakeup(sc->aifthread);
984263bc
MD
928 }
929}
930
931/*
932 * Command Processing
933 */
934
935/*
936 * Start as much queued I/O as possible on the controller
937 */
938void
939aac_startio(struct aac_softc *sc)
940{
941 struct aac_command *cm;
e9ae7f4f 942 int error;
984263bc 943
e9ae7f4f 944 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 945
984263bc 946 for (;;) {
e9ae7f4f
SW
947 /*
948 * This flag might be set if the card is out of resources.
949 * Checking it here prevents an infinite loop of deferrals.
950 */
951 if (sc->flags & AAC_QUEUE_FRZN)
952 break;
953
984263bc 954 /*
d9773475 955 * Try to get a command that's been put off for lack of
984263bc
MD
956 * resources
957 */
958 cm = aac_dequeue_ready(sc);
959
960 /*
d9773475 961 * Try to build a command off the bio queue (ignore error
984263bc
MD
962 * return)
963 */
964 if (cm == NULL)
965 aac_bio_command(sc, &cm);
966
967 /* nothing to do? */
968 if (cm == NULL)
969 break;
970
e9ae7f4f
SW
971 /* don't map more than once */
972 if (cm->cm_flags & AAC_CMD_MAPPED)
973 panic("aac: command %p already mapped", cm);
974
d9773475 975 /*
e9ae7f4f
SW
976 * Set up the command to go to the controller. If there are no
977 * data buffers associated with the command then it can bypass
978 * busdma.
d9773475 979 */
e9ae7f4f
SW
980 if (cm->cm_datalen != 0) {
981 error = bus_dmamap_load(sc->aac_buffer_dmat,
982 cm->cm_datamap, cm->cm_data,
983 cm->cm_datalen,
984 aac_map_command_sg, cm, 0);
985 if (error == EINPROGRESS) {
986 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, "freezing queue\n");
987 sc->flags |= AAC_QUEUE_FRZN;
988 error = 0;
989 } else if (error != 0)
990 panic("aac_startio: unexpected error %d from "
991 "busdma", error);
992 } else
993 aac_map_command_sg(cm, NULL, 0, 0);
d9773475 994 }
984263bc
MD
995}
996
997/*
998 * Handle notification of one or more FIBs coming from the controller.
999 */
1000static void
cd8ab232 1001aac_command_thread(void *arg)
984263bc 1002{
cd8ab232 1003 struct aac_softc *sc = arg;
984263bc
MD
1004 struct aac_fib *fib;
1005 u_int32_t fib_size;
d9773475 1006 int size, retval;
984263bc 1007
e9ae7f4f 1008 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 1009
e9ae7f4f 1010 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
d9773475 1011 sc->aifflags = AAC_AIFFLAGS_RUNNING;
984263bc 1012
d9773475 1013 while ((sc->aifflags & AAC_AIFFLAGS_EXIT) == 0) {
e9ae7f4f 1014
d9773475 1015 retval = 0;
e9ae7f4f
SW
1016 if ((sc->aifflags & AAC_AIFFLAGS_PENDING) == 0)
1017 retval = lksleep(sc->aifthread, &sc->aac_io_lock, 0,
d9773475 1018 "aifthd", AAC_PERIODIC_INTERVAL * hz);
e9ae7f4f 1019
d9773475
PA
1020 /*
1021 * First see if any FIBs need to be allocated. This needs
1022 * to be called without the driver lock because contigmalloc
7f8935d3 1023 * can sleep.
d9773475
PA
1024 */
1025 if ((sc->aifflags & AAC_AIFFLAGS_ALLOCFIBS) != 0) {
e9ae7f4f 1026 lockmgr(&sc->aac_io_lock, LK_RELEASE);
d9773475 1027 aac_alloc_commands(sc);
e9ae7f4f 1028 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
d9773475
PA
1029 sc->aifflags &= ~AAC_AIFFLAGS_ALLOCFIBS;
1030 aac_startio(sc);
1031 }
984263bc 1032
d9773475
PA
1033 /*
1034 * While we're here, check to see if any commands are stuck.
1035 * This is pretty low-priority, so it's ok if it doesn't
1036 * always fire.
1037 */
1038 if (retval == EWOULDBLOCK)
1039 aac_timeout(sc);
1040
1041 /* Check the hardware printf message buffer */
1042 if (sc->aac_common->ac_printf[0] != 0)
1043 aac_print_printf(sc);
1044
1045 /* Also check to see if the adapter has a command for us. */
1046 if (sc->flags & AAC_FLAGS_NEW_COMM)
1047 continue;
984263bc
MD
1048 for (;;) {
1049 if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE,
e9ae7f4f 1050 &fib_size, &fib))
d9773475
PA
1051 break;
1052
984263bc 1053 AAC_PRINT_FIB(sc, fib);
d9773475 1054
984263bc
MD
1055 switch (fib->Header.Command) {
1056 case AifRequest:
1057 aac_handle_aif(sc, fib);
1058 break;
1059 default:
1060 device_printf(sc->aac_dev, "unknown command "
1061 "from controller\n");
1062 break;
1063 }
1064
984263bc 1065 if ((fib->Header.XferState == 0) ||
d9773475 1066 (fib->Header.StructType != AAC_FIBTYPE_TFIB)) {
984263bc 1067 break;
d9773475 1068 }
984263bc 1069
d9773475 1070 /* Return the AIF to the controller. */
984263bc
MD
1071 if (fib->Header.XferState & AAC_FIBSTATE_FROMADAP) {
1072 fib->Header.XferState |= AAC_FIBSTATE_DONEHOST;
1073 *(AAC_FSAStatus*)fib->data = ST_OK;
1074
1075 /* XXX Compute the Size field? */
1076 size = fib->Header.Size;
1077 if (size > sizeof(struct aac_fib)) {
1078 size = sizeof(struct aac_fib);
1079 fib->Header.Size = size;
1080 }
1081 /*
1082 * Since we did not generate this command, it
1083 * cannot go through the normal
1084 * enqueue->startio chain.
1085 */
1086 aac_enqueue_response(sc,
d9773475
PA
1087 AAC_ADAP_NORM_RESP_QUEUE,
1088 fib);
984263bc
MD
1089 }
1090 }
1091 }
1092 sc->aifflags &= ~AAC_AIFFLAGS_RUNNING;
e9ae7f4f 1093 lockmgr(&sc->aac_io_lock, LK_RELEASE);
984263bc 1094 wakeup(sc->aac_dev);
984263bc
MD
1095}
1096
1097/*
d9773475 1098 * Process completed commands.
984263bc
MD
1099 */
1100static void
d9773475 1101aac_complete(void *context, int pending)
984263bc 1102{
d9773475 1103 struct aac_softc *sc;
984263bc
MD
1104 struct aac_command *cm;
1105 struct aac_fib *fib;
1106 u_int32_t fib_size;
1107
d9773475 1108 sc = (struct aac_softc *)context;
e9ae7f4f 1109 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 1110
e9ae7f4f 1111 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
d9773475
PA
1112
1113 /* pull completed commands off the queue */
984263bc
MD
1114 for (;;) {
1115 /* look for completed FIBs on our queue */
1116 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
d9773475 1117 &fib))
984263bc 1118 break; /* nothing to do */
d9773475 1119
e9ae7f4f 1120 /* get the command, unmap and hand off for processing */
d9773475 1121 cm = sc->aac_commands + fib->Header.SenderData;
984263bc
MD
1122 if (cm == NULL) {
1123 AAC_PRINT_FIB(sc, fib);
984263bc 1124 break;
d9773475 1125 }
e9ae7f4f
SW
1126 if ((cm->cm_flags & AAC_CMD_TIMEDOUT) != 0)
1127 device_printf(sc->aac_dev,
1128 "COMMAND %p COMPLETED AFTER %d SECONDS\n",
cec73927 1129 cm, (int)(time_uptime - cm->cm_timestamp));
e9ae7f4f 1130
d9773475 1131 aac_remove_busy(cm);
e9ae7f4f
SW
1132
1133 aac_unmap_command(cm);
984263bc
MD
1134 cm->cm_flags |= AAC_CMD_COMPLETED;
1135
1136 /* is there a completion handler? */
1137 if (cm->cm_complete != NULL) {
1138 cm->cm_complete(cm);
1139 } else {
1140 /* assume that someone is sleeping on this command */
1141 wakeup(cm);
1142 }
1143 }
1144
1145 /* see if we can start some more I/O */
d9773475 1146 sc->flags &= ~AAC_QUEUE_FRZN;
984263bc 1147 aac_startio(sc);
d9773475 1148
e9ae7f4f 1149 lockmgr(&sc->aac_io_lock, LK_RELEASE);
984263bc
MD
1150}
1151
1152/*
1153 * Handle a bio submitted from a disk device.
1154 */
1155void
81b5c339 1156aac_submit_bio(struct aac_disk *ad, struct bio *bio)
984263bc 1157{
984263bc
MD
1158 struct aac_softc *sc;
1159
81b5c339 1160 bio->bio_driver_info = ad;
984263bc 1161 sc = ad->ad_controller;
e9ae7f4f 1162 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
1163
1164 /* queue the BIO and try to get some work done */
81b5c339 1165 aac_enqueue_bio(sc, bio);
984263bc
MD
1166 aac_startio(sc);
1167}
1168
1169/*
1170 * Get a bio and build a command to go with it.
1171 */
1172static int
1173aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
1174{
1175 struct aac_command *cm;
1176 struct aac_fib *fib;
984263bc 1177 struct aac_disk *ad;
81b5c339 1178 struct bio *bio;
1eabbf32 1179 struct buf *bp;
984263bc 1180
e9ae7f4f 1181 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
1182
1183 /* get the resources we will need */
1184 cm = NULL;
d9773475 1185 bio = NULL;
984263bc
MD
1186 if (aac_alloc_command(sc, &cm)) /* get a command */
1187 goto fail;
d9773475
PA
1188 if ((bio = aac_dequeue_bio(sc)) == NULL)
1189 goto fail;
984263bc
MD
1190
1191 /* fill out the command */
81b5c339 1192 bp = bio->bio_buf;
1eabbf32
HP
1193 cm->cm_data = (void *)bp->b_data;
1194 cm->cm_datalen = bp->b_bcount;
984263bc 1195 cm->cm_complete = aac_bio_complete;
81b5c339 1196 cm->cm_private = bio;
cec73927 1197 cm->cm_timestamp = time_uptime;
984263bc
MD
1198
1199 /* build the FIB */
1200 fib = cm->cm_fib;
d9773475
PA
1201 fib->Header.Size = sizeof(struct aac_fib_header);
1202 fib->Header.XferState =
1203 AAC_FIBSTATE_HOSTOWNED |
1204 AAC_FIBSTATE_INITIALISED |
1205 AAC_FIBSTATE_EMPTY |
984263bc
MD
1206 AAC_FIBSTATE_FROMHOST |
1207 AAC_FIBSTATE_REXPECTED |
1208 AAC_FIBSTATE_NORM |
1209 AAC_FIBSTATE_ASYNC |
1210 AAC_FIBSTATE_FAST_RESPONSE;
984263bc
MD
1211
1212 /* build the read/write request */
81b5c339 1213 ad = (struct aac_disk *)bio->bio_driver_info;
d9773475
PA
1214
1215 if (sc->flags & AAC_FLAGS_RAW_IO) {
1216 struct aac_raw_io *raw;
1217 raw = (struct aac_raw_io *)&fib->data[0];
1218 fib->Header.Command = RawIo;
1219 raw->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
1220 raw->ByteCount = bp->b_bcount;
1221 raw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
1222 raw->BpTotal = 0;
1223 raw->BpComplete = 0;
1224 fib->Header.Size += sizeof(struct aac_raw_io);
1225 cm->cm_sgtable = (struct aac_sg_table *)&raw->SgMapRaw;
1226 if (bp->b_cmd == BUF_CMD_READ) {
1227 raw->Flags = 1;
1228 cm->cm_flags |= AAC_CMD_DATAIN;
1229 } else {
1230 raw->Flags = 0;
1231 cm->cm_flags |= AAC_CMD_DATAOUT;
1232 }
1233 } else if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
1234 fib->Header.Command = ContainerCommand;
1235 if (bp->b_cmd == BUF_CMD_READ) {
1236 struct aac_blockread *br;
1237 br = (struct aac_blockread *)&fib->data[0];
1238 br->Command = VM_CtBlockRead;
1239 br->ContainerId = ad->ad_container->co_mntobj.ObjectId;
1240 br->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
1241 br->ByteCount = bp->b_bcount;
1242 fib->Header.Size += sizeof(struct aac_blockread);
1243 cm->cm_sgtable = &br->SgMap;
1244 cm->cm_flags |= AAC_CMD_DATAIN;
1245 } else {
1246 struct aac_blockwrite *bw;
1247 bw = (struct aac_blockwrite *)&fib->data[0];
1248 bw->Command = VM_CtBlockWrite;
1249 bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
1250 bw->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
1251 bw->ByteCount = bp->b_bcount;
1252 bw->Stable = CUNSTABLE;
1253 fib->Header.Size += sizeof(struct aac_blockwrite);
1254 cm->cm_flags |= AAC_CMD_DATAOUT;
1255 cm->cm_sgtable = &bw->SgMap;
1256 }
984263bc 1257 } else {
d9773475
PA
1258 fib->Header.Command = ContainerCommand64;
1259 if (bp->b_cmd == BUF_CMD_READ) {
1260 struct aac_blockread64 *br;
1261 br = (struct aac_blockread64 *)&fib->data[0];
1262 br->Command = VM_CtHostRead64;
1263 br->ContainerId = ad->ad_container->co_mntobj.ObjectId;
1264 br->SectorCount = bp->b_bcount / AAC_BLOCK_SIZE;
1265 br->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
1266 br->Pad = 0;
1267 br->Flags = 0;
1268 fib->Header.Size += sizeof(struct aac_blockread64);
e9ae7f4f 1269 cm->cm_flags |= AAC_CMD_DATAIN;
d9773475
PA
1270 cm->cm_sgtable = (struct aac_sg_table *)&br->SgMap64;
1271 } else {
1272 struct aac_blockwrite64 *bw;
1273 bw = (struct aac_blockwrite64 *)&fib->data[0];
1274 bw->Command = VM_CtHostWrite64;
1275 bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
1276 bw->SectorCount = bp->b_bcount / AAC_BLOCK_SIZE;
1277 bw->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
1278 bw->Pad = 0;
1279 bw->Flags = 0;
1280 fib->Header.Size += sizeof(struct aac_blockwrite64);
e9ae7f4f 1281 cm->cm_flags |= AAC_CMD_DATAOUT;
d9773475
PA
1282 cm->cm_sgtable = (struct aac_sg_table *)&bw->SgMap64;
1283 }
984263bc
MD
1284 }
1285
1286 *cmp = cm;
1287 return(0);
1288
1289fail:
81b5c339
MD
1290 if (bio != NULL)
1291 aac_enqueue_bio(sc, bio);
984263bc
MD
1292 if (cm != NULL)
1293 aac_release_command(cm);
1294 return(ENOMEM);
1295}
1296
1297/*
1298 * Handle a bio-instigated command that has been completed.
1299 */
1300static void
1301aac_bio_complete(struct aac_command *cm)
1302{
1303 struct aac_blockread_response *brr;
1304 struct aac_blockwrite_response *bwr;
81b5c339 1305 struct bio *bio;
1eabbf32 1306 struct buf *bp;
81b5c339 1307 const char *code;
984263bc
MD
1308 AAC_FSAStatus status;
1309
1310 /* fetch relevant status and then release the command */
81b5c339
MD
1311 bio = (struct bio *)cm->cm_private;
1312 bp = bio->bio_buf;
10f3fee5 1313 if (bp->b_cmd == BUF_CMD_READ) {
984263bc
MD
1314 brr = (struct aac_blockread_response *)&cm->cm_fib->data[0];
1315 status = brr->Status;
1316 } else {
1317 bwr = (struct aac_blockwrite_response *)&cm->cm_fib->data[0];
1318 status = bwr->Status;
1319 }
1320 aac_release_command(cm);
1321
1322 /* fix up the bio based on status */
1323 if (status == ST_OK) {
1eabbf32 1324 bp->b_resid = 0;
4090d6ff 1325 code = NULL;
984263bc 1326 } else {
1eabbf32
HP
1327 bp->b_error = EIO;
1328 bp->b_flags |= B_ERROR;
984263bc 1329 }
81b5c339 1330 aac_biodone(bio, code);
984263bc
MD
1331}
1332
984263bc
MD
1333/*
1334 * Submit a command to the controller, return when it completes.
1335 * XXX This is very dangerous! If the card has gone out to lunch, we could
1336 * be stuck here forever. At the same time, signals are not caught
d9773475
PA
1337 * because there is a risk that a signal could wakeup the sleep before
1338 * the card has a chance to complete the command. Since there is no way
1339 * to cancel a command that is in progress, we can't protect against the
1340 * card completing a command late and spamming the command and data
1341 * memory. So, we are held hostage until the command completes.
984263bc
MD
1342 */
1343static int
d9773475 1344aac_wait_command(struct aac_command *cm)
984263bc 1345{
d9773475
PA
1346 struct aac_softc *sc;
1347 int error;
984263bc 1348
d9773475 1349 sc = cm->cm_sc;
e9ae7f4f 1350 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 1351
984263bc 1352 /* Put the command on the ready queue and get things going */
984263bc 1353 aac_enqueue_ready(cm);
d9773475 1354 aac_startio(sc);
e9ae7f4f 1355 error = lksleep(cm, &sc->aac_io_lock, 0, "aacwait", 0);
984263bc
MD
1356 return(error);
1357}
1358
1359/*
1360 *Command Buffer Management
1361 */
1362
1363/*
1364 * Allocate a command.
1365 */
1366int
1367aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp)
1368{
1369 struct aac_command *cm;
1370
e9ae7f4f 1371 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 1372
d9773475
PA
1373 if ((cm = aac_dequeue_free(sc)) == NULL) {
1374 if (sc->total_fibs < sc->aac_max_fibs) {
7f8935d3 1375 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
d9773475 1376 sc->aifflags |= AAC_AIFFLAGS_ALLOCFIBS;
7f8935d3 1377 lockmgr(&sc->aac_io_lock, LK_RELEASE);
d9773475
PA
1378 wakeup(sc->aifthread);
1379 }
1380 return (EBUSY);
1381 }
984263bc
MD
1382
1383 *cmp = cm;
1384 return(0);
1385}
1386
1387/*
1388 * Release a command back to the freelist.
1389 */
1390void
1391aac_release_command(struct aac_command *cm)
1392{
d9773475
PA
1393 struct aac_event *event;
1394 struct aac_softc *sc;
1395
e9ae7f4f
SW
1396 sc = cm->cm_sc;
1397 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 1398
e9ae7f4f 1399 /* (re)initialize the command/FIB */
984263bc
MD
1400 cm->cm_sgtable = NULL;
1401 cm->cm_flags = 0;
1402 cm->cm_complete = NULL;
1403 cm->cm_private = NULL;
e9ae7f4f 1404 cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
984263bc
MD
1405 cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY;
1406 cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB;
1407 cm->cm_fib->Header.Flags = 0;
d9773475 1408 cm->cm_fib->Header.SenderSize = cm->cm_sc->aac_max_fib_size;
984263bc 1409
d9773475 1410 /*
984263bc
MD
1411 * These are duplicated in aac_start to cover the case where an
1412 * intermediate stage may have destroyed them. They're left
e9ae7f4f 1413 * initialized here for debugging purposes only.
984263bc 1414 */
984263bc
MD
1415 cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys;
1416 cm->cm_fib->Header.SenderData = 0;
1417
1418 aac_enqueue_free(cm);
d9773475 1419
7f8935d3 1420 if ((event = TAILQ_FIRST(&sc->aac_ev_cmfree)) != NULL) {
d9773475
PA
1421 TAILQ_REMOVE(&sc->aac_ev_cmfree, event, ev_links);
1422 event->ev_callback(sc, event, event->ev_arg);
1423 }
984263bc
MD
1424}
1425
1426/*
1427 * Map helper for command/FIB allocation.
1428 */
1429static void
1430aac_map_command_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1431{
d9773475 1432 uint64_t *fibphys;
984263bc 1433
d9773475 1434 fibphys = (uint64_t *)arg;
984263bc 1435
d9773475 1436 *fibphys = segs[0].ds_addr;
984263bc
MD
1437}
1438
1439/*
e9ae7f4f 1440 * Allocate and initialize commands/FIBs for this adapter.
984263bc
MD
1441 */
1442static int
1443aac_alloc_commands(struct aac_softc *sc)
1444{
1445 struct aac_command *cm;
d9773475
PA
1446 struct aac_fibmap *fm;
1447 uint64_t fibphys;
1448 int i, error;
1449
e9ae7f4f 1450 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475
PA
1451
1452 if (sc->total_fibs + sc->aac_max_fibs_alloc > sc->aac_max_fibs)
1453 return (ENOMEM);
1454
1455 fm = kmalloc(sizeof(struct aac_fibmap), M_AACBUF, M_INTWAIT | M_ZERO);
984263bc
MD
1456
1457 /* allocate the FIBs in DMAable memory and load them */
d9773475
PA
1458 if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&fm->aac_fibs,
1459 BUS_DMA_NOWAIT, &fm->aac_fibmap)) {
1460 device_printf(sc->aac_dev,
1461 "Not enough contiguous memory available.\n");
1462 kfree(fm, M_AACBUF);
1463 return (ENOMEM);
984263bc
MD
1464 }
1465
d9773475 1466 /* Ignore errors since this doesn't bounce */
e9ae7f4f
SW
1467 (void)bus_dmamap_load(sc->aac_fib_dmat, fm->aac_fibmap, fm->aac_fibs,
1468 sc->aac_max_fibs_alloc * sc->aac_max_fib_size,
1469 aac_map_command_helper, &fibphys, 0);
984263bc 1470
e9ae7f4f 1471 /* initialize constant fields in the command structure */
d9773475
PA
1472 bzero(fm->aac_fibs, sc->aac_max_fibs_alloc * sc->aac_max_fib_size);
1473 for (i = 0; i < sc->aac_max_fibs_alloc; i++) {
1474 cm = sc->aac_commands + sc->total_fibs;
1475 fm->aac_commands = cm;
984263bc 1476 cm->cm_sc = sc;
d9773475
PA
1477 cm->cm_fib = (struct aac_fib *)
1478 ((u_int8_t *)fm->aac_fibs + i*sc->aac_max_fib_size);
1479 cm->cm_fibphys = fibphys + i*sc->aac_max_fib_size;
1480 cm->cm_index = sc->total_fibs;
984263bc 1481
d9773475
PA
1482 if ((error = bus_dmamap_create(sc->aac_buffer_dmat, 0,
1483 &cm->cm_datamap)) != 0)
1484 break;
e9ae7f4f 1485 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
d9773475
PA
1486 aac_release_command(cm);
1487 sc->total_fibs++;
e9ae7f4f 1488 lockmgr(&sc->aac_io_lock, LK_RELEASE);
984263bc 1489 }
d9773475
PA
1490
1491 if (i > 0) {
e9ae7f4f 1492 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
d9773475 1493 TAILQ_INSERT_TAIL(&sc->aac_fibmap_tqh, fm, fm_link);
e9ae7f4f
SW
1494 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, "total_fibs= %d\n", sc->total_fibs);
1495 lockmgr(&sc->aac_io_lock, LK_RELEASE);
d9773475
PA
1496 return (0);
1497 }
1498
1499 bus_dmamap_unload(sc->aac_fib_dmat, fm->aac_fibmap);
1500 bus_dmamem_free(sc->aac_fib_dmat, fm->aac_fibs, fm->aac_fibmap);
1501 kfree(fm, M_AACBUF);
1502 return (ENOMEM);
984263bc
MD
1503}
1504
1505/*
1506 * Free FIBs owned by this adapter.
1507 */
1508static void
1509aac_free_commands(struct aac_softc *sc)
1510{
d9773475
PA
1511 struct aac_fibmap *fm;
1512 struct aac_command *cm;
984263bc
MD
1513 int i;
1514
e9ae7f4f 1515 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 1516
d9773475 1517 while ((fm = TAILQ_FIRST(&sc->aac_fibmap_tqh)) != NULL) {
984263bc 1518
d9773475
PA
1519 TAILQ_REMOVE(&sc->aac_fibmap_tqh, fm, fm_link);
1520 /*
1521 * We check against total_fibs to handle partially
1522 * allocated blocks.
1523 */
1524 for (i = 0; i < sc->aac_max_fibs_alloc && sc->total_fibs--; i++) {
1525 cm = fm->aac_commands + i;
1526 bus_dmamap_destroy(sc->aac_buffer_dmat, cm->cm_datamap);
1527 }
1528 bus_dmamap_unload(sc->aac_fib_dmat, fm->aac_fibmap);
1529 bus_dmamem_free(sc->aac_fib_dmat, fm->aac_fibs, fm->aac_fibmap);
1530 kfree(fm, M_AACBUF);
1531 }
984263bc
MD
1532}
1533
1534/*
1535 * Command-mapping helper function - populate this command's s/g table.
1536 */
1537static void
1538aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1539{
d9773475 1540 struct aac_softc *sc;
984263bc
MD
1541 struct aac_command *cm;
1542 struct aac_fib *fib;
984263bc
MD
1543 int i;
1544
984263bc 1545 cm = (struct aac_command *)arg;
d9773475 1546 sc = cm->cm_sc;
984263bc 1547 fib = cm->cm_fib;
e9ae7f4f 1548 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 1549
984263bc 1550 /* copy into the FIB */
d9773475
PA
1551 if (cm->cm_sgtable != NULL) {
1552 if (fib->Header.Command == RawIo) {
1553 struct aac_sg_tableraw *sg;
1554 sg = (struct aac_sg_tableraw *)cm->cm_sgtable;
1555 sg->SgCount = nseg;
1556 for (i = 0; i < nseg; i++) {
1557 sg->SgEntryRaw[i].SgAddress = segs[i].ds_addr;
1558 sg->SgEntryRaw[i].SgByteCount = segs[i].ds_len;
1559 sg->SgEntryRaw[i].Next = 0;
1560 sg->SgEntryRaw[i].Prev = 0;
1561 sg->SgEntryRaw[i].Flags = 0;
1562 }
1563 /* update the FIB size for the s/g count */
1564 fib->Header.Size += nseg*sizeof(struct aac_sg_entryraw);
1565 } else if ((cm->cm_sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
1566 struct aac_sg_table *sg;
1567 sg = cm->cm_sgtable;
1568 sg->SgCount = nseg;
1569 for (i = 0; i < nseg; i++) {
1570 sg->SgEntry[i].SgAddress = segs[i].ds_addr;
1571 sg->SgEntry[i].SgByteCount = segs[i].ds_len;
1572 }
1573 /* update the FIB size for the s/g count */
1574 fib->Header.Size += nseg*sizeof(struct aac_sg_entry);
1575 } else {
1576 struct aac_sg_table64 *sg;
1577 sg = (struct aac_sg_table64 *)cm->cm_sgtable;
1578 sg->SgCount = nseg;
1579 for (i = 0; i < nseg; i++) {
1580 sg->SgEntry64[i].SgAddress = segs[i].ds_addr;
1581 sg->SgEntry64[i].SgByteCount = segs[i].ds_len;
1582 }
1583 /* update the FIB size for the s/g count */
1584 fib->Header.Size += nseg*sizeof(struct aac_sg_entry64);
1585 }
1586 }
984263bc 1587
d9773475
PA
1588 /* Fix up the address values in the FIB. Use the command array index
1589 * instead of a pointer since these fields are only 32 bits. Shift
1590 * the SenderFibAddress over to make room for the fast response bit
1591 * and for the AIF bit
1592 */
1593 cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 2);
1594 cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys;
984263bc 1595
d9773475
PA
1596 /* save a pointer to the command for speedy reverse-lookup */
1597 cm->cm_fib->Header.SenderData = cm->cm_index;
1598
1599 if (cm->cm_flags & AAC_CMD_DATAIN)
1600 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
1601 BUS_DMASYNC_PREREAD);
1602 if (cm->cm_flags & AAC_CMD_DATAOUT)
1603 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
1604 BUS_DMASYNC_PREWRITE);
1605 cm->cm_flags |= AAC_CMD_MAPPED;
984263bc 1606
d9773475
PA
1607 if (sc->flags & AAC_FLAGS_NEW_COMM) {
1608 int count = 10000000L;
1609 while (AAC_SEND_COMMAND(sc, cm) != 0) {
1610 if (--count == 0) {
1611 aac_unmap_command(cm);
1612 sc->flags |= AAC_QUEUE_FRZN;
1613 aac_requeue_ready(cm);
1614 }
1615 DELAY(5); /* wait 5 usec. */
1616 }
1617 } else {
1618 /* Put the FIB on the outbound queue */
1619 if (aac_enqueue_fib(sc, cm->cm_queue, cm) == EBUSY) {
1620 aac_unmap_command(cm);
1621 sc->flags |= AAC_QUEUE_FRZN;
1622 aac_requeue_ready(cm);
1623 }
984263bc 1624 }
984263bc
MD
1625}
1626
1627/*
1628 * Unmap a command from controller-visible space.
1629 */
1630static void
1631aac_unmap_command(struct aac_command *cm)
1632{
1633 struct aac_softc *sc;
1634
984263bc 1635 sc = cm->cm_sc;
e9ae7f4f 1636 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
1637
1638 if (!(cm->cm_flags & AAC_CMD_MAPPED))
1639 return;
1640
1641 if (cm->cm_datalen != 0) {
1642 if (cm->cm_flags & AAC_CMD_DATAIN)
1643 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
1644 BUS_DMASYNC_POSTREAD);
1645 if (cm->cm_flags & AAC_CMD_DATAOUT)
1646 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
1647 BUS_DMASYNC_POSTWRITE);
1648
1649 bus_dmamap_unload(sc->aac_buffer_dmat, cm->cm_datamap);
1650 }
1651 cm->cm_flags &= ~AAC_CMD_MAPPED;
1652}
1653
1654/*
1655 * Hardware Interface
1656 */
1657
1658/*
e9ae7f4f 1659 * Initialize the adapter.
984263bc
MD
1660 */
1661static void
1662aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1663{
1664 struct aac_softc *sc;
1665
984263bc 1666 sc = (struct aac_softc *)arg;
e9ae7f4f 1667 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
1668
1669 sc->aac_common_busaddr = segs[0].ds_addr;
1670}
1671
1672static int
1673aac_check_firmware(struct aac_softc *sc)
1674{
e9ae7f4f 1675 u_int32_t code, major, minor, options = 0, atu_size = 0;
b4df2201 1676 int rid, status;
e9ae7f4f 1677 time_t then;
984263bc 1678
e9ae7f4f
SW
1679 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
1680 /*
1681 * Wait for the adapter to come ready.
1682 */
cec73927 1683 then = time_uptime;
e9ae7f4f
SW
1684 do {
1685 code = AAC_GET_FWSTATUS(sc);
1686 if (code & AAC_SELF_TEST_FAILED) {
1687 device_printf(sc->aac_dev, "FATAL: selftest failed\n");
1688 return(ENXIO);
1689 }
1690 if (code & AAC_KERNEL_PANIC) {
1691 device_printf(sc->aac_dev,
1692 "FATAL: controller kernel panic");
1693 return(ENXIO);
1694 }
cec73927 1695 if (time_uptime > (then + AAC_BOOT_TIMEOUT)) {
e9ae7f4f
SW
1696 device_printf(sc->aac_dev,
1697 "FATAL: controller not coming ready, "
1698 "status %x\n", code);
1699 return(ENXIO);
1700 }
1701 } while (!(code & AAC_UP_AND_RUNNING));
984263bc
MD
1702
1703 /*
1704 * Retrieve the firmware version numbers. Dell PERC2/QC cards with
1705 * firmware version 1.x are not compatible with this driver.
1706 */
1707 if (sc->flags & AAC_FLAGS_PERC2QC) {
1708 if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
1709 NULL)) {
1710 device_printf(sc->aac_dev,
1711 "Error reading firmware version\n");
1712 return (EIO);
1713 }
1714
1715 /* These numbers are stored as ASCII! */
1716 major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
1717 minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
1718 if (major == 1) {
1719 device_printf(sc->aac_dev,
1720 "Firmware version %d.%d is not supported.\n",
1721 major, minor);
1722 return (EINVAL);
1723 }
1724 }
1725
1726 /*
1727 * Retrieve the capabilities/supported options word so we know what
d9773475
PA
1728 * work-arounds to enable. Some firmware revs don't support this
1729 * command.
984263bc 1730 */
d9773475
PA
1731 if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status)) {
1732 if (status != AAC_SRB_STS_INVALID_REQUEST) {
1733 device_printf(sc->aac_dev,
1734 "RequestAdapterInfo failed\n");
1735 return (EIO);
1736 }
1737 } else {
1738 options = AAC_GET_MAILBOX(sc, 1);
1739 atu_size = AAC_GET_MAILBOX(sc, 2);
1740 sc->supported_options = options;
1741
1742 if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 &&
1743 (sc->flags & AAC_FLAGS_NO4GB) == 0)
1744 sc->flags |= AAC_FLAGS_4GB_WINDOW;
1745 if (options & AAC_SUPPORTED_NONDASD)
1746 sc->flags |= AAC_FLAGS_ENABLE_CAM;
1747 if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0
1748 && (sizeof(bus_addr_t) > 4)) {
1749 device_printf(sc->aac_dev,
1750 "Enabling 64-bit address support\n");
1751 sc->flags |= AAC_FLAGS_SG_64BIT;
1752 }
1753 if ((options & AAC_SUPPORTED_NEW_COMM)
b4df2201 1754 && sc->aac_if->aif_send_command)
d9773475
PA
1755 sc->flags |= AAC_FLAGS_NEW_COMM;
1756 if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE)
1757 sc->flags |= AAC_FLAGS_ARRAY_64BIT;
1758 }
1759
1760 /* Check for broken hardware that does a lower number of commands */
1761 sc->aac_max_fibs = (sc->flags & AAC_FLAGS_256FIBS ? 256:512);
1762
1763 /* Remap mem. resource, if required */
1764 if ((sc->flags & AAC_FLAGS_NEW_COMM) &&
b4df2201
SW
1765 atu_size > rman_get_size(sc->aac_regs_res1)) {
1766 rid = rman_get_rid(sc->aac_regs_res1);
1767 bus_release_resource(sc->aac_dev, SYS_RES_MEMORY, rid,
1768 sc->aac_regs_res1);
1769 sc->aac_regs_res1 = bus_alloc_resource(sc->aac_dev,
1770 SYS_RES_MEMORY, &rid, 0ul, ~0ul, atu_size, RF_ACTIVE);
e9ae7f4f
SW
1771 if (sc->aac_regs_res1 == NULL) {
1772 sc->aac_regs_res1 = bus_alloc_resource_any(
b4df2201 1773 sc->aac_dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
e9ae7f4f 1774 if (sc->aac_regs_res1 == NULL) {
d9773475
PA
1775 device_printf(sc->aac_dev,
1776 "couldn't allocate register window\n");
1777 return (ENXIO);
1778 }
1779 sc->flags &= ~AAC_FLAGS_NEW_COMM;
1780 }
e9ae7f4f
SW
1781 sc->aac_btag1 = rman_get_bustag(sc->aac_regs_res1);
1782 sc->aac_bhandle1 = rman_get_bushandle(sc->aac_regs_res1);
1783
1784 if (sc->aac_hwif == AAC_HWIF_NARK) {
1785 sc->aac_regs_res0 = sc->aac_regs_res1;
e9ae7f4f
SW
1786 sc->aac_btag0 = sc->aac_btag1;
1787 sc->aac_bhandle0 = sc->aac_bhandle1;
1788 }
984263bc 1789 }
984263bc 1790
d9773475
PA
1791 /* Read preferred settings */
1792 sc->aac_max_fib_size = sizeof(struct aac_fib);
1793 sc->aac_max_sectors = 128; /* 64KB */
1794 if (sc->flags & AAC_FLAGS_SG_64BIT)
1795 sc->aac_sg_tablesize = (AAC_FIB_DATASIZE
e9ae7f4f
SW
1796 - sizeof(struct aac_blockwrite64))
1797 / sizeof(struct aac_sg_entry64);
d9773475
PA
1798 else
1799 sc->aac_sg_tablesize = (AAC_FIB_DATASIZE
e9ae7f4f
SW
1800 - sizeof(struct aac_blockwrite))
1801 / sizeof(struct aac_sg_entry);
d9773475
PA
1802
1803 if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) {
1804 options = AAC_GET_MAILBOX(sc, 1);
1805 sc->aac_max_fib_size = (options & 0xFFFF);
1806 sc->aac_max_sectors = (options >> 16) << 1;
1807 options = AAC_GET_MAILBOX(sc, 2);
1808 sc->aac_sg_tablesize = (options >> 16);
1809 options = AAC_GET_MAILBOX(sc, 3);
1810 sc->aac_max_fibs = (options & 0xFFFF);
1811 }
1812 if (sc->aac_max_fib_size > PAGE_SIZE)
1813 sc->aac_max_fib_size = PAGE_SIZE;
1814 sc->aac_max_fibs_alloc = PAGE_SIZE / sc->aac_max_fib_size;
984263bc 1815
e9ae7f4f
SW
1816 if (sc->aac_max_fib_size > sizeof(struct aac_fib)) {
1817 sc->flags |= AAC_FLAGS_RAW_IO;
1818 device_printf(sc->aac_dev, "Enable Raw I/O\n");
1819 }
1820 if ((sc->flags & AAC_FLAGS_RAW_IO) &&
1821 (sc->flags & AAC_FLAGS_ARRAY_64BIT)) {
1822 sc->flags |= AAC_FLAGS_LBA_64BIT;
1823 device_printf(sc->aac_dev, "Enable 64-bit array\n");
1824 }
1825
984263bc
MD
1826 return (0);
1827}
1828
1829static int
1830aac_init(struct aac_softc *sc)
1831{
1832 struct aac_adapter_init *ip;
e9ae7f4f 1833 u_int32_t qoffset;
984263bc
MD
1834 int error;
1835
e9ae7f4f 1836 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
1837
1838 /*
1839 * Fill in the init structure. This tells the adapter about the
1840 * physical location of various important shared data structures.
1841 */
1842 ip = &sc->aac_common->ac_init;
1843 ip->InitStructRevision = AAC_INIT_STRUCT_REVISION;
d9773475
PA
1844 if (sc->aac_max_fib_size > sizeof(struct aac_fib)) {
1845 ip->InitStructRevision = AAC_INIT_STRUCT_REVISION_4;
1846 sc->flags |= AAC_FLAGS_RAW_IO;
1847 }
984263bc
MD
1848 ip->MiniPortRevision = AAC_INIT_STRUCT_MINIPORT_REVISION;
1849
1850 ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr +
1851 offsetof(struct aac_common, ac_fibs);
d9773475 1852 ip->AdapterFibsVirtualAddress = 0;
984263bc
MD
1853 ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib);
1854 ip->AdapterFibAlign = sizeof(struct aac_fib);
1855
1856 ip->PrintfBufferAddress = sc->aac_common_busaddr +
1857 offsetof(struct aac_common, ac_printf);
1858 ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE;
1859
d9773475
PA
1860 /*
1861 * The adapter assumes that pages are 4K in size, except on some
1862 * broken firmware versions that do the page->byte conversion twice,
1863 * therefore 'assuming' that this value is in 16MB units (2^24).
1864 * Round up since the granularity is so high.
1865 */
e9ae7f4f 1866 ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE;
d9773475
PA
1867 if (sc->flags & AAC_FLAGS_BROKEN_MEMMAP) {
1868 ip->HostPhysMemPages =
1869 (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE;
1870 }
cec73927 1871 ip->HostElapsedSeconds = time_uptime; /* reset later if invalid */
984263bc 1872
d9773475
PA
1873 ip->InitFlags = 0;
1874 if (sc->flags & AAC_FLAGS_NEW_COMM) {
e9ae7f4f 1875 ip->InitFlags |= AAC_INITFLAGS_NEW_COMM_SUPPORTED;
d9773475
PA
1876 device_printf(sc->aac_dev, "New comm. interface enabled\n");
1877 }
1878
1879 ip->MaxIoCommands = sc->aac_max_fibs;
1880 ip->MaxIoSize = sc->aac_max_sectors << 9;
1881 ip->MaxFibSize = sc->aac_max_fib_size;
1882
984263bc 1883 /*
e9ae7f4f 1884 * Initialize FIB queues. Note that it appears that the layout of the
984263bc
MD
1885 * indexes and the segmentation of the entries may be mandated by the
1886 * adapter, which is only told about the base of the queue index fields.
1887 *
1888 * The initial values of the indices are assumed to inform the adapter
d9773475 1889 * of the sizes of the respective queues, and theoretically it could
984263bc
MD
1890 * work out the entire layout of the queue structures from this. We
1891 * take the easy route and just lay this area out like everyone else
1892 * does.
1893 *
d9773475
PA
1894 * The Linux driver uses a much more complex scheme whereby several
1895 * header records are kept for each queue. We use a couple of generic
984263bc
MD
1896 * list manipulation functions which 'know' the size of each list by
1897 * virtue of a table.
1898 */
d9773475
PA
1899 qoffset = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
1900 qoffset &= ~(AAC_QUEUE_ALIGN - 1);
1901 sc->aac_queues =
1902 (struct aac_queue_table *)((uintptr_t)sc->aac_common + qoffset);
1903 ip->CommHeaderAddress = sc->aac_common_busaddr + qoffset;
984263bc
MD
1904
1905 sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1906 AAC_HOST_NORM_CMD_ENTRIES;
1907 sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1908 AAC_HOST_NORM_CMD_ENTRIES;
1909 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1910 AAC_HOST_HIGH_CMD_ENTRIES;
1911 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1912 AAC_HOST_HIGH_CMD_ENTRIES;
1913 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1914 AAC_ADAP_NORM_CMD_ENTRIES;
1915 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1916 AAC_ADAP_NORM_CMD_ENTRIES;
1917 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1918 AAC_ADAP_HIGH_CMD_ENTRIES;
1919 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1920 AAC_ADAP_HIGH_CMD_ENTRIES;
1921 sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1922 AAC_HOST_NORM_RESP_ENTRIES;
1923 sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1924 AAC_HOST_NORM_RESP_ENTRIES;
1925 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1926 AAC_HOST_HIGH_RESP_ENTRIES;
1927 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1928 AAC_HOST_HIGH_RESP_ENTRIES;
1929 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1930 AAC_ADAP_NORM_RESP_ENTRIES;
1931 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1932 AAC_ADAP_NORM_RESP_ENTRIES;
1933 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1934 AAC_ADAP_HIGH_RESP_ENTRIES;
1935 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1936 AAC_ADAP_HIGH_RESP_ENTRIES;
1937 sc->aac_qentries[AAC_HOST_NORM_CMD_QUEUE] =
1938 &sc->aac_queues->qt_HostNormCmdQueue[0];
1939 sc->aac_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
1940 &sc->aac_queues->qt_HostHighCmdQueue[0];
1941 sc->aac_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
1942 &sc->aac_queues->qt_AdapNormCmdQueue[0];
1943 sc->aac_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
1944 &sc->aac_queues->qt_AdapHighCmdQueue[0];
1945 sc->aac_qentries[AAC_HOST_NORM_RESP_QUEUE] =
1946 &sc->aac_queues->qt_HostNormRespQueue[0];
1947 sc->aac_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
1948 &sc->aac_queues->qt_HostHighRespQueue[0];
1949 sc->aac_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
1950 &sc->aac_queues->qt_AdapNormRespQueue[0];
1951 sc->aac_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
1952 &sc->aac_queues->qt_AdapHighRespQueue[0];
1953
1954 /*
1955 * Do controller-type-specific initialisation
1956 */
1957 switch (sc->aac_hwif) {
1958 case AAC_HWIF_I960RX:
e9ae7f4f 1959 AAC_MEM0_SETREG4(sc, AAC_RX_ODBR, ~0);
984263bc 1960 break;
d9773475 1961 case AAC_HWIF_RKT:
e9ae7f4f 1962 AAC_MEM0_SETREG4(sc, AAC_RKT_ODBR, ~0);
d9773475
PA
1963 break;
1964 default:
1965 break;
984263bc
MD
1966 }
1967
1968 /*
1969 * Give the init structure to the controller.
1970 */
d9773475 1971 if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
984263bc
MD
1972 sc->aac_common_busaddr +
1973 offsetof(struct aac_common, ac_init), 0, 0, 0,
1974 NULL)) {
1975 device_printf(sc->aac_dev,
1976 "error establishing init structure\n");
1977 error = EIO;
1978 goto out;
1979 }
1980
1981 error = 0;
1982out:
1983 return(error);
1984}
1985
e9ae7f4f
SW
1986static int
1987aac_setup_intr(struct aac_softc *sc)
1988{
b4df2201 1989
e9ae7f4f
SW
1990 if (sc->flags & AAC_FLAGS_NEW_COMM) {
1991 if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
1992 INTR_MPSAFE,
1993 aac_new_intr, sc, &sc->aac_intr, NULL)) {
1994 device_printf(sc->aac_dev, "can't set up interrupt\n");
1995 return (EINVAL);
1996 }
1997 } else {
1998 if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
1999 0, aac_filter,
2000 sc, &sc->aac_intr, NULL)) {
2001 device_printf(sc->aac_dev,
2002 "can't set up interrupt filter\n");
2003 return (EINVAL);
2004 }
2005 }
2006 return (0);
2007}
2008
984263bc
MD
2009/*
2010 * Send a synchronous command to the controller and wait for a result.
d9773475 2011 * Indicate if the controller completed the command with an error status.
984263bc
MD
2012 */
2013static int
2014aac_sync_command(struct aac_softc *sc, u_int32_t command,
2015 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3,
2016 u_int32_t *sp)
2017{
2018 time_t then;
2019 u_int32_t status;
2020
57e09377
MD
2021 if (sp != NULL)
2022 *sp = 0; /* avoid gcc warnings */
e9ae7f4f 2023 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
2024
2025 /* populate the mailbox */
2026 AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
2027
2028 /* ensure the sync command doorbell flag is cleared */
2029 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
2030
2031 /* then set it to signal the adapter */
2032 AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
2033
2034 /* spin waiting for the command to complete */
cec73927 2035 then = time_uptime;
984263bc 2036 do {
cec73927 2037 if (time_uptime > (then + AAC_IMMEDIATE_TIMEOUT)) {
e9ae7f4f 2038 fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, "timed out");
984263bc
MD
2039 return(EIO);
2040 }
2041 } while (!(AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND));
2042
2043 /* clear the completion flag */
2044 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
2045
2046 /* get the command status */
2047 status = AAC_GET_MAILBOX(sc, 0);
2048 if (sp != NULL)
2049 *sp = status;
984263bc 2050
d9773475
PA
2051 if (status != AAC_SRB_STS_SUCCESS)
2052 return (-1);
2053 return(0);
984263bc
MD
2054}
2055
984263bc 2056int
d9773475 2057aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
984263bc
MD
2058 struct aac_fib *fib, u_int16_t datasize)
2059{
e9ae7f4f
SW
2060 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
2061#if 0 /* XXX swildner */
d9773475 2062 KKASSERT(lockstatus(&sc->aac_io_lock, curthread) != 0);
e9ae7f4f 2063#endif
984263bc
MD
2064
2065 if (datasize > AAC_FIB_DATASIZE)
2066 return(EINVAL);
2067
2068 /*
2069 * Set up the sync FIB
2070 */
2071 fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED |
2072 AAC_FIBSTATE_INITIALISED |
2073 AAC_FIBSTATE_EMPTY;
2074 fib->Header.XferState |= xferstate;
2075 fib->Header.Command = command;
2076 fib->Header.StructType = AAC_FIBTYPE_TFIB;
e9ae7f4f 2077 fib->Header.Size = sizeof(struct aac_fib_header) + datasize;
984263bc 2078 fib->Header.SenderSize = sizeof(struct aac_fib);
d9773475 2079 fib->Header.SenderFibAddress = 0; /* Not needed */
984263bc
MD
2080 fib->Header.ReceiverFibAddress = sc->aac_common_busaddr +
2081 offsetof(struct aac_common,
2082 ac_sync_fib);
2083
2084 /*
2085 * Give the FIB to the controller, wait for a response.
2086 */
2087 if (aac_sync_command(sc, AAC_MONKER_SYNCFIB,
2088 fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) {
e9ae7f4f 2089 fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, "IO error");
984263bc
MD
2090 return(EIO);
2091 }
2092
2093 return (0);
2094}
2095
2096/*
2097 * Adapter-space FIB queue manipulation
2098 *
2099 * Note that the queue implementation here is a little funky; neither the PI or
2100 * CI will ever be zero. This behaviour is a controller feature.
2101 */
b4df2201 2102static const struct {
984263bc
MD
2103 int size;
2104 int notify;
2105} aac_qinfo[] = {
2106 {AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL},
2107 {AAC_HOST_HIGH_CMD_ENTRIES, 0},
2108 {AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY},
2109 {AAC_ADAP_HIGH_CMD_ENTRIES, 0},
2110 {AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL},
2111 {AAC_HOST_HIGH_RESP_ENTRIES, 0},
2112 {AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY},
2113 {AAC_ADAP_HIGH_RESP_ENTRIES, 0}
2114};
2115
2116/*
2117 * Atomically insert an entry into the nominated queue, returns 0 on success or
2118 * EBUSY if the queue is full.
2119 *
2120 * Note: it would be more efficient to defer notifying the controller in
2121 * the case where we may be inserting several entries in rapid succession,
2122 * but implementing this usefully may be difficult (it would involve a
2123 * separate queue/notify interface).
2124 */
2125static int
2126aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
2127{
2128 u_int32_t pi, ci;
7f2216bc 2129 int error;
984263bc
MD
2130 u_int32_t fib_size;
2131 u_int32_t fib_addr;
2132
e9ae7f4f 2133 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2134
d9773475 2135 fib_size = cm->cm_fib->Header.Size;
984263bc
MD
2136 fib_addr = cm->cm_fib->Header.ReceiverFibAddress;
2137
984263bc
MD
2138 /* get the producer/consumer indices */
2139 pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
2140 ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
2141
2142 /* wrap the queue? */
2143 if (pi >= aac_qinfo[queue].size)
2144 pi = 0;
2145
2146 /* check for queue full */
2147 if ((pi + 1) == ci) {
2148 error = EBUSY;
2149 goto out;
2150 }
e9ae7f4f 2151
158dbeb8
MD
2152 /*
2153 * To avoid a race with its completion interrupt, place this command on
2154 * the busy queue prior to advertising it to the controller.
2155 */
2156 aac_enqueue_busy(cm);
2157
984263bc
MD
2158 /* populate queue entry */
2159 (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
2160 (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
2161
2162 /* update producer index */
2163 sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
2164
984263bc
MD
2165 /* notify the adapter if we know how */
2166 if (aac_qinfo[queue].notify != 0)
2167 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
2168
2169 error = 0;
2170
2171out:
984263bc
MD
2172 return(error);
2173}
2174
2175/*
2176 * Atomically remove one entry from the nominated queue, returns 0 on
2177 * success or ENOENT if the queue is empty.
2178 */
2179static int
2180aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
2181 struct aac_fib **fib_addr)
2182{
2183 u_int32_t pi, ci;
d9773475 2184 u_int32_t fib_index;
7f2216bc 2185 int error;
984263bc
MD
2186 int notify;
2187
e9ae7f4f 2188 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2189
984263bc
MD
2190 /* get the producer/consumer indices */
2191 pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
2192 ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
2193
2194 /* check for queue empty */
2195 if (ci == pi) {
2196 error = ENOENT;
2197 goto out;
2198 }
158dbeb8
MD
2199
2200 /* wrap the pi so the following test works */
2201 if (pi >= aac_qinfo[queue].size)
2202 pi = 0;
2203
984263bc
MD
2204 notify = 0;
2205 if (ci == pi + 1)
2206 notify++;
2207
2208 /* wrap the queue? */
2209 if (ci >= aac_qinfo[queue].size)
2210 ci = 0;
2211
2212 /* fetch the entry */
2213 *fib_size = (sc->aac_qentries[queue] + ci)->aq_fib_size;
984263bc 2214
d9773475
PA
2215 switch (queue) {
2216 case AAC_HOST_NORM_CMD_QUEUE:
2217 case AAC_HOST_HIGH_CMD_QUEUE:
2218 /*
2219 * The aq_fib_addr is only 32 bits wide so it can't be counted
2220 * on to hold an address. For AIF's, the adapter assumes
2221 * that it's giving us an address into the array of AIF fibs.
2222 * Therefore, we have to convert it to an index.
2223 */
2224 fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr /
2225 sizeof(struct aac_fib);
2226 *fib_addr = &sc->aac_common->ac_fibs[fib_index];
2227 break;
2228
2229 case AAC_HOST_NORM_RESP_QUEUE:
2230 case AAC_HOST_HIGH_RESP_QUEUE:
2231 {
2232 struct aac_command *cm;
2233
2234 /*
2235 * As above, an index is used instead of an actual address.
2236 * Gotta shift the index to account for the fast response
2237 * bit. No other correction is needed since this value was
2238 * originally provided by the driver via the SenderFibAddress
2239 * field.
2240 */
2241 fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr;
2242 cm = sc->aac_commands + (fib_index >> 2);
2243 *fib_addr = cm->cm_fib;
2244
2245 /*
2246 * Is this a fast response? If it is, update the fib fields in
2247 * local memory since the whole fib isn't DMA'd back up.
2248 */
2249 if (fib_index & 0x01) {
2250 (*fib_addr)->Header.XferState |= AAC_FIBSTATE_DONEADAP;
2251 *((u_int32_t*)((*fib_addr)->data)) = AAC_ERROR_NORMAL;
2252 }
2253 break;
2254 }
2255 default:
2256 panic("Invalid queue in aac_dequeue_fib()");
2257 break;
984263bc 2258 }
d9773475 2259
984263bc
MD
2260 /* update consumer index */
2261 sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
2262
2263 /* if we have made the queue un-full, notify the adapter */
2264 if (notify && (aac_qinfo[queue].notify != 0))
2265 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
2266 error = 0;
2267
2268out:
984263bc
MD
2269 return(error);
2270}
2271
2272/*
2273 * Put our response to an Adapter Initialed Fib on the response queue
2274 */
2275static int
2276aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
2277{
2278 u_int32_t pi, ci;
7f2216bc 2279 int error;
984263bc
MD
2280 u_int32_t fib_size;
2281 u_int32_t fib_addr;
2282
e9ae7f4f 2283 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
2284
2285 /* Tell the adapter where the FIB is */
d9773475 2286 fib_size = fib->Header.Size;
984263bc
MD
2287 fib_addr = fib->Header.SenderFibAddress;
2288 fib->Header.ReceiverFibAddress = fib_addr;
2289
984263bc
MD
2290 /* get the producer/consumer indices */
2291 pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
2292 ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
2293
2294 /* wrap the queue? */
2295 if (pi >= aac_qinfo[queue].size)
2296 pi = 0;
2297
2298 /* check for queue full */
2299 if ((pi + 1) == ci) {
2300 error = EBUSY;
2301 goto out;
2302 }
2303
2304 /* populate queue entry */
2305 (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
2306 (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
2307
2308 /* update producer index */
2309 sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
2310
2311 /* notify the adapter if we know how */
2312 if (aac_qinfo[queue].notify != 0)
2313 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
2314
2315 error = 0;
2316
2317out:
984263bc
MD
2318 return(error);
2319}
2320
2321/*
2322 * Check for commands that have been outstanding for a suspiciously long time,
2323 * and complain about them.
2324 */
2325static void
e9ae7f4f 2326aac_timeout(struct aac_softc *sc)
984263bc 2327{
984263bc
MD
2328 struct aac_command *cm;
2329 time_t deadline;
158dbeb8 2330 int timedout, code;
e9ae7f4f 2331
984263bc 2332 /*
d9773475 2333 * Traverse the busy command list, bitch about late commands once
984263bc
MD
2334 * only.
2335 */
158dbeb8 2336 timedout = 0;
cec73927 2337 deadline = time_uptime - AAC_CMD_TIMEOUT;
984263bc
MD
2338 TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) {
2339 if ((cm->cm_timestamp < deadline)
e9ae7f4f 2340 && !(cm->cm_flags & AAC_CMD_TIMEDOUT)) {
984263bc
MD
2341 cm->cm_flags |= AAC_CMD_TIMEDOUT;
2342 device_printf(sc->aac_dev,
e9ae7f4f
SW
2343 "COMMAND %p (TYPE %d) TIMEOUT AFTER %d SECONDS\n",
2344 cm, cm->cm_fib->Header.Command,
cec73927 2345 (int)(time_uptime-cm->cm_timestamp));
984263bc 2346 AAC_PRINT_FIB(sc, cm->cm_fib);
158dbeb8
MD
2347 timedout++;
2348 }
2349 }
e9ae7f4f 2350
158dbeb8
MD
2351 if (timedout) {
2352 code = AAC_GET_FWSTATUS(sc);
2353 if (code != AAC_UP_AND_RUNNING) {
2354 device_printf(sc->aac_dev, "WARNING! Controller is no "
2355 "longer running! code= 0x%x\n", code);
984263bc
MD
2356 }
2357 }
984263bc
MD
2358}
2359
2360/*
2361 * Interface Function Vectors
2362 */
2363
2364/*
2365 * Read the current firmware status word.
2366 */
2367static int
2368aac_sa_get_fwstatus(struct aac_softc *sc)
2369{
e9ae7f4f 2370 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2371
e9ae7f4f 2372 return(AAC_MEM0_GETREG4(sc, AAC_SA_FWSTATUS));
984263bc
MD
2373}
2374
2375static int
2376aac_rx_get_fwstatus(struct aac_softc *sc)
2377{
e9ae7f4f 2378 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2379
e9ae7f4f
SW
2380 return(AAC_MEM0_GETREG4(sc, sc->flags & AAC_FLAGS_NEW_COMM ?
2381 AAC_RX_OMR0 : AAC_RX_FWSTATUS));
984263bc
MD
2382}
2383
d9773475
PA
2384static int
2385aac_rkt_get_fwstatus(struct aac_softc *sc)
2386{
e9ae7f4f 2387 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 2388
e9ae7f4f
SW
2389 return(AAC_MEM0_GETREG4(sc, sc->flags & AAC_FLAGS_NEW_COMM ?
2390 AAC_RKT_OMR0 : AAC_RKT_FWSTATUS));
d9773475
PA
2391}
2392
984263bc
MD
2393/*
2394 * Notify the controller of a change in a given queue
2395 */
2396
2397static void
2398aac_sa_qnotify(struct aac_softc *sc, int qbit)
2399{
e9ae7f4f 2400 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2401
e9ae7f4f 2402 AAC_MEM0_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit);
984263bc
MD
2403}
2404
2405static void
2406aac_rx_qnotify(struct aac_softc *sc, int qbit)
2407{
e9ae7f4f 2408 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2409
e9ae7f4f 2410 AAC_MEM0_SETREG4(sc, AAC_RX_IDBR, qbit);
984263bc
MD
2411}
2412
d9773475
PA
2413static void
2414aac_rkt_qnotify(struct aac_softc *sc, int qbit)
2415{
e9ae7f4f 2416 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 2417
e9ae7f4f 2418 AAC_MEM0_SETREG4(sc, AAC_RKT_IDBR, qbit);
d9773475
PA
2419}
2420
984263bc
MD
2421/*
2422 * Get the interrupt reason bits
2423 */
2424static int
2425aac_sa_get_istatus(struct aac_softc *sc)
2426{
e9ae7f4f 2427 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2428
e9ae7f4f 2429 return(AAC_MEM0_GETREG2(sc, AAC_SA_DOORBELL0));
984263bc
MD
2430}
2431
2432static int
2433aac_rx_get_istatus(struct aac_softc *sc)
2434{
e9ae7f4f 2435 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2436
e9ae7f4f 2437 return(AAC_MEM0_GETREG4(sc, AAC_RX_ODBR));
984263bc
MD
2438}
2439
d9773475
PA
2440static int
2441aac_rkt_get_istatus(struct aac_softc *sc)
2442{
e9ae7f4f 2443 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 2444
e9ae7f4f 2445 return(AAC_MEM0_GETREG4(sc, AAC_RKT_ODBR));
d9773475
PA
2446}
2447
984263bc
MD
2448/*
2449 * Clear some interrupt reason bits
2450 */
2451static void
2452aac_sa_clear_istatus(struct aac_softc *sc, int mask)
2453{
e9ae7f4f 2454 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2455
e9ae7f4f 2456 AAC_MEM0_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask);
984263bc
MD
2457}
2458
2459static void
2460aac_rx_clear_istatus(struct aac_softc *sc, int mask)
2461{
e9ae7f4f 2462 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2463
e9ae7f4f 2464 AAC_MEM0_SETREG4(sc, AAC_RX_ODBR, mask);
984263bc
MD
2465}
2466
d9773475
PA
2467static void
2468aac_rkt_clear_istatus(struct aac_softc *sc, int mask)
2469{
e9ae7f4f 2470 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 2471
e9ae7f4f 2472 AAC_MEM0_SETREG4(sc, AAC_RKT_ODBR, mask);
d9773475
PA
2473}
2474
984263bc
MD
2475/*
2476 * Populate the mailbox and set the command word
2477 */
2478static void
2479aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
2480 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2481{
e9ae7f4f 2482 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2483
e9ae7f4f
SW
2484 AAC_MEM1_SETREG4(sc, AAC_SA_MAILBOX, command);
2485 AAC_MEM1_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0);
2486 AAC_MEM1_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1);
2487 AAC_MEM1_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2);
2488 AAC_MEM1_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3);
984263bc
MD
2489}
2490
2491static void
2492aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command,
2493 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2494{
e9ae7f4f 2495 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2496
e9ae7f4f
SW
2497 AAC_MEM1_SETREG4(sc, AAC_RX_MAILBOX, command);
2498 AAC_MEM1_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0);
2499 AAC_MEM1_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1);
2500 AAC_MEM1_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2);
2501 AAC_MEM1_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3);
984263bc
MD
2502}
2503
d9773475
PA
2504static void
2505aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
2506 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2507{
e9ae7f4f 2508 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 2509
e9ae7f4f
SW
2510 AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX, command);
2511 AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0);
2512 AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1);
2513 AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2);
2514 AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3);
d9773475
PA
2515}
2516
984263bc
MD
2517/*
2518 * Fetch the immediate command status word
2519 */
2520static int
2521aac_sa_get_mailbox(struct aac_softc *sc, int mb)
2522{
e9ae7f4f 2523 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2524
e9ae7f4f 2525 return(AAC_MEM1_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4)));
984263bc
MD
2526}
2527
2528static int
2529aac_rx_get_mailbox(struct aac_softc *sc, int mb)
2530{
e9ae7f4f 2531 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2532
e9ae7f4f 2533 return(AAC_MEM1_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4)));
984263bc
MD
2534}
2535
d9773475
PA
2536static int
2537aac_rkt_get_mailbox(struct aac_softc *sc, int mb)
2538{
e9ae7f4f 2539 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 2540
e9ae7f4f 2541 return(AAC_MEM1_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4)));
d9773475
PA
2542}
2543
984263bc
MD
2544/*
2545 * Set/clear interrupt masks
2546 */
2547static void
2548aac_sa_set_interrupts(struct aac_softc *sc, int enable)
2549{
e9ae7f4f 2550 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "%sable interrupts", enable ? "en" : "dis");
984263bc
MD
2551
2552 if (enable) {
e9ae7f4f 2553 AAC_MEM0_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
984263bc 2554 } else {
e9ae7f4f 2555 AAC_MEM0_SETREG2((sc), AAC_SA_MASK0_SET, ~0);
984263bc
MD
2556 }
2557}
2558
2559static void
2560aac_rx_set_interrupts(struct aac_softc *sc, int enable)
2561{
e9ae7f4f 2562 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "%sable interrupts", enable ? "en" : "dis");
984263bc
MD
2563
2564 if (enable) {
d9773475 2565 if (sc->flags & AAC_FLAGS_NEW_COMM)
e9ae7f4f 2566 AAC_MEM0_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INT_NEW_COMM);
d9773475 2567 else
e9ae7f4f 2568 AAC_MEM0_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
984263bc 2569 } else {
e9ae7f4f 2570 AAC_MEM0_SETREG4(sc, AAC_RX_OIMR, ~0);
984263bc
MD
2571 }
2572}
2573
d9773475
PA
2574static void
2575aac_rkt_set_interrupts(struct aac_softc *sc, int enable)
2576{
e9ae7f4f 2577 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "%sable interrupts", enable ? "en" : "dis");
d9773475
PA
2578
2579 if (enable) {
2580 if (sc->flags & AAC_FLAGS_NEW_COMM)
e9ae7f4f 2581 AAC_MEM0_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INT_NEW_COMM);
d9773475 2582 else
e9ae7f4f 2583 AAC_MEM0_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS);
d9773475 2584 } else {
e9ae7f4f 2585 AAC_MEM0_SETREG4(sc, AAC_RKT_OIMR, ~0);
d9773475
PA
2586 }
2587}
2588
2589/*
2590 * New comm. interface: Send command functions
2591 */
2592static int
2593aac_rx_send_command(struct aac_softc *sc, struct aac_command *cm)
2594{
2595 u_int32_t index, device;
2596
e9ae7f4f 2597 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "send command (new comm.)");
d9773475 2598
e9ae7f4f 2599 index = AAC_MEM0_GETREG4(sc, AAC_RX_IQUE);
d9773475 2600 if (index == 0xffffffffL)
e9ae7f4f 2601 index = AAC_MEM0_GETREG4(sc, AAC_RX_IQUE);
d9773475
PA
2602 if (index == 0xffffffffL)
2603 return index;
2604 aac_enqueue_busy(cm);
2605 device = index;
e9ae7f4f 2606 AAC_MEM1_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys & 0xffffffffUL));
d9773475 2607 device += 4;
e9ae7f4f 2608 AAC_MEM1_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys >> 32));
d9773475 2609 device += 4;
e9ae7f4f
SW
2610 AAC_MEM1_SETREG4(sc, device, cm->cm_fib->Header.Size);
2611 AAC_MEM0_SETREG4(sc, AAC_RX_IQUE, index);
d9773475
PA
2612 return 0;
2613}
2614
2615static int
2616aac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm)
2617{
2618 u_int32_t index, device;
2619
e9ae7f4f 2620 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "send command (new comm.)");
d9773475 2621
e9ae7f4f 2622 index = AAC_MEM0_GETREG4(sc, AAC_RKT_IQUE);
d9773475 2623 if (index == 0xffffffffL)
e9ae7f4f 2624 index = AAC_MEM0_GETREG4(sc, AAC_RKT_IQUE);
d9773475
PA
2625 if (index == 0xffffffffL)
2626 return index;
2627 aac_enqueue_busy(cm);
2628 device = index;
e9ae7f4f 2629 AAC_MEM1_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys & 0xffffffffUL));
d9773475 2630 device += 4;
e9ae7f4f 2631 AAC_MEM1_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys >> 32));
d9773475 2632 device += 4;
e9ae7f4f
SW
2633 AAC_MEM1_SETREG4(sc, device, cm->cm_fib->Header.Size);
2634 AAC_MEM0_SETREG4(sc, AAC_RKT_IQUE, index);
d9773475
PA
2635 return 0;
2636}
2637
2638/*
2639 * New comm. interface: get, set outbound queue index
2640 */
2641static int
2642aac_rx_get_outb_queue(struct aac_softc *sc)
2643{
e9ae7f4f 2644 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 2645
e9ae7f4f 2646 return(AAC_MEM0_GETREG4(sc, AAC_RX_OQUE));
d9773475
PA
2647}
2648
2649static int
2650aac_rkt_get_outb_queue(struct aac_softc *sc)
2651{
e9ae7f4f 2652 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 2653
e9ae7f4f 2654 return(AAC_MEM0_GETREG4(sc, AAC_RKT_OQUE));
d9773475
PA
2655}
2656
2657static void
2658aac_rx_set_outb_queue(struct aac_softc *sc, int index)
2659{
e9ae7f4f 2660 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 2661
e9ae7f4f 2662 AAC_MEM0_SETREG4(sc, AAC_RX_OQUE, index);
d9773475
PA
2663}
2664
2665static void
2666aac_rkt_set_outb_queue(struct aac_softc *sc, int index)
2667{
e9ae7f4f 2668 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
d9773475 2669
e9ae7f4f 2670 AAC_MEM0_SETREG4(sc, AAC_RKT_OQUE, index);
d9773475
PA
2671}
2672
984263bc
MD
2673/*
2674 * Debugging and Diagnostics
2675 */
2676
2677/*
2678 * Print some information about the controller.
2679 */
2680static void
2681aac_describe_controller(struct aac_softc *sc)
2682{
2683 struct aac_fib *fib;
2684 struct aac_adapter_info *info;
e9ae7f4f 2685 char *adapter_type = "Adaptec RAID controller";
984263bc 2686
e9ae7f4f 2687 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2688
e9ae7f4f 2689 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
d9773475 2690 aac_alloc_sync_fib(sc, &fib);
984263bc
MD
2691
2692 fib->data[0] = 0;
2693 if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) {
2694 device_printf(sc->aac_dev, "RequestAdapterInfo failed\n");
2695 aac_release_sync_fib(sc);
e9ae7f4f 2696 lockmgr(&sc->aac_io_lock, LK_RELEASE);
984263bc
MD
2697 return;
2698 }
984263bc
MD
2699
2700 /* save the kernel revision structure for later use */
d9773475 2701 info = (struct aac_adapter_info *)&fib->data[0];
984263bc 2702 sc->aac_revision = info->KernelRevision;
984263bc 2703
d9773475
PA
2704 if (bootverbose) {
2705 device_printf(sc->aac_dev, "%s %dMHz, %dMB memory "
2706 "(%dMB cache, %dMB execution), %s\n",
2707 aac_describe_code(aac_cpu_variant, info->CpuVariant),
2708 info->ClockSpeed, info->TotalMem / (1024 * 1024),
2709 info->BufferMem / (1024 * 1024),
2710 info->ExecutionMem / (1024 * 1024),
2711 aac_describe_code(aac_battery_platform,
2712 info->batteryPlatform));
2713
2714 device_printf(sc->aac_dev,
2715 "Kernel %d.%d-%d, Build %d, S/N %6X\n",
2716 info->KernelRevision.external.comp.major,
2717 info->KernelRevision.external.comp.minor,
2718 info->KernelRevision.external.comp.dash,
2719 info->KernelRevision.buildNumber,
2720 (u_int32_t)(info->SerialNumber & 0xffffff));
984263bc 2721
c3783d8f 2722 device_printf(sc->aac_dev, "Supported Options=%pb%i\n",
984263bc
MD
2723 "\20"
2724 "\1SNAPSHOT"
2725 "\2CLUSTERS"
2726 "\3WCACHE"
2727 "\4DATA64"
2728 "\5HOSTTIME"
2729 "\6RAID50"
2730 "\7WINDOW4GB"
2731 "\10SCSIUPGD"
2732 "\11SOFTERR"
2733 "\12NORECOND"
2734 "\13SGMAP64"
2735 "\14ALARM"
d9773475
PA
2736 "\15NONDASD"
2737 "\16SCSIMGT"
2738 "\17RAIDSCSI"
2739 "\21ADPTINFO"
2740 "\22NEWCOMM"
2741 "\23ARRAY64BIT"
c3783d8f 2742 "\24HEATSENSOR"
2743 , sc->supported_options);
984263bc 2744 }
e9ae7f4f
SW
2745
2746 if (sc->supported_options & AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO) {
2747 fib->data[0] = 0;
2748 if (aac_sync_fib(sc, RequestSupplementAdapterInfo, 0, fib, 1))
2749 device_printf(sc->aac_dev,
2750 "RequestSupplementAdapterInfo failed\n");
2751 else
2752 adapter_type = ((struct aac_supplement_adapter_info *)
2753 &fib->data[0])->AdapterTypeText;
2754 }
2755 device_printf(sc->aac_dev, "%s, aac driver %d.%d.%d-%d\n",
2756 adapter_type,
2757 AAC_DRIVER_MAJOR_VERSION, AAC_DRIVER_MINOR_VERSION,
2758 AAC_DRIVER_BUGFIX_LEVEL, AAC_DRIVER_BUILD);
2759
d9773475 2760 aac_release_sync_fib(sc);
e9ae7f4f 2761 lockmgr(&sc->aac_io_lock, LK_RELEASE);
984263bc
MD
2762}
2763
2764/*
2765 * Look up a text description of a numeric error code and return a pointer to
2766 * same.
2767 */
b4df2201
SW
2768static const char *
2769aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
984263bc
MD
2770{
2771 int i;
2772
2773 for (i = 0; table[i].string != NULL; i++)
2774 if (table[i].code == code)
2775 return(table[i].string);
2776 return(table[i + 1].string);
2777}
2778
2779/*
2780 * Management Interface
2781 */
2782
2783static int
fef8985e 2784aac_open(struct dev_open_args *ap)
984263bc 2785{
b13267a5 2786 cdev_t dev = ap->a_head.a_dev;
984263bc
MD
2787 struct aac_softc *sc;
2788
984263bc 2789 sc = dev->si_drv1;
e9ae7f4f
SW
2790 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
2791 device_busy(sc->aac_dev);
984263bc
MD
2792
2793 return 0;
2794}
2795
2796static int
fef8985e 2797aac_ioctl(struct dev_ioctl_args *ap)
984263bc 2798{
fef8985e 2799 caddr_t arg = ap->a_data;
e9ae7f4f
SW
2800 cdev_t dev = ap->a_head.a_dev;
2801 u_long cmd = ap->a_cmd;
2802 union aac_statrequest *as;
2803 struct aac_softc *sc;
984263bc 2804 int error = 0;
984263bc 2805
e9ae7f4f
SW
2806 as = (union aac_statrequest *)arg;
2807 sc = dev->si_drv1;
2808 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc 2809
e9ae7f4f
SW
2810 switch (cmd) {
2811 case AACIO_STATS:
984263bc
MD
2812 switch (as->as_item) {
2813 case AACQ_FREE:
2814 case AACQ_BIO:
2815 case AACQ_READY:
2816 case AACQ_BUSY:
984263bc
MD
2817 bcopy(&sc->aac_qstat[as->as_item], &as->as_qstat,
2818 sizeof(struct aac_qstat));
2819 break;
2820 default:
2821 error = ENOENT;
2822 break;
2823 }
e9ae7f4f 2824 break;
3930af25 2825
984263bc 2826 case FSACTL_SENDFIB:
e9ae7f4f
SW
2827 case FSACTL_SEND_LARGE_FIB:
2828 arg = *(caddr_t*)arg;
2829 case FSACTL_LNX_SENDFIB:
2830 case FSACTL_LNX_SEND_LARGE_FIB:
2831 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_SENDFIB");
984263bc
MD
2832 error = aac_ioctl_sendfib(sc, arg);
2833 break;
e9ae7f4f
SW
2834 case FSACTL_SEND_RAW_SRB:
2835 arg = *(caddr_t*)arg;
2836 case FSACTL_LNX_SEND_RAW_SRB:
2837 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_SEND_RAW_SRB");
2838 error = aac_ioctl_send_raw_srb(sc, arg);
2839 break;
984263bc 2840 case FSACTL_AIF_THREAD:
e9ae7f4f
SW
2841 case FSACTL_LNX_AIF_THREAD:
2842 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_AIF_THREAD");
984263bc
MD
2843 error = EINVAL;
2844 break;
2845 case FSACTL_OPEN_GET_ADAPTER_FIB:
e9ae7f4f
SW
2846 arg = *(caddr_t*)arg;
2847 case FSACTL_LNX_OPEN_GET_ADAPTER_FIB:
2848 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_OPEN_GET_ADAPTER_FIB");
2849 error = aac_open_aif(sc, arg);
984263bc
MD
2850 break;
2851 case FSACTL_GET_NEXT_ADAPTER_FIB:
e9ae7f4f
SW
2852 arg = *(caddr_t*)arg;
2853 case FSACTL_LNX_GET_NEXT_ADAPTER_FIB:
2854 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_GET_NEXT_ADAPTER_FIB");
984263bc
MD
2855 error = aac_getnext_aif(sc, arg);
2856 break;
2857 case FSACTL_CLOSE_GET_ADAPTER_FIB:
e9ae7f4f
SW
2858 arg = *(caddr_t*)arg;
2859 case FSACTL_LNX_CLOSE_GET_ADAPTER_FIB:
2860 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_CLOSE_GET_ADAPTER_FIB");
2861 error = aac_close_aif(sc, arg);
984263bc
MD
2862 break;
2863 case FSACTL_MINIPORT_REV_CHECK:
e9ae7f4f
SW
2864 arg = *(caddr_t*)arg;
2865 case FSACTL_LNX_MINIPORT_REV_CHECK:
2866 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_MINIPORT_REV_CHECK");
984263bc
MD
2867 error = aac_rev_check(sc, arg);
2868 break;
2869 case FSACTL_QUERY_DISK:
e9ae7f4f
SW
2870 arg = *(caddr_t*)arg;
2871 case FSACTL_LNX_QUERY_DISK:
2872 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_QUERY_DISK");
984263bc 2873 error = aac_query_disk(sc, arg);
d9773475 2874 break;
984263bc 2875 case FSACTL_DELETE_DISK:
e9ae7f4f 2876 case FSACTL_LNX_DELETE_DISK:
984263bc
MD
2877 /*
2878 * We don't trust the underland to tell us when to delete a
d9773475 2879 * container, rather we rely on an AIF coming from the
984263bc
MD
2880 * controller
2881 */
2882 error = 0;
2883 break;
d9773475
PA
2884 case FSACTL_GET_PCI_INFO:
2885 arg = *(caddr_t*)arg;
2886 case FSACTL_LNX_GET_PCI_INFO:
e9ae7f4f 2887 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_GET_PCI_INFO");
d9773475
PA
2888 error = aac_get_pci_info(sc, arg);
2889 break;
e9ae7f4f
SW
2890 case FSACTL_GET_FEATURES:
2891 arg = *(caddr_t*)arg;
2892 case FSACTL_LNX_GET_FEATURES:
2893 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_GET_FEATURES");
2894 error = aac_supported_features(sc, arg);
2895 break;
984263bc 2896 default:
e9ae7f4f 2897 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "unsupported cmd 0x%lx\n", cmd);
984263bc
MD
2898 error = EINVAL;
2899 break;
2900 }
2901 return(error);
2902}
2903
eda1a08c 2904static struct filterops aac_filterops =
e9ae7f4f 2905 { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, aac_filter_detach, aac_filter_read };
eda1a08c
SG
2906
2907static int
2908aac_kqfilter(struct dev_kqfilter_args *ap)
2909{
2910 cdev_t dev = ap->a_head.a_dev;
2911 struct aac_softc *sc = dev->si_drv1;
2912 struct knote *kn = ap->a_kn;
2913 struct klist *klist;
2914
2915 ap->a_result = 0;
2916
2917 switch (kn->kn_filter) {
2918 case EVFILT_READ:
2919 kn->kn_fop = &aac_filterops;
2920 kn->kn_hook = (caddr_t)sc;
2921 break;
2922 default:
b287d649 2923 ap->a_result = EOPNOTSUPP;
eda1a08c
SG
2924 return (0);
2925 }
2926
5b22f1a7
SG
2927 klist = &sc->rcv_kq.ki_note;
2928 knote_insert(klist, kn);
eda1a08c
SG
2929
2930 return (0);
2931}
2932
2933static void
2934aac_filter_detach(struct knote *kn)
2935{
2936 struct aac_softc *sc = (struct aac_softc *)kn->kn_hook;
2937 struct klist *klist;
2938
5b22f1a7
SG
2939 klist = &sc->rcv_kq.ki_note;
2940 knote_remove(klist, kn);
eda1a08c
SG
2941}
2942
2943static int
e9ae7f4f 2944aac_filter_read(struct knote *kn, long hint)
eda1a08c 2945{
e9ae7f4f
SW
2946 struct aac_softc *sc;
2947 struct aac_fib_context *ctx;
bcbcb2e6 2948 int ret = 0;
eda1a08c 2949
e9ae7f4f 2950 sc = (struct aac_softc *)kn->kn_hook;
eda1a08c 2951
e9ae7f4f
SW
2952 lockmgr(&sc->aac_aifq_lock, LK_EXCLUSIVE);
2953 for (ctx = sc->fibctx; ctx; ctx = ctx->next)
2954 if (ctx->ctx_idx != sc->aifq_idx || ctx->ctx_wrap)
bcbcb2e6 2955 ret = 1;
e9ae7f4f 2956 lockmgr(&sc->aac_aifq_lock, LK_RELEASE);
eda1a08c 2957
bcbcb2e6 2958 return(ret);
e9ae7f4f 2959}
eda1a08c 2960
d9773475
PA
2961static void
2962aac_ioctl_event(struct aac_softc *sc, struct aac_event *event, void *arg)
2963{
2964
2965 switch (event->ev_type) {
2966 case AAC_EVENT_CMFREE:
e9ae7f4f 2967 KKASSERT(lockstatus(&sc->aac_io_lock, curthread) != 0);
d9773475
PA
2968 if (aac_alloc_command(sc, (struct aac_command **)arg)) {
2969 aac_add_event(sc, event);
d9773475
PA
2970 return;
2971 }
2972 kfree(event, M_AACBUF);
2973 wakeup(arg);
d9773475
PA
2974 break;
2975 default:
2976 break;
2977 }
2978}
2979
984263bc
MD
2980/*
2981 * Send a FIB supplied from userspace
2982 */
2983static int
2984aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib)
2985{
2986 struct aac_command *cm;
2987 int size, error;
2988
e9ae7f4f 2989 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
2990
2991 cm = NULL;
2992
2993 /*
2994 * Get a command
2995 */
e9ae7f4f 2996 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
984263bc 2997 if (aac_alloc_command(sc, &cm)) {
d9773475
PA
2998 struct aac_event *event;
2999
3000 event = kmalloc(sizeof(struct aac_event), M_AACBUF,
3001 M_INTWAIT | M_ZERO);
3002 event->ev_type = AAC_EVENT_CMFREE;
3003 event->ev_callback = aac_ioctl_event;
3004 event->ev_arg = &cm;
3005 aac_add_event(sc, event);
e9ae7f4f 3006 lksleep(&cm, &sc->aac_io_lock, 0, "sendfib", 0);
984263bc 3007 }
e9ae7f4f 3008 lockmgr(&sc->aac_io_lock, LK_RELEASE);
984263bc
MD
3009
3010 /*
3011 * Fetch the FIB header, then re-copy to get data as well.
3012 */
3013 if ((error = copyin(ufib, cm->cm_fib,
3014 sizeof(struct aac_fib_header))) != 0)
3015 goto out;
3016 size = cm->cm_fib->Header.Size + sizeof(struct aac_fib_header);
e9ae7f4f
SW
3017 if (size > sc->aac_max_fib_size) {
3018 device_printf(sc->aac_dev, "incoming FIB oversized (%d > %d)\n",
3019 size, sc->aac_max_fib_size);
3020 size = sc->aac_max_fib_size;
984263bc
MD
3021 }
3022 if ((error = copyin(ufib, cm->cm_fib, size)) != 0)
3023 goto out;
3024 cm->cm_fib->Header.Size = size;
cec73927 3025 cm->cm_timestamp = time_uptime;
984263bc
MD
3026
3027 /*
3028 * Pass the FIB to the controller, wait for it to complete.
3029 */
e9ae7f4f
SW
3030 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
3031 error = aac_wait_command(cm);
3032 lockmgr(&sc->aac_io_lock, LK_RELEASE);
3033 if (error != 0) {
d9773475
PA
3034 device_printf(sc->aac_dev,
3035 "aac_wait_command return %d\n", error);
984263bc
MD
3036 goto out;
3037 }
3038
3039 /*
3040 * Copy the FIB and data back out to the caller.
3041 */
3042 size = cm->cm_fib->Header.Size;
e9ae7f4f
SW
3043 if (size > sc->aac_max_fib_size) {
3044 device_printf(sc->aac_dev, "outbound FIB oversized (%d > %d)\n",
3045 size, sc->aac_max_fib_size);
3046 size = sc->aac_max_fib_size;
984263bc
MD
3047 }
3048 error = copyout(cm->cm_fib, ufib, size);
3049
3050out:
3051 if (cm != NULL) {
e9ae7f4f 3052 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
984263bc 3053 aac_release_command(cm);
e9ae7f4f
SW
3054 lockmgr(&sc->aac_io_lock, LK_RELEASE);
3055 }
3056 return(error);
3057}
3058
3059/*
3060 * Send a passthrough FIB supplied from userspace
3061 */
3062static int
3063aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg)
3064{
3065 struct aac_command *cm;
3066 struct aac_event *event;
3067 struct aac_fib *fib;
3068 struct aac_srb *srbcmd, *user_srb;
3069 struct aac_sg_entry *sge;
878b1602 3070#ifdef __x86_64__
e9ae7f4f 3071 struct aac_sg_entry64 *sge64;
878b1602 3072#endif
e9ae7f4f
SW
3073 void *srb_sg_address, *ureply;
3074 uint32_t fibsize, srb_sg_bytecount;
3075 int error, transfer_data;
3076
3077 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
3078
3079 cm = NULL;
3080 transfer_data = 0;
3081 fibsize = 0;
3082 user_srb = (struct aac_srb *)arg;
3083
3084 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
3085 if (aac_alloc_command(sc, &cm)) {
3086 event = kmalloc(sizeof(struct aac_event), M_AACBUF,
3087 M_NOWAIT | M_ZERO);
3088 if (event == NULL) {
3089 error = EBUSY;
3090 lockmgr(&sc->aac_io_lock, LK_RELEASE);
3091 goto out;
3092 }
3093 event->ev_type = AAC_EVENT_CMFREE;
3094 event->ev_callback = aac_ioctl_event;
3095 event->ev_arg = &cm;
3096 aac_add_event(sc, event);
3097 lksleep(cm, &sc->aac_io_lock, 0, "aacraw", 0);
3098 }
3099 lockmgr(&sc->aac_io_lock, LK_RELEASE);
3100
3101 cm->cm_data = NULL;
3102 fib = cm->cm_fib;
3103 srbcmd = (struct aac_srb *)fib->data;
3104 error = copyin(&user_srb->data_len, &fibsize, sizeof(uint32_t));
3105 if (error != 0)
3106 goto out;
3107 if (fibsize > (sc->aac_max_fib_size - sizeof(struct aac_fib_header))) {
3108 error = EINVAL;
3109 goto out;
3110 }
3111 error = copyin(user_srb, srbcmd, fibsize);
3112 if (error != 0)
3113 goto out;
3114 srbcmd->function = 0;
3115 srbcmd->retry_limit = 0;
3116 if (srbcmd->sg_map.SgCount > 1) {
3117 error = EINVAL;
3118 goto out;
3119 }
3120
3121 /* Retrieve correct SG entries. */
3122 if (fibsize == (sizeof(struct aac_srb) +
3123 srbcmd->sg_map.SgCount * sizeof(struct aac_sg_entry))) {
3124 sge = srbcmd->sg_map.SgEntry;
e9ae7f4f
SW
3125 srb_sg_bytecount = sge->SgByteCount;
3126 srb_sg_address = (void *)(uintptr_t)sge->SgAddress;
3127 }
dbefba87 3128#ifdef __x86_64__
e9ae7f4f
SW
3129 else if (fibsize == (sizeof(struct aac_srb) +
3130 srbcmd->sg_map.SgCount * sizeof(struct aac_sg_entry64))) {
3131 sge = NULL;
3132 sge64 = (struct aac_sg_entry64 *)srbcmd->sg_map.SgEntry;
3133 srb_sg_bytecount = sge64->SgByteCount;
3134 srb_sg_address = (void *)sge64->SgAddress;
3135 if (sge64->SgAddress > 0xffffffffull &&
3136 (sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
3137 error = EINVAL;
3138 goto out;
3139 }
3140 }
3141#endif
3142 else {
3143 error = EINVAL;
3144 goto out;
3145 }
3146 ureply = (char *)arg + fibsize;
3147 srbcmd->data_len = srb_sg_bytecount;
3148 if (srbcmd->sg_map.SgCount == 1)
3149 transfer_data = 1;
3150
3151 cm->cm_sgtable = (struct aac_sg_table *)&srbcmd->sg_map;
3152 if (transfer_data) {
3153 cm->cm_datalen = srb_sg_bytecount;
3154 cm->cm_data = kmalloc(cm->cm_datalen, M_AACBUF, M_NOWAIT);
3155 if (cm->cm_data == NULL) {
3156 error = ENOMEM;
3157 goto out;
3158 }
3159 if (srbcmd->flags & AAC_SRB_FLAGS_DATA_IN)
3160 cm->cm_flags |= AAC_CMD_DATAIN;
3161 if (srbcmd->flags & AAC_SRB_FLAGS_DATA_OUT) {
3162 cm->cm_flags |= AAC_CMD_DATAOUT;
3163 error = copyin(srb_sg_address, cm->cm_data,
3164 cm->cm_datalen);
3165 if (error != 0)
3166 goto out;
3167 }
984263bc 3168 }
d9773475 3169
e9ae7f4f
SW
3170 fib->Header.Size = sizeof(struct aac_fib_header) +
3171 sizeof(struct aac_srb);
3172 fib->Header.XferState =
3173 AAC_FIBSTATE_HOSTOWNED |
3174 AAC_FIBSTATE_INITIALISED |
3175 AAC_FIBSTATE_EMPTY |
3176 AAC_FIBSTATE_FROMHOST |
3177 AAC_FIBSTATE_REXPECTED |
3178 AAC_FIBSTATE_NORM |
3179 AAC_FIBSTATE_ASYNC |
3180 AAC_FIBSTATE_FAST_RESPONSE;
3181 fib->Header.Command = (sc->flags & AAC_FLAGS_SG_64BIT) != 0 ?
3182 ScsiPortCommandU64 : ScsiPortCommand;
3183
3184 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
3185 aac_wait_command(cm);
3186 lockmgr(&sc->aac_io_lock, LK_RELEASE);
3187
3188 if (transfer_data && (srbcmd->flags & AAC_SRB_FLAGS_DATA_IN) != 0) {
3189 error = copyout(cm->cm_data, srb_sg_address, cm->cm_datalen);
3190 if (error != 0)
3191 goto out;
3192 }
3193 error = copyout(fib->data, ureply, sizeof(struct aac_srb_response));
3194out:
3195 if (cm != NULL) {
3196 if (cm->cm_data != NULL)
3197 kfree(cm->cm_data, M_AACBUF);
3198 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
3199 aac_release_command(cm);
3200 lockmgr(&sc->aac_io_lock, LK_RELEASE);
3201 }
984263bc
MD
3202 return(error);
3203}
3204
e9ae7f4f
SW
3205static int
3206aac_close(struct dev_close_args *ap)
3207{
3208 cdev_t dev = ap->a_head.a_dev;
3209 struct aac_softc *sc;
3210
3211 sc = dev->si_drv1;
3212 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
3213 get_mplock();
3214 device_unbusy(sc->aac_dev);
3215 rel_mplock();
3216
3217 return 0;
3218}
3219
984263bc
MD
3220/*
3221 * Handle an AIF sent to us by the controller; queue it for later reference.
3222 * If the queue fills up, then drop the older entries.
3223 */
3224static void
3225aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
3226{
3227 struct aac_aif_command *aif;
3228 struct aac_container *co, *co_next;
e9ae7f4f
SW
3229 struct aac_fib_context *ctx;
3230 struct aac_mntinforesp *mir;
3231 int next, current, found;
158dbeb8 3232 int count = 0, added = 0, i = 0;
e9ae7f4f 3233 uint32_t channel;
984263bc 3234
e9ae7f4f 3235 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
3236
3237 aif = (struct aac_aif_command*)&fib->data[0];
3238 aac_print_aif(sc, aif);
3239
3240 /* Is it an event that we should care about? */
3241 switch (aif->command) {
3242 case AifCmdEventNotify:
3243 switch (aif->data.EN.type) {
3244 case AifEnAddContainer:
3245 case AifEnDeleteContainer:
3246 /*
d9773475 3247 * A container was added or deleted, but the message
984263bc
MD
3248 * doesn't tell us anything else! Re-enumerate the
3249 * containers and sort things out.
3250 */
d9773475 3251 aac_alloc_sync_fib(sc, &fib);
984263bc
MD
3252 do {
3253 /*
3254 * Ask the controller for its containers one at
3255 * a time.
3256 * XXX What if the controller's list changes
3257 * midway through this enumaration?
3258 * XXX This should be done async.
3259 */
e9ae7f4f 3260 if ((mir = aac_get_container_info(sc, fib, i)) == NULL)
984263bc 3261 continue;
e9ae7f4f
SW
3262 if (i == 0)
3263 count = mir->MntRespCount;
984263bc
MD
3264 /*
3265 * Check the container against our list.
3266 * co->co_found was already set to 0 in a
3267 * previous run.
3268 */
3269 if ((mir->Status == ST_OK) &&
3270 (mir->MntTable[0].VolType != CT_NONE)) {
3271 found = 0;
3272 TAILQ_FOREACH(co,
d9773475 3273 &sc->aac_container_tqh,
984263bc
MD
3274 co_link) {
3275 if (co->co_mntobj.ObjectId ==
3276 mir->MntTable[0].ObjectId) {
3277 co->co_found = 1;
3278 found = 1;
3279 break;
3280 }
3281 }
3282 /*
3283 * If the container matched, continue
3284 * in the list.
3285 */
3286 if (found) {
3287 i++;
3288 continue;
3289 }
3290
3291 /*
3292 * This is a new container. Do all the
d9773475
PA
3293 * appropriate things to set it up.
3294 */
984263bc
MD
3295 aac_add_container(sc, mir, 1);
3296 added = 1;
3297 }
3298 i++;
158dbeb8 3299 } while ((i < count) && (i < AAC_MAX_CONTAINERS));
984263bc
MD
3300 aac_release_sync_fib(sc);
3301
3302 /*
3303 * Go through our list of containers and see which ones
3304 * were not marked 'found'. Since the controller didn't
3305 * list them they must have been deleted. Do the
3306 * appropriate steps to destroy the device. Also reset
3307 * the co->co_found field.
3308 */
3309 co = TAILQ_FIRST(&sc->aac_container_tqh);
3310 while (co != NULL) {
3311 if (co->co_found == 0) {
e9ae7f4f 3312 lockmgr(&sc->aac_io_lock, LK_RELEASE);
d9773475 3313 get_mplock();
984263bc
MD
3314 device_delete_child(sc->aac_dev,
3315 co->co_disk);
d9773475 3316 rel_mplock();
e9ae7f4f 3317 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
984263bc 3318 co_next = TAILQ_NEXT(co, co_link);
e9ae7f4f 3319 lockmgr(&sc->aac_container_lock, LK_EXCLUSIVE);
984263bc
MD
3320 TAILQ_REMOVE(&sc->aac_container_tqh, co,
3321 co_link);
e9ae7f4f 3322 lockmgr(&sc->aac_container_lock, LK_RELEASE);
d9773475 3323 kfree(co, M_AACBUF);
984263bc
MD
3324 co = co_next;
3325 } else {
3326 co->co_found = 0;
3327 co = TAILQ_NEXT(co, co_link);
3328 }
3329 }
3330
3331 /* Attach the newly created containers */
d9773475 3332 if (added) {
e9ae7f4f 3333 lockmgr(&sc->aac_io_lock, LK_RELEASE);
d9773475 3334 get_mplock();
984263bc 3335 bus_generic_attach(sc->aac_dev);
d9773475 3336 rel_mplock();
e9ae7f4f
SW
3337 lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE);
3338 }
3339
3340 break;
3341
3342 case AifEnEnclosureManagement:
3343 switch (aif->data.EN.data.EEE.eventType) {
3344 case AIF_EM_DRIVE_INSERTION:
3345 case AIF_EM_DRIVE_REMOVAL:
3346 channel = aif->data.EN.data.EEE.unitID;
3347 if (sc->cam_rescan_cb != NULL)
3348 sc->cam_rescan_cb(sc,
3349 (channel >> 24) & 0xF,
3350 (channel & 0xFFFF));
3351 break;
d9773475 3352 }
e9ae7f4f 3353 break;
d9773475 3354
e9ae7f4f
SW
3355 case AifEnAddJBOD:
3356 case AifEnDeleteJBOD:
3357 channel = aif->data.EN.data.ECE.container;
3358 if (sc->cam_rescan_cb != NULL)
3359 sc->cam_rescan_cb(sc, (channel >> 24) & 0xF,
3360 AAC_CAM_TARGET_WILDCARD);
d9773475 3361 break;
984263bc
MD
3362
3363 default:
3364 break;
3365 }
3366
3367 default:
3368 break;
3369 }
3370
3371 /* Copy the AIF data to the AIF queue for ioctl retrieval */
e9ae7f4f
SW
3372 lockmgr(&sc->aac_aifq_lock, LK_EXCLUSIVE);
3373 current = sc->aifq_idx;
3374 next = (current + 1) % AAC_AIFQ_LENGTH;
3375 if (next == 0)
3376 sc->aifq_filled = 1;
3377 bcopy(fib, &sc->aac_aifq[current], sizeof(struct aac_fib));
3378 /* modify AIF contexts */
3379 if (sc->aifq_filled) {
3380 for (ctx = sc->fibctx; ctx; ctx = ctx->next) {
3381 if (next == ctx->ctx_idx)
3382 ctx->ctx_wrap = 1;
3383 else if (current == ctx->ctx_idx && ctx->ctx_wrap)
3384 ctx->ctx_idx = next;
3385 }
3386 }
3387 sc->aifq_idx = next;
3388 /* On the off chance that someone is sleeping for an aif... */
3389 if (sc->aac_state & AAC_STATE_AIF_SLEEPER)
3390 wakeup(sc->aac_aifq);
3391 /* token may have been lost */
3392 /* Wakeup any poll()ers */
3393 KNOTE(&sc->rcv_kq.ki_note, 0);
3394 /* token may have been lost */
3395 lockmgr(&sc->aac_aifq_lock, LK_RELEASE);
984263bc
MD
3396}
3397
3398/*
3399 * Return the Revision of the driver to userspace and check to see if the
3400 * userspace app is possibly compatible. This is extremely bogus since
3401 * our driver doesn't follow Adaptec's versioning system. Cheat by just
3402 * returning what the card reported.
3403 */
3404static int
3405aac_rev_check(struct aac_softc *sc, caddr_t udata)
3406{
3407 struct aac_rev_check rev_check;
3408 struct aac_rev_check_resp rev_check_resp;
3409 int error = 0;
3410
e9ae7f4f 3411 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
984263bc
MD
3412
3413 /*
3414 * Copyin the revision struct from userspace
3415 */
3416 if ((error = copyin(udata, (caddr_t)&rev_check,
3417 sizeof(struct aac_rev_check))) != 0) {
3418 return error;
3419 }
3420
e9ae7f4f 3421 fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "Userland revision= %d\n",
984263bc
MD
3422 rev_check.callingRevision.buildNumber);
3423
3424 /*
3425 * Doctor up the response struct.
3426 */
3427 rev_check_resp.possiblyCompatible = 1;
e9ae7f4f
SW
3428 rev_check_resp.adapterSWRevision.external.comp.major =
3429 AAC_DRIVER_MAJOR_VERSION;
3430 rev_check_resp.adapterSWRevision.external.comp.minor =
3431 AAC_DRIVER_MINOR_VERSION;
3432 rev_check_resp.adapterSWRevision.external.comp.type =
3433 AAC_DRIVER_TYPE;
3434 rev_check_resp.adapterSWRevision.external.comp.dash =
3435 AAC_DRIVER_BUGFIX_LEVEL;
984263bc 3436 rev_check_resp.adapterSWRevision.buildNumber =
e9ae7f4f 3437 AAC_DRIVER_BUILD;
984263bc
MD
3438
3439 return(copyout((caddr_t)&rev_check_resp, udata,
3440 sizeof(struct aac_rev_check_resp)));
3441}
3442
e9ae7f4f
SW
3443/*
3444 * Pass the fib context to the caller
3445 */
3446static int
3447aac_open_aif(struct aac_softc *sc, caddr_t arg)
3448{
3449 struct aac_fib_context *fibctx, *ctx;
3450 int error = 0;
3451
3452 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
3453
3454 fibctx = kmalloc(sizeof(struct aac_fib_context), M_AACBUF, M_NOWAIT|M_ZERO);
3455 if (fibctx == NULL)
3456 return (ENOMEM);
3457
3458 lockmgr(&sc->aac_aifq_lock, LK_EXCLUSIVE);
3459 /* all elements are already 0, add to queue */
3460 if (sc->fibctx == NULL)
3461 sc->fibctx = fibctx;
3462 else {
3463 for (ctx = sc->fibctx; ctx->next; ctx = ctx->next)
3464 ;
3465 ctx->next = fibctx;
3466 fibctx->prev = ctx;
3467 }
3468
3469 /* evaluate unique value */
3470 fibctx->unique = (*(u_int32_t *)&fibctx & 0xffffffff);
3471 ctx = sc->fibctx;
3472 while (ctx != fibctx) {
3473 if (ctx->unique == fibctx->unique) {
3474 fibctx->unique++;
3475 ctx = sc->fibctx;
3476 } else {
3477 ctx = ctx->next;
3478 }
3479 }
3480 lockmgr(&sc->aac_aifq_lock, LK_RELEASE);
3481
3482 error = copyout(&fibctx->unique, (void *)arg, sizeof(u_int32_t));
3483 if (error)
3484 aac_close_aif(sc, (caddr_t)ctx);
3485 return error;
3486}
3487
3488/*
3489 * Close the caller's fib context
3490 */
3491static int
3492aac_close_aif(struct aac_softc *sc, caddr_t arg)
3493{
3494 struct aac_fib_context *ctx;
3495
3496 fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
3497