aac.c revision 177462
1169689Skan/*-
2169689Skan * Copyright (c) 2000 Michael Smith
3169689Skan * Copyright (c) 2001 Scott Long
4169689Skan * Copyright (c) 2000 BSDi
5169689Skan * Copyright (c) 2001 Adaptec, Inc.
6169689Skan * All rights reserved.
7169689Skan *
8169689Skan * Redistribution and use in source and binary forms, with or without
9169689Skan * modification, are permitted provided that the following conditions
10169689Skan * are met:
11169689Skan * 1. Redistributions of source code must retain the above copyright
12169689Skan *    notice, this list of conditions and the following disclaimer.
13169689Skan * 2. Redistributions in binary form must reproduce the above copyright
14169689Skan *    notice, this list of conditions and the following disclaimer in the
15169689Skan *    documentation and/or other materials provided with the distribution.
16169689Skan *
17169689Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20169689Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27169689Skan * SUCH DAMAGE.
28169689Skan */
29169689Skan
30169689Skan#include <sys/cdefs.h>
31169689Skan__FBSDID("$FreeBSD: head/sys/dev/aac/aac.c 177462 2008-03-20 17:59:19Z emaste $");
32169689Skan
33169689Skan/*
34169689Skan * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
35169689Skan */
36169689Skan#define AAC_DRIVER_VERSION		0x02000000
37169689Skan#define AAC_DRIVERNAME			"aac"
38169689Skan
39169689Skan#include "opt_aac.h"
40169689Skan
41169689Skan/* #include <stddef.h> */
42169689Skan#include <sys/param.h>
43169689Skan#include <sys/systm.h>
44169689Skan#include <sys/malloc.h>
45169689Skan#include <sys/kernel.h>
46169689Skan#include <sys/kthread.h>
47169689Skan#include <sys/sysctl.h>
48169689Skan#include <sys/poll.h>
49169689Skan#include <sys/ioccom.h>
50169689Skan
51169689Skan#include <sys/bus.h>
52169689Skan#include <sys/conf.h>
53169689Skan#include <sys/signalvar.h>
54169689Skan#include <sys/time.h>
55169689Skan#include <sys/eventhandler.h>
56169689Skan#include <sys/rman.h>
57169689Skan
58169689Skan#include <machine/bus.h>
59169689Skan#include <sys/bus_dma.h>
60169689Skan#include <machine/resource.h>
61169689Skan
62169689Skan#include <dev/pci/pcireg.h>
63169689Skan#include <dev/pci/pcivar.h>
64169689Skan
65169689Skan#include <dev/aac/aacreg.h>
66169689Skan#include <sys/aac_ioctl.h>
67169689Skan#include <dev/aac/aacvar.h>
68169689Skan#include <dev/aac/aac_tables.h>
69169689Skan
70169689Skanstatic void	aac_startup(void *arg);
71169689Skanstatic void	aac_add_container(struct aac_softc *sc,
72169689Skan				  struct aac_mntinforesp *mir, int f);
73169689Skanstatic void	aac_get_bus_info(struct aac_softc *sc);
74169689Skan
75169689Skan/* Command Processing */
76169689Skanstatic void	aac_timeout(struct aac_softc *sc);
77169689Skanstatic void	aac_complete(void *context, int pending);
78169689Skanstatic int	aac_bio_command(struct aac_softc *sc, struct aac_command **cmp);
79169689Skanstatic void	aac_bio_complete(struct aac_command *cm);
80169689Skanstatic int	aac_wait_command(struct aac_command *cm);
81169689Skanstatic void	aac_command_thread(struct aac_softc *sc);
82169689Skan
83169689Skan/* Command Buffer Management */
84169689Skanstatic void	aac_map_command_sg(void *arg, bus_dma_segment_t *segs,
85169689Skan				   int nseg, int error);
86169689Skanstatic void	aac_map_command_helper(void *arg, bus_dma_segment_t *segs,
87169689Skan				       int nseg, int error);
88169689Skanstatic int	aac_alloc_commands(struct aac_softc *sc);
89169689Skanstatic void	aac_free_commands(struct aac_softc *sc);
90169689Skanstatic void	aac_unmap_command(struct aac_command *cm);
91169689Skan
92169689Skan/* Hardware Interface */
93169689Skanstatic void	aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg,
94169689Skan			       int error);
95169689Skanstatic int	aac_check_firmware(struct aac_softc *sc);
96169689Skanstatic int	aac_init(struct aac_softc *sc);
97169689Skanstatic int	aac_sync_command(struct aac_softc *sc, u_int32_t command,
98169689Skan				 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
99169689Skan				 u_int32_t arg3, u_int32_t *sp);
100169689Skanstatic int	aac_enqueue_fib(struct aac_softc *sc, int queue,
101169689Skan				struct aac_command *cm);
102169689Skanstatic int	aac_dequeue_fib(struct aac_softc *sc, int queue,
103169689Skan				u_int32_t *fib_size, struct aac_fib **fib_addr);
104169689Skanstatic int	aac_enqueue_response(struct aac_softc *sc, int queue,
105169689Skan				     struct aac_fib *fib);
106169689Skan
107169689Skan/* Falcon/PPC interface */
108169689Skanstatic int	aac_fa_get_fwstatus(struct aac_softc *sc);
109169689Skanstatic void	aac_fa_qnotify(struct aac_softc *sc, int qbit);
110169689Skanstatic int	aac_fa_get_istatus(struct aac_softc *sc);
111169689Skanstatic void	aac_fa_clear_istatus(struct aac_softc *sc, int mask);
112169689Skanstatic void	aac_fa_set_mailbox(struct aac_softc *sc, u_int32_t command,
113169689Skan				   u_int32_t arg0, u_int32_t arg1,
114169689Skan				   u_int32_t arg2, u_int32_t arg3);
115169689Skanstatic int	aac_fa_get_mailbox(struct aac_softc *sc, int mb);
116169689Skanstatic void	aac_fa_set_interrupts(struct aac_softc *sc, int enable);
117169689Skan
118169689Skanstruct aac_interface aac_fa_interface = {
119169689Skan	aac_fa_get_fwstatus,
120169689Skan	aac_fa_qnotify,
121169689Skan	aac_fa_get_istatus,
122169689Skan	aac_fa_clear_istatus,
123169689Skan	aac_fa_set_mailbox,
124169689Skan	aac_fa_get_mailbox,
125169689Skan	aac_fa_set_interrupts,
126169689Skan	NULL, NULL, NULL
127169689Skan};
128169689Skan
129169689Skan/* StrongARM interface */
130169689Skanstatic int	aac_sa_get_fwstatus(struct aac_softc *sc);
131169689Skanstatic void	aac_sa_qnotify(struct aac_softc *sc, int qbit);
132169689Skanstatic int	aac_sa_get_istatus(struct aac_softc *sc);
133169689Skanstatic void	aac_sa_clear_istatus(struct aac_softc *sc, int mask);
134169689Skanstatic void	aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
135169689Skan				   u_int32_t arg0, u_int32_t arg1,
136169689Skan				   u_int32_t arg2, u_int32_t arg3);
137169689Skanstatic int	aac_sa_get_mailbox(struct aac_softc *sc, int mb);
138169689Skanstatic void	aac_sa_set_interrupts(struct aac_softc *sc, int enable);
139169689Skan
140169689Skanstruct aac_interface aac_sa_interface = {
141169689Skan	aac_sa_get_fwstatus,
142169689Skan	aac_sa_qnotify,
143169689Skan	aac_sa_get_istatus,
144169689Skan	aac_sa_clear_istatus,
145169689Skan	aac_sa_set_mailbox,
146169689Skan	aac_sa_get_mailbox,
147169689Skan	aac_sa_set_interrupts,
148169689Skan	NULL, NULL, NULL
149169689Skan};
150169689Skan
151169689Skan/* i960Rx interface */
152169689Skanstatic int	aac_rx_get_fwstatus(struct aac_softc *sc);
153169689Skanstatic void	aac_rx_qnotify(struct aac_softc *sc, int qbit);
154169689Skanstatic int	aac_rx_get_istatus(struct aac_softc *sc);
155169689Skanstatic void	aac_rx_clear_istatus(struct aac_softc *sc, int mask);
156169689Skanstatic void	aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command,
157169689Skan				   u_int32_t arg0, u_int32_t arg1,
158169689Skan				   u_int32_t arg2, u_int32_t arg3);
159169689Skanstatic int	aac_rx_get_mailbox(struct aac_softc *sc, int mb);
160169689Skanstatic void	aac_rx_set_interrupts(struct aac_softc *sc, int enable);
161169689Skanstatic int aac_rx_send_command(struct aac_softc *sc, struct aac_command *cm);
162169689Skanstatic int aac_rx_get_outb_queue(struct aac_softc *sc);
163169689Skanstatic void aac_rx_set_outb_queue(struct aac_softc *sc, int index);
164169689Skan
165169689Skanstruct aac_interface aac_rx_interface = {
166169689Skan	aac_rx_get_fwstatus,
167169689Skan	aac_rx_qnotify,
168169689Skan	aac_rx_get_istatus,
169169689Skan	aac_rx_clear_istatus,
170169689Skan	aac_rx_set_mailbox,
171169689Skan	aac_rx_get_mailbox,
172169689Skan	aac_rx_set_interrupts,
173169689Skan	aac_rx_send_command,
174169689Skan	aac_rx_get_outb_queue,
175169689Skan	aac_rx_set_outb_queue
176169689Skan};
177169689Skan
178169689Skan/* Rocket/MIPS interface */
179169689Skanstatic int	aac_rkt_get_fwstatus(struct aac_softc *sc);
180169689Skanstatic void	aac_rkt_qnotify(struct aac_softc *sc, int qbit);
181169689Skanstatic int	aac_rkt_get_istatus(struct aac_softc *sc);
182169689Skanstatic void	aac_rkt_clear_istatus(struct aac_softc *sc, int mask);
183169689Skanstatic void	aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command,
184169689Skan				    u_int32_t arg0, u_int32_t arg1,
185169689Skan				    u_int32_t arg2, u_int32_t arg3);
186169689Skanstatic int	aac_rkt_get_mailbox(struct aac_softc *sc, int mb);
187169689Skanstatic void	aac_rkt_set_interrupts(struct aac_softc *sc, int enable);
188169689Skanstatic int aac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm);
189169689Skanstatic int aac_rkt_get_outb_queue(struct aac_softc *sc);
190169689Skanstatic void aac_rkt_set_outb_queue(struct aac_softc *sc, int index);
191169689Skan
192169689Skanstruct aac_interface aac_rkt_interface = {
193169689Skan	aac_rkt_get_fwstatus,
194169689Skan	aac_rkt_qnotify,
195169689Skan	aac_rkt_get_istatus,
196169689Skan	aac_rkt_clear_istatus,
197169689Skan	aac_rkt_set_mailbox,
198169689Skan	aac_rkt_get_mailbox,
199169689Skan	aac_rkt_set_interrupts,
200169689Skan	aac_rkt_send_command,
201169689Skan	aac_rkt_get_outb_queue,
202169689Skan	aac_rkt_set_outb_queue
203169689Skan};
204169689Skan
205169689Skan/* Debugging and Diagnostics */
206169689Skanstatic void	aac_describe_controller(struct aac_softc *sc);
207169689Skanstatic char	*aac_describe_code(struct aac_code_lookup *table,
208169689Skan				   u_int32_t code);
209169689Skan
210169689Skan/* Management Interface */
211169689Skanstatic d_open_t		aac_open;
212169689Skanstatic d_close_t	aac_close;
213169689Skanstatic d_ioctl_t	aac_ioctl;
214169689Skanstatic d_poll_t		aac_poll;
215169689Skanstatic int		aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib);
216169689Skanstatic int		aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg);
217169689Skanstatic void		aac_handle_aif(struct aac_softc *sc,
218169689Skan					   struct aac_fib *fib);
219169689Skanstatic int		aac_rev_check(struct aac_softc *sc, caddr_t udata);
220169689Skanstatic int		aac_open_aif(struct aac_softc *sc, caddr_t arg);
221169689Skanstatic int		aac_close_aif(struct aac_softc *sc, caddr_t arg);
222169689Skanstatic int		aac_getnext_aif(struct aac_softc *sc, caddr_t arg);
223169689Skanstatic int		aac_return_aif(struct aac_softc *sc,
224169689Skan					struct aac_fib_context *ctx, caddr_t uptr);
225169689Skanstatic int		aac_query_disk(struct aac_softc *sc, caddr_t uptr);
226169689Skanstatic int		aac_get_pci_info(struct aac_softc *sc, caddr_t uptr);
227169689Skanstatic void		aac_ioctl_event(struct aac_softc *sc,
228169689Skan				        struct aac_event *event, void *arg);
229169689Skan
230169689Skanstatic struct cdevsw aac_cdevsw = {
231169689Skan	.d_version =	D_VERSION,
232169689Skan	.d_flags =	D_NEEDGIANT,
233169689Skan	.d_open =	aac_open,
234169689Skan	.d_close =	aac_close,
235169689Skan	.d_ioctl =	aac_ioctl,
236169689Skan	.d_poll =	aac_poll,
237169689Skan	.d_name =	"aac",
238169689Skan};
239169689Skan
240169689SkanMALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for the AAC driver");
241169689Skan
242169689Skan/* sysctl node */
243169689SkanSYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters");
244169689Skan
245169689Skan/*
246169689Skan * Device Interface
247169689Skan */
248169689Skan
249169689Skan/*
250169689Skan * Initialize the controller and softc
251169689Skan */
252169689Skanint
253169689Skanaac_attach(struct aac_softc *sc)
254169689Skan{
255169689Skan	int error, unit;
256169689Skan
257169689Skan	debug_called(1);
258169689Skan
259169689Skan	/*
260169689Skan	 * Initialize per-controller queues.
261169689Skan	 */
262169689Skan	aac_initq_free(sc);
263169689Skan	aac_initq_ready(sc);
264169689Skan	aac_initq_busy(sc);
265169689Skan	aac_initq_bio(sc);
266169689Skan
267169689Skan	/*
268169689Skan	 * Initialize command-completion task.
269169689Skan	 */
270169689Skan	TASK_INIT(&sc->aac_task_complete, 0, aac_complete, sc);
271169689Skan
272169689Skan	/* mark controller as suspended until we get ourselves organised */
273169689Skan	sc->aac_state |= AAC_STATE_SUSPEND;
274169689Skan
275169689Skan	/*
276169689Skan	 * Check that the firmware on the card is supported.
277169689Skan	 */
278169689Skan	if ((error = aac_check_firmware(sc)) != 0)
279169689Skan		return(error);
280169689Skan
281169689Skan	/*
282169689Skan	 * Initialize locks
283169689Skan	 */
284169689Skan	mtx_init(&sc->aac_aifq_lock, "AAC AIF lock", NULL, MTX_DEF);
285169689Skan	mtx_init(&sc->aac_io_lock, "AAC I/O lock", NULL, MTX_DEF);
286169689Skan	mtx_init(&sc->aac_container_lock, "AAC container lock", NULL, MTX_DEF);
287169689Skan	TAILQ_INIT(&sc->aac_container_tqh);
288169689Skan	TAILQ_INIT(&sc->aac_ev_cmfree);
289169689Skan
290169689Skan	/*
291169689Skan	 * Initialize the adapter.
292169689Skan	 */
293169689Skan	if ((error = aac_init(sc)) != 0)
294169689Skan		return(error);
295169689Skan
296169689Skan	/*
297169689Skan	 * Allocate and connect our interrupt.
298169689Skan	 */
299169689Skan	sc->aac_irq_rid = 0;
300169689Skan	if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ,
301169689Skan			   			  &sc->aac_irq_rid,
302169689Skan			   			  RF_SHAREABLE |
303169689Skan						  RF_ACTIVE)) == NULL) {
304169689Skan		device_printf(sc->aac_dev, "can't allocate interrupt\n");
305169689Skan		return (EINVAL);
306169689Skan	}
307169689Skan	if (sc->flags & AAC_FLAGS_NEW_COMM) {
308169689Skan		if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
309169689Skan				   INTR_MPSAFE|INTR_TYPE_BIO, NULL,
310169689Skan				   aac_new_intr, sc, &sc->aac_intr)) {
311169689Skan			device_printf(sc->aac_dev, "can't set up interrupt\n");
312169689Skan			return (EINVAL);
313169689Skan		}
314169689Skan	} else {
315169689Skan		if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
316169689Skan				   INTR_TYPE_BIO, aac_fast_intr, NULL,
317169689Skan				   sc, &sc->aac_intr)) {
318169689Skan			device_printf(sc->aac_dev,
319169689Skan				      "can't set up FAST interrupt\n");
320169689Skan			if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
321169689Skan					   INTR_MPSAFE|INTR_TYPE_BIO,
322169689Skan					   NULL, (driver_intr_t *)aac_fast_intr,
323169689Skan					   sc, &sc->aac_intr)) {
324169689Skan				device_printf(sc->aac_dev,
325169689Skan					     "can't set up MPSAFE interrupt\n");
326169689Skan				return (EINVAL);
327169689Skan			}
328169689Skan		}
329169689Skan	}
330169689Skan
331169689Skan	/*
332169689Skan	 * Print a little information about the controller.
333169689Skan	 */
334169689Skan	aac_describe_controller(sc);
335169689Skan
336169689Skan	/*
337169689Skan	 * Register to probe our containers later.
338169689Skan	 */
339169689Skan	sc->aac_ich.ich_func = aac_startup;
340169689Skan	sc->aac_ich.ich_arg = sc;
341169689Skan	if (config_intrhook_establish(&sc->aac_ich) != 0) {
342169689Skan		device_printf(sc->aac_dev,
343169689Skan			      "can't establish configuration hook\n");
344169689Skan		return(ENXIO);
345169689Skan	}
346169689Skan
347169689Skan	/*
348169689Skan	 * Make the control device.
349169689Skan	 */
350169689Skan	unit = device_get_unit(sc->aac_dev);
351169689Skan	sc->aac_dev_t = make_dev(&aac_cdevsw, unit, UID_ROOT, GID_OPERATOR,
352169689Skan				 0640, "aac%d", unit);
353169689Skan	(void)make_dev_alias(sc->aac_dev_t, "afa%d", unit);
354169689Skan	(void)make_dev_alias(sc->aac_dev_t, "hpn%d", unit);
355169689Skan	sc->aac_dev_t->si_drv1 = sc;
356169689Skan
357169689Skan	/* Create the AIF thread */
358169689Skan	if (kproc_create((void(*)(void *))aac_command_thread, sc,
359169689Skan		   &sc->aifthread, 0, 0, "aac%daif", unit))
360169689Skan		panic("Could not create AIF thread\n");
361169689Skan
362169689Skan	/* Register the shutdown method to only be called post-dump */
363169689Skan	if ((sc->eh = EVENTHANDLER_REGISTER(shutdown_final, aac_shutdown,
364169689Skan	    sc->aac_dev, SHUTDOWN_PRI_DEFAULT)) == NULL)
365169689Skan		device_printf(sc->aac_dev,
366169689Skan			      "shutdown event registration failed\n");
367169689Skan
368169689Skan	/* Register with CAM for the non-DASD devices */
369169689Skan	if ((sc->flags & AAC_FLAGS_ENABLE_CAM) != 0) {
370169689Skan		TAILQ_INIT(&sc->aac_sim_tqh);
371169689Skan		aac_get_bus_info(sc);
372169689Skan	}
373169689Skan
374169689Skan	return(0);
375169689Skan}
376169689Skan
377169689Skanvoid
378169689Skanaac_add_event(struct aac_softc *sc, struct aac_event *event)
379169689Skan{
380169689Skan
381169689Skan	switch (event->ev_type & AAC_EVENT_MASK) {
382169689Skan	case AAC_EVENT_CMFREE:
383169689Skan		TAILQ_INSERT_TAIL(&sc->aac_ev_cmfree, event, ev_links);
384169689Skan		break;
385169689Skan	default:
386169689Skan		device_printf(sc->aac_dev, "aac_add event: unknown event %d\n",
387169689Skan		    event->ev_type);
388169689Skan		break;
389169689Skan	}
390169689Skan
391169689Skan	return;
392169689Skan}
393169689Skan
394169689Skan/*
395169689Skan * Probe for containers, create disks.
396169689Skan */
397169689Skanstatic void
398169689Skanaac_startup(void *arg)
399169689Skan{
400169689Skan	struct aac_softc *sc;
401169689Skan	struct aac_fib *fib;
402169689Skan	struct aac_mntinfo *mi;
403169689Skan	struct aac_mntinforesp *mir = NULL;
404169689Skan	int count = 0, i = 0;
405169689Skan
406169689Skan	debug_called(1);
407169689Skan
408169689Skan	sc = (struct aac_softc *)arg;
409169689Skan
410169689Skan	/* disconnect ourselves from the intrhook chain */
411169689Skan	config_intrhook_disestablish(&sc->aac_ich);
412169689Skan
413169689Skan	mtx_lock(&sc->aac_io_lock);
414169689Skan	aac_alloc_sync_fib(sc, &fib);
415169689Skan	mi = (struct aac_mntinfo *)&fib->data[0];
416169689Skan
417169689Skan	/* loop over possible containers */
418169689Skan	do {
419169689Skan		/* request information on this container */
420169689Skan		bzero(mi, sizeof(struct aac_mntinfo));
421169689Skan		mi->Command = VM_NameServe;
422169689Skan		mi->MntType = FT_FILESYS;
423169689Skan		mi->MntCount = i;
424169689Skan		if (aac_sync_fib(sc, ContainerCommand, 0, fib,
425169689Skan				 sizeof(struct aac_mntinfo))) {
426169689Skan			printf("error probing container %d", i);
427169689Skan			continue;
428169689Skan		}
429169689Skan
430169689Skan		mir = (struct aac_mntinforesp *)&fib->data[0];
431169689Skan		/* XXX Need to check if count changed */
432169689Skan		count = mir->MntRespCount;
433169689Skan		aac_add_container(sc, mir, 0);
434169689Skan		i++;
435169689Skan	} while ((i < count) && (i < AAC_MAX_CONTAINERS));
436169689Skan
437169689Skan	aac_release_sync_fib(sc);
438169689Skan	mtx_unlock(&sc->aac_io_lock);
439169689Skan
440169689Skan	/* poke the bus to actually attach the child devices */
441169689Skan	if (bus_generic_attach(sc->aac_dev))
442169689Skan		device_printf(sc->aac_dev, "bus_generic_attach failed\n");
443169689Skan
444169689Skan	/* mark the controller up */
445169689Skan	sc->aac_state &= ~AAC_STATE_SUSPEND;
446169689Skan
447169689Skan	/* enable interrupts now */
448169689Skan	AAC_UNMASK_INTERRUPTS(sc);
449169689Skan}
450169689Skan
451169689Skan/*
452169689Skan * Create a device to represent a new container
453169689Skan */
454169689Skanstatic void
455169689Skanaac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f)
456169689Skan{
457169689Skan	struct aac_container *co;
458169689Skan	device_t child;
459169689Skan
460169689Skan	/*
461169689Skan	 * Check container volume type for validity.  Note that many of
462169689Skan	 * the possible types may never show up.
463169689Skan	 */
464169689Skan	if ((mir->Status == ST_OK) && (mir->MntTable[0].VolType != CT_NONE)) {
465169689Skan		co = (struct aac_container *)malloc(sizeof *co, M_AACBUF,
466169689Skan		       M_NOWAIT | M_ZERO);
467169689Skan		if (co == NULL)
468169689Skan			panic("Out of memory?!\n");
469169689Skan		debug(1, "id %x  name '%.16s'  size %u  type %d",
470169689Skan		      mir->MntTable[0].ObjectId,
471169689Skan		      mir->MntTable[0].FileSystemName,
472169689Skan		      mir->MntTable[0].Capacity, mir->MntTable[0].VolType);
473169689Skan
474169689Skan		if ((child = device_add_child(sc->aac_dev, "aacd", -1)) == NULL)
475169689Skan			device_printf(sc->aac_dev, "device_add_child failed\n");
476169689Skan		else
477169689Skan			device_set_ivars(child, co);
478169689Skan		device_set_desc(child, aac_describe_code(aac_container_types,
479169689Skan				mir->MntTable[0].VolType));
480169689Skan		co->co_disk = child;
481169689Skan		co->co_found = f;
482169689Skan		bcopy(&mir->MntTable[0], &co->co_mntobj,
483169689Skan		      sizeof(struct aac_mntobj));
484169689Skan		mtx_lock(&sc->aac_container_lock);
485169689Skan		TAILQ_INSERT_TAIL(&sc->aac_container_tqh, co, co_link);
486169689Skan		mtx_unlock(&sc->aac_container_lock);
487169689Skan	}
488169689Skan}
489169689Skan
490169689Skan/*
491169689Skan * Free all of the resources associated with (sc)
492169689Skan *
493169689Skan * Should not be called if the controller is active.
494169689Skan */
495169689Skanvoid
496169689Skanaac_free(struct aac_softc *sc)
497169689Skan{
498169689Skan
499169689Skan	debug_called(1);
500169689Skan
501169689Skan	/* remove the control device */
502169689Skan	if (sc->aac_dev_t != NULL)
503169689Skan		destroy_dev(sc->aac_dev_t);
504169689Skan
505169689Skan	/* throw away any FIB buffers, discard the FIB DMA tag */
506169689Skan	aac_free_commands(sc);
507169689Skan	if (sc->aac_fib_dmat)
508169689Skan		bus_dma_tag_destroy(sc->aac_fib_dmat);
509169689Skan
510169689Skan	free(sc->aac_commands, M_AACBUF);
511169689Skan
512169689Skan	/* destroy the common area */
513169689Skan	if (sc->aac_common) {
514169689Skan		bus_dmamap_unload(sc->aac_common_dmat, sc->aac_common_dmamap);
515169689Skan		bus_dmamem_free(sc->aac_common_dmat, sc->aac_common,
516169689Skan				sc->aac_common_dmamap);
517169689Skan	}
518169689Skan	if (sc->aac_common_dmat)
519169689Skan		bus_dma_tag_destroy(sc->aac_common_dmat);
520169689Skan
521169689Skan	/* disconnect the interrupt handler */
522169689Skan	if (sc->aac_intr)
523169689Skan		bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr);
524169689Skan	if (sc->aac_irq != NULL)
525169689Skan		bus_release_resource(sc->aac_dev, SYS_RES_IRQ, sc->aac_irq_rid,
526169689Skan				     sc->aac_irq);
527169689Skan
528169689Skan	/* destroy data-transfer DMA tag */
529169689Skan	if (sc->aac_buffer_dmat)
530169689Skan		bus_dma_tag_destroy(sc->aac_buffer_dmat);
531169689Skan
532169689Skan	/* destroy the parent DMA tag */
533169689Skan	if (sc->aac_parent_dmat)
534169689Skan		bus_dma_tag_destroy(sc->aac_parent_dmat);
535169689Skan
536169689Skan	/* release the register window mapping */
537169689Skan	if (sc->aac_regs_resource != NULL)
538169689Skan		bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
539169689Skan				     sc->aac_regs_rid, sc->aac_regs_resource);
540169689Skan}
541169689Skan
542169689Skan/*
543169689Skan * Disconnect from the controller completely, in preparation for unload.
544169689Skan */
545169689Skanint
546169689Skanaac_detach(device_t dev)
547169689Skan{
548169689Skan	struct aac_softc *sc;
549169689Skan	struct aac_container *co;
550169689Skan	struct aac_sim	*sim;
551169689Skan	int error;
552169689Skan
553169689Skan	debug_called(1);
554169689Skan
555169689Skan	sc = device_get_softc(dev);
556169689Skan
557169689Skan	if (sc->aac_state & AAC_STATE_OPEN)
558169689Skan		return(EBUSY);
559169689Skan
560169689Skan	/* Remove the child containers */
561169689Skan	while ((co = TAILQ_FIRST(&sc->aac_container_tqh)) != NULL) {
562169689Skan		error = device_delete_child(dev, co->co_disk);
563169689Skan		if (error)
564169689Skan			return (error);
565169689Skan		TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link);
566169689Skan		free(co, M_AACBUF);
567169689Skan	}
568169689Skan
569169689Skan	/* Remove the CAM SIMs */
570169689Skan	while ((sim = TAILQ_FIRST(&sc->aac_sim_tqh)) != NULL) {
571169689Skan		TAILQ_REMOVE(&sc->aac_sim_tqh, sim, sim_link);
572169689Skan		error = device_delete_child(dev, sim->sim_dev);
573169689Skan		if (error)
574169689Skan			return (error);
575169689Skan		free(sim, M_AACBUF);
576169689Skan	}
577169689Skan
578169689Skan	if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
579169689Skan		sc->aifflags |= AAC_AIFFLAGS_EXIT;
580169689Skan		wakeup(sc->aifthread);
581169689Skan		tsleep(sc->aac_dev, PUSER | PCATCH, "aacdch", 30 * hz);
582169689Skan	}
583169689Skan
584169689Skan	if (sc->aifflags & AAC_AIFFLAGS_RUNNING)
585169689Skan		panic("Cannot shutdown AIF thread\n");
586169689Skan
587169689Skan	if ((error = aac_shutdown(dev)))
588169689Skan		return(error);
589169689Skan
590169689Skan	EVENTHANDLER_DEREGISTER(shutdown_final, sc->eh);
591169689Skan
592169689Skan	aac_free(sc);
593169689Skan
594169689Skan	mtx_destroy(&sc->aac_aifq_lock);
595169689Skan	mtx_destroy(&sc->aac_io_lock);
596169689Skan	mtx_destroy(&sc->aac_container_lock);
597169689Skan
598169689Skan	return(0);
599169689Skan}
600169689Skan
601169689Skan/*
602169689Skan * Bring the controller down to a dormant state and detach all child devices.
603169689Skan *
604169689Skan * This function is called before detach or system shutdown.
605169689Skan *
606169689Skan * Note that we can assume that the bioq on the controller is empty, as we won't
607169689Skan * allow shutdown if any device is open.
608169689Skan */
609169689Skanint
610169689Skanaac_shutdown(device_t dev)
611169689Skan{
612169689Skan	struct aac_softc *sc;
613169689Skan	struct aac_fib *fib;
614169689Skan	struct aac_close_command *cc;
615169689Skan
616169689Skan	debug_called(1);
617169689Skan
618169689Skan	sc = device_get_softc(dev);
619169689Skan
620169689Skan	sc->aac_state |= AAC_STATE_SUSPEND;
621169689Skan
622169689Skan	/*
623169689Skan	 * Send a Container shutdown followed by a HostShutdown FIB to the
624169689Skan	 * controller to convince it that we don't want to talk to it anymore.
625169689Skan	 * We've been closed and all I/O completed already
626169689Skan	 */
627169689Skan	device_printf(sc->aac_dev, "shutting down controller...");
628169689Skan
629169689Skan	mtx_lock(&sc->aac_io_lock);
630169689Skan	aac_alloc_sync_fib(sc, &fib);
631169689Skan	cc = (struct aac_close_command *)&fib->data[0];
632169689Skan
633169689Skan	bzero(cc, sizeof(struct aac_close_command));
634169689Skan	cc->Command = VM_CloseAll;
635169689Skan	cc->ContainerId = 0xffffffff;
636169689Skan	if (aac_sync_fib(sc, ContainerCommand, 0, fib,
637169689Skan	    sizeof(struct aac_close_command)))
638169689Skan		printf("FAILED.\n");
639169689Skan	else
640169689Skan		printf("done\n");
641169689Skan#if 0
642169689Skan	else {
643169689Skan		fib->data[0] = 0;
644169689Skan		/*
645169689Skan		 * XXX Issuing this command to the controller makes it shut down
646169689Skan		 * but also keeps it from coming back up without a reset of the
647169689Skan		 * PCI bus.  This is not desirable if you are just unloading the
648169689Skan		 * driver module with the intent to reload it later.
649169689Skan		 */
650169689Skan		if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
651169689Skan		    fib, 1)) {
652169689Skan			printf("FAILED.\n");
653169689Skan		} else {
654169689Skan			printf("done.\n");
655169689Skan		}
656169689Skan	}
657169689Skan#endif
658169689Skan
659169689Skan	AAC_MASK_INTERRUPTS(sc);
660169689Skan	aac_release_sync_fib(sc);
661169689Skan	mtx_unlock(&sc->aac_io_lock);
662169689Skan
663169689Skan	return(0);
664169689Skan}
665169689Skan
666169689Skan/*
667169689Skan * Bring the controller to a quiescent state, ready for system suspend.
668169689Skan */
669169689Skanint
670169689Skanaac_suspend(device_t dev)
671169689Skan{
672169689Skan	struct aac_softc *sc;
673169689Skan
674169689Skan	debug_called(1);
675169689Skan
676169689Skan	sc = device_get_softc(dev);
677169689Skan
678169689Skan	sc->aac_state |= AAC_STATE_SUSPEND;
679169689Skan
680169689Skan	AAC_MASK_INTERRUPTS(sc);
681169689Skan	return(0);
682169689Skan}
683169689Skan
684169689Skan/*
685169689Skan * Bring the controller back to a state ready for operation.
686169689Skan */
687169689Skanint
688169689Skanaac_resume(device_t dev)
689169689Skan{
690169689Skan	struct aac_softc *sc;
691169689Skan
692169689Skan	debug_called(1);
693169689Skan
694169689Skan	sc = device_get_softc(dev);
695169689Skan
696169689Skan	sc->aac_state &= ~AAC_STATE_SUSPEND;
697169689Skan	AAC_UNMASK_INTERRUPTS(sc);
698169689Skan	return(0);
699169689Skan}
700169689Skan
701169689Skan/*
702169689Skan * Interrupt handler for NEW_COMM interface.
703169689Skan */
704169689Skanvoid
705169689Skanaac_new_intr(void *arg)
706169689Skan{
707169689Skan	struct aac_softc *sc;
708169689Skan	u_int32_t index, fast;
709169689Skan	struct aac_command *cm;
710169689Skan	struct aac_fib *fib;
711169689Skan	int i;
712169689Skan
713169689Skan	debug_called(2);
714169689Skan
715169689Skan	sc = (struct aac_softc *)arg;
716208737Sjmallett
717169689Skan	mtx_lock(&sc->aac_io_lock);
718169689Skan	while (1) {
719169689Skan		index = AAC_GET_OUTB_QUEUE(sc);
720169689Skan		if (index == 0xffffffff)
721169689Skan			index = AAC_GET_OUTB_QUEUE(sc);
722169689Skan		if (index == 0xffffffff)
723169689Skan			break;
724169689Skan		if (index & 2) {
725169689Skan			if (index == 0xfffffffe) {
726169689Skan				/* XXX This means that the controller wants
727169689Skan				 * more work.  Ignore it for now.
728169689Skan				 */
729169689Skan				continue;
730169689Skan			}
731169689Skan			/* AIF */
732169689Skan			fib = (struct aac_fib *)malloc(sizeof *fib, M_AACBUF,
733169689Skan				   M_NOWAIT | M_ZERO);
734169689Skan			if (fib == NULL) {
735169689Skan				/* If we're really this short on memory,
736169689Skan				 * hopefully breaking out of the handler will
737169689Skan				 * allow something to get freed.  This
738169689Skan				 * actually sucks a whole lot.
739169689Skan				 */
740169689Skan				break;
741169689Skan			}
742169689Skan			index &= ~2;
743169689Skan			for (i = 0; i < sizeof(struct aac_fib)/4; ++i)
744169689Skan				((u_int32_t *)fib)[i] = AAC_GETREG4(sc, index + i*4);
745169689Skan			aac_handle_aif(sc, fib);
746169689Skan			free(fib, M_AACBUF);
747169689Skan
748169689Skan			/*
749169689Skan			 * AIF memory is owned by the adapter, so let it
750169689Skan			 * know that we are done with it.
751169689Skan			 */
752169689Skan			AAC_SET_OUTB_QUEUE(sc, index);
753169689Skan			AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
754169689Skan		} else {
755169689Skan			fast = index & 1;
756169689Skan			cm = sc->aac_commands + (index >> 2);
757169689Skan			fib = cm->cm_fib;
758169689Skan			if (fast) {
759169689Skan				fib->Header.XferState |= AAC_FIBSTATE_DONEADAP;
760169689Skan				*((u_int32_t *)(fib->data)) = AAC_ERROR_NORMAL;
761169689Skan			}
762169689Skan			aac_remove_busy(cm);
763169689Skan 			aac_unmap_command(cm);
764169689Skan			cm->cm_flags |= AAC_CMD_COMPLETED;
765169689Skan
766208737Sjmallett			/* is there a completion handler? */
767208737Sjmallett			if (cm->cm_complete != NULL) {
768208737Sjmallett				cm->cm_complete(cm);
769169689Skan			} else {
770169689Skan				/* assume that someone is sleeping on this
771169689Skan				 * command
772169689Skan				 */
773169689Skan				wakeup(cm);
774169689Skan			}
775169689Skan			sc->flags &= ~AAC_QUEUE_FRZN;
776169689Skan		}
777169689Skan	}
778169689Skan	/* see if we can start some more I/O */
779169689Skan	if ((sc->flags & AAC_QUEUE_FRZN) == 0)
780169689Skan		aac_startio(sc);
781169689Skan
782169689Skan	mtx_unlock(&sc->aac_io_lock);
783169689Skan}
784169689Skan
785169689Skanint
786169689Skanaac_fast_intr(void *arg)
787169689Skan{
788169689Skan	struct aac_softc *sc;
789169689Skan	u_int16_t reason;
790169689Skan
791169689Skan	debug_called(2);
792169689Skan
793169689Skan	sc = (struct aac_softc *)arg;
794169689Skan
795169689Skan	/*
796169689Skan	 * Read the status register directly.  This is faster than taking the
797169689Skan	 * driver lock and reading the queues directly.  It also saves having
798169689Skan	 * to turn parts of the driver lock into a spin mutex, which would be
799169689Skan	 * ugly.
800169689Skan	 */
801169689Skan	reason = AAC_GET_ISTATUS(sc);
802169689Skan	AAC_CLEAR_ISTATUS(sc, reason);
803169689Skan
804169689Skan	/* handle completion processing */
805169689Skan	if (reason & AAC_DB_RESPONSE_READY)
806169689Skan		taskqueue_enqueue_fast(taskqueue_fast, &sc->aac_task_complete);
807169689Skan
808169689Skan	/* controller wants to talk to us */
809169689Skan	if (reason & (AAC_DB_PRINTF | AAC_DB_COMMAND_READY)) {
810169689Skan		/*
811169689Skan		 * XXX Make sure that we don't get fooled by strange messages
812169689Skan		 * that start with a NULL.
813169689Skan		 */
814169689Skan		if ((reason & AAC_DB_PRINTF) &&
815169689Skan			(sc->aac_common->ac_printf[0] == 0))
816169689Skan			sc->aac_common->ac_printf[0] = 32;
817169689Skan
818169689Skan		/*
819169689Skan		 * This might miss doing the actual wakeup.  However, the
820169689Skan		 * msleep that this is waking up has a timeout, so it will
821169689Skan		 * wake up eventually.  AIFs and printfs are low enough
822169689Skan		 * priority that they can handle hanging out for a few seconds
823169689Skan		 * if needed.
824169689Skan		 */
825169689Skan		wakeup(sc->aifthread);
826169689Skan	}
827169689Skan	return (FILTER_HANDLED);
828169689Skan}
829169689Skan
830169689Skan/*
831169689Skan * Command Processing
832169689Skan */
833169689Skan
834169689Skan/*
835169689Skan * Start as much queued I/O as possible on the controller
836169689Skan */
837169689Skanvoid
838169689Skanaac_startio(struct aac_softc *sc)
839169689Skan{
840169689Skan	struct aac_command *cm;
841169689Skan	int error;
842169689Skan
843169689Skan	debug_called(2);
844169689Skan
845169689Skan	for (;;) {
846169689Skan		/*
847169689Skan		 * This flag might be set if the card is out of resources.
848169689Skan		 * Checking it here prevents an infinite loop of deferrals.
849169689Skan		 */
850169689Skan		if (sc->flags & AAC_QUEUE_FRZN)
851169689Skan			break;
852169689Skan
853169689Skan		/*
854169689Skan		 * Try to get a command that's been put off for lack of
855169689Skan		 * resources
856169689Skan		 */
857169689Skan		cm = aac_dequeue_ready(sc);
858169689Skan
859169689Skan		/*
860169689Skan		 * Try to build a command off the bio queue (ignore error
861169689Skan		 * return)
862169689Skan		 */
863169689Skan		if (cm == NULL)
864169689Skan			aac_bio_command(sc, &cm);
865169689Skan
866169689Skan		/* nothing to do? */
867169689Skan		if (cm == NULL)
868169689Skan			break;
869169689Skan
870169689Skan		/* don't map more than once */
871169689Skan		if (cm->cm_flags & AAC_CMD_MAPPED)
872169689Skan			panic("aac: command %p already mapped", cm);
873169689Skan
874169689Skan		/*
875169689Skan		 * Set up the command to go to the controller.  If there are no
876169689Skan		 * data buffers associated with the command then it can bypass
877169689Skan		 * busdma.
878169689Skan		 */
879169689Skan		if (cm->cm_datalen != 0) {
880169689Skan			error = bus_dmamap_load(sc->aac_buffer_dmat,
881169689Skan						cm->cm_datamap, cm->cm_data,
882169689Skan						cm->cm_datalen,
883169689Skan						aac_map_command_sg, cm, 0);
884169689Skan			if (error == EINPROGRESS) {
885169689Skan				debug(1, "freezing queue\n");
886169689Skan				sc->flags |= AAC_QUEUE_FRZN;
887169689Skan				error = 0;
888169689Skan			} else if (error != 0)
889169689Skan				panic("aac_startio: unexpected error %d from "
890169689Skan				      "busdma\n", error);
891169689Skan		} else
892169689Skan			aac_map_command_sg(cm, NULL, 0, 0);
893169689Skan	}
894169689Skan}
895169689Skan
896169689Skan/*
897169689Skan * Handle notification of one or more FIBs coming from the controller.
898169689Skan */
899169689Skanstatic void
900169689Skanaac_command_thread(struct aac_softc *sc)
901169689Skan{
902169689Skan	struct aac_fib *fib;
903169689Skan	u_int32_t fib_size;
904169689Skan	int size, retval;
905169689Skan
906169689Skan	debug_called(2);
907169689Skan
908169689Skan	mtx_lock(&sc->aac_io_lock);
909169689Skan	sc->aifflags = AAC_AIFFLAGS_RUNNING;
910169689Skan
911169689Skan	while ((sc->aifflags & AAC_AIFFLAGS_EXIT) == 0) {
912169689Skan
913169689Skan		retval = 0;
914169689Skan		if ((sc->aifflags & AAC_AIFFLAGS_PENDING) == 0)
915169689Skan			retval = msleep(sc->aifthread, &sc->aac_io_lock, PRIBIO,
916169689Skan					"aifthd", AAC_PERIODIC_INTERVAL * hz);
917169689Skan
918169689Skan		/*
919169689Skan		 * First see if any FIBs need to be allocated.  This needs
920169689Skan		 * to be called without the driver lock because contigmalloc
921169689Skan		 * will grab Giant, and would result in an LOR.
922169689Skan		 */
923169689Skan		if ((sc->aifflags & AAC_AIFFLAGS_ALLOCFIBS) != 0) {
924169689Skan			mtx_unlock(&sc->aac_io_lock);
925169689Skan			aac_alloc_commands(sc);
926169689Skan			mtx_lock(&sc->aac_io_lock);
927169689Skan			sc->aifflags &= ~AAC_AIFFLAGS_ALLOCFIBS;
928169689Skan			aac_startio(sc);
929169689Skan		}
930169689Skan
931169689Skan		/*
932169689Skan		 * While we're here, check to see if any commands are stuck.
933169689Skan		 * This is pretty low-priority, so it's ok if it doesn't
934169689Skan		 * always fire.
935169689Skan		 */
936169689Skan		if (retval == EWOULDBLOCK)
937169689Skan			aac_timeout(sc);
938169689Skan
939169689Skan		/* Check the hardware printf message buffer */
940169689Skan		if (sc->aac_common->ac_printf[0] != 0)
941169689Skan			aac_print_printf(sc);
942169689Skan
943169689Skan		/* Also check to see if the adapter has a command for us. */
944169689Skan		if (sc->flags & AAC_FLAGS_NEW_COMM)
945169689Skan			continue;
946169689Skan		for (;;) {
947169689Skan			if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE,
948169689Skan					   &fib_size, &fib))
949169689Skan				break;
950169689Skan
951169689Skan			AAC_PRINT_FIB(sc, fib);
952169689Skan
953169689Skan			switch (fib->Header.Command) {
954169689Skan			case AifRequest:
955169689Skan				aac_handle_aif(sc, fib);
956169689Skan				break;
957169689Skan			default:
958169689Skan				device_printf(sc->aac_dev, "unknown command "
959169689Skan					      "from controller\n");
960169689Skan				break;
961169689Skan			}
962169689Skan
963169689Skan			if ((fib->Header.XferState == 0) ||
964169689Skan			    (fib->Header.StructType != AAC_FIBTYPE_TFIB)) {
965169689Skan				break;
966169689Skan			}
967169689Skan
968169689Skan			/* Return the AIF to the controller. */
969169689Skan			if (fib->Header.XferState & AAC_FIBSTATE_FROMADAP) {
970169689Skan				fib->Header.XferState |= AAC_FIBSTATE_DONEHOST;
971169689Skan				*(AAC_FSAStatus*)fib->data = ST_OK;
972169689Skan
973169689Skan				/* XXX Compute the Size field? */
974169689Skan				size = fib->Header.Size;
975169689Skan				if (size > sizeof(struct aac_fib)) {
976169689Skan					size = sizeof(struct aac_fib);
977169689Skan					fib->Header.Size = size;
978169689Skan				}
979169689Skan				/*
980169689Skan				 * Since we did not generate this command, it
981169689Skan				 * cannot go through the normal
982169689Skan				 * enqueue->startio chain.
983169689Skan				 */
984169689Skan				aac_enqueue_response(sc,
985169689Skan						 AAC_ADAP_NORM_RESP_QUEUE,
986169689Skan						 fib);
987169689Skan			}
988169689Skan		}
989169689Skan	}
990169689Skan	sc->aifflags &= ~AAC_AIFFLAGS_RUNNING;
991169689Skan	mtx_unlock(&sc->aac_io_lock);
992169689Skan	wakeup(sc->aac_dev);
993169689Skan
994169689Skan	kproc_exit(0);
995169689Skan}
996169689Skan
997169689Skan/*
998169689Skan * Process completed commands.
999169689Skan */
1000169689Skanstatic void
1001169689Skanaac_complete(void *context, int pending)
1002169689Skan{
1003169689Skan	struct aac_softc *sc;
1004169689Skan	struct aac_command *cm;
1005169689Skan	struct aac_fib *fib;
1006169689Skan	u_int32_t fib_size;
1007169689Skan
1008169689Skan	debug_called(2);
1009169689Skan
1010169689Skan	sc = (struct aac_softc *)context;
1011169689Skan
1012169689Skan	mtx_lock(&sc->aac_io_lock);
1013169689Skan
1014169689Skan	/* pull completed commands off the queue */
1015169689Skan	for (;;) {
1016169689Skan		/* look for completed FIBs on our queue */
1017169689Skan		if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
1018169689Skan							&fib))
1019169689Skan			break;	/* nothing to do */
1020169689Skan
1021169689Skan		/* get the command, unmap and hand off for processing */
1022169689Skan		cm = sc->aac_commands + fib->Header.SenderData;
1023169689Skan		if (cm == NULL) {
1024169689Skan			AAC_PRINT_FIB(sc, fib);
1025169689Skan			break;
1026169689Skan		}
1027169689Skan		aac_remove_busy(cm);
1028169689Skan
1029169689Skan 		aac_unmap_command(cm);
1030169689Skan		cm->cm_flags |= AAC_CMD_COMPLETED;
1031169689Skan
1032169689Skan		/* is there a completion handler? */
1033169689Skan		if (cm->cm_complete != NULL) {
1034169689Skan			cm->cm_complete(cm);
1035169689Skan		} else {
1036169689Skan			/* assume that someone is sleeping on this command */
1037169689Skan			wakeup(cm);
1038169689Skan		}
1039169689Skan	}
1040169689Skan
1041169689Skan	/* see if we can start some more I/O */
1042169689Skan	sc->flags &= ~AAC_QUEUE_FRZN;
1043169689Skan	aac_startio(sc);
1044169689Skan
1045169689Skan	mtx_unlock(&sc->aac_io_lock);
1046169689Skan}
1047169689Skan
1048169689Skan/*
1049169689Skan * Handle a bio submitted from a disk device.
1050169689Skan */
1051169689Skanvoid
1052169689Skanaac_submit_bio(struct bio *bp)
1053169689Skan{
1054169689Skan	struct aac_disk *ad;
1055169689Skan	struct aac_softc *sc;
1056169689Skan
1057169689Skan	debug_called(2);
1058169689Skan
1059169689Skan	ad = (struct aac_disk *)bp->bio_disk->d_drv1;
1060169689Skan	sc = ad->ad_controller;
1061169689Skan
1062169689Skan	/* queue the BIO and try to get some work done */
1063169689Skan	aac_enqueue_bio(sc, bp);
1064169689Skan	aac_startio(sc);
1065169689Skan}
1066169689Skan
1067169689Skan/*
1068169689Skan * Get a bio and build a command to go with it.
1069169689Skan */
1070169689Skanstatic int
1071169689Skanaac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
1072169689Skan{
1073169689Skan	struct aac_command *cm;
1074169689Skan	struct aac_fib *fib;
1075169689Skan	struct aac_disk *ad;
1076169689Skan	struct bio *bp;
1077169689Skan
1078169689Skan	debug_called(2);
1079169689Skan
1080169689Skan	/* get the resources we will need */
1081169689Skan	cm = NULL;
1082169689Skan	bp = NULL;
1083169689Skan	if (aac_alloc_command(sc, &cm))	/* get a command */
1084169689Skan		goto fail;
1085169689Skan	if ((bp = aac_dequeue_bio(sc)) == NULL)
1086169689Skan		goto fail;
1087169689Skan
1088169689Skan	/* fill out the command */
1089169689Skan	cm->cm_data = (void *)bp->bio_data;
1090169689Skan	cm->cm_datalen = bp->bio_bcount;
1091169689Skan	cm->cm_complete = aac_bio_complete;
1092169689Skan	cm->cm_private = bp;
1093169689Skan	cm->cm_timestamp = time_uptime;
1094169689Skan	cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
1095169689Skan
1096169689Skan	/* build the FIB */
1097169689Skan	fib = cm->cm_fib;
1098169689Skan	fib->Header.Size = sizeof(struct aac_fib_header);
1099169689Skan	fib->Header.XferState =
1100169689Skan		AAC_FIBSTATE_HOSTOWNED   |
1101169689Skan		AAC_FIBSTATE_INITIALISED |
1102169689Skan		AAC_FIBSTATE_EMPTY	 |
1103169689Skan		AAC_FIBSTATE_FROMHOST	 |
1104169689Skan		AAC_FIBSTATE_REXPECTED   |
1105169689Skan		AAC_FIBSTATE_NORM	 |
1106169689Skan		AAC_FIBSTATE_ASYNC	 |
1107169689Skan		AAC_FIBSTATE_FAST_RESPONSE;
1108169689Skan
1109169689Skan	/* build the read/write request */
1110169689Skan	ad = (struct aac_disk *)bp->bio_disk->d_drv1;
1111169689Skan
1112169689Skan	if (sc->flags & AAC_FLAGS_RAW_IO) {
1113169689Skan		struct aac_raw_io *raw;
1114169689Skan		raw = (struct aac_raw_io *)&fib->data[0];
1115169689Skan		fib->Header.Command = RawIo;
1116169689Skan		raw->BlockNumber = (u_int64_t)bp->bio_pblkno;
1117169689Skan		raw->ByteCount = bp->bio_bcount;
1118169689Skan		raw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
1119169689Skan		raw->BpTotal = 0;
1120169689Skan		raw->BpComplete = 0;
1121169689Skan		fib->Header.Size += sizeof(struct aac_raw_io);
1122169689Skan		cm->cm_sgtable = (struct aac_sg_table *)&raw->SgMapRaw;
1123169689Skan		if (bp->bio_cmd == BIO_READ) {
1124169689Skan			raw->Flags = 1;
1125169689Skan			cm->cm_flags |= AAC_CMD_DATAIN;
1126169689Skan		} else {
1127169689Skan			raw->Flags = 0;
1128169689Skan			cm->cm_flags |= AAC_CMD_DATAOUT;
1129169689Skan		}
1130169689Skan	} else if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
1131169689Skan		fib->Header.Command = ContainerCommand;
1132169689Skan		if (bp->bio_cmd == BIO_READ) {
1133169689Skan			struct aac_blockread *br;
1134169689Skan			br = (struct aac_blockread *)&fib->data[0];
1135169689Skan			br->Command = VM_CtBlockRead;
1136169689Skan			br->ContainerId = ad->ad_container->co_mntobj.ObjectId;
1137169689Skan			br->BlockNumber = bp->bio_pblkno;
1138169689Skan			br->ByteCount = bp->bio_bcount;
1139169689Skan			fib->Header.Size += sizeof(struct aac_blockread);
1140169689Skan			cm->cm_sgtable = &br->SgMap;
1141169689Skan			cm->cm_flags |= AAC_CMD_DATAIN;
1142169689Skan		} else {
1143169689Skan			struct aac_blockwrite *bw;
1144169689Skan			bw = (struct aac_blockwrite *)&fib->data[0];
1145169689Skan			bw->Command = VM_CtBlockWrite;
1146169689Skan			bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
1147169689Skan			bw->BlockNumber = bp->bio_pblkno;
1148169689Skan			bw->ByteCount = bp->bio_bcount;
1149169689Skan			bw->Stable = CUNSTABLE;
1150169689Skan			fib->Header.Size += sizeof(struct aac_blockwrite);
1151169689Skan			cm->cm_flags |= AAC_CMD_DATAOUT;
1152169689Skan			cm->cm_sgtable = &bw->SgMap;
1153169689Skan		}
1154169689Skan	} else {
1155169689Skan		fib->Header.Command = ContainerCommand64;
1156169689Skan		if (bp->bio_cmd == BIO_READ) {
1157169689Skan			struct aac_blockread64 *br;
1158169689Skan			br = (struct aac_blockread64 *)&fib->data[0];
1159169689Skan			br->Command = VM_CtHostRead64;
1160169689Skan			br->ContainerId = ad->ad_container->co_mntobj.ObjectId;
1161169689Skan			br->SectorCount = bp->bio_bcount / AAC_BLOCK_SIZE;
1162169689Skan			br->BlockNumber = bp->bio_pblkno;
1163169689Skan			br->Pad = 0;
1164169689Skan			br->Flags = 0;
1165169689Skan			fib->Header.Size += sizeof(struct aac_blockread64);
1166169689Skan			cm->cm_flags |= AAC_CMD_DATAOUT;
1167169689Skan			cm->cm_sgtable = (struct aac_sg_table *)&br->SgMap64;
1168169689Skan		} else {
1169169689Skan			struct aac_blockwrite64 *bw;
1170169689Skan			bw = (struct aac_blockwrite64 *)&fib->data[0];
1171169689Skan			bw->Command = VM_CtHostWrite64;
1172169689Skan			bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
1173169689Skan			bw->SectorCount = bp->bio_bcount / AAC_BLOCK_SIZE;
1174169689Skan			bw->BlockNumber = bp->bio_pblkno;
1175169689Skan			bw->Pad = 0;
1176169689Skan			bw->Flags = 0;
1177169689Skan			fib->Header.Size += sizeof(struct aac_blockwrite64);
1178169689Skan			cm->cm_flags |= AAC_CMD_DATAIN;
1179169689Skan			cm->cm_sgtable = (struct aac_sg_table *)&bw->SgMap64;
1180169689Skan		}
1181169689Skan	}
1182169689Skan
1183169689Skan	*cmp = cm;
1184169689Skan	return(0);
1185169689Skan
1186169689Skanfail:
1187169689Skan	if (bp != NULL)
1188169689Skan		aac_enqueue_bio(sc, bp);
1189169689Skan	if (cm != NULL)
1190169689Skan		aac_release_command(cm);
1191169689Skan	return(ENOMEM);
1192169689Skan}
1193169689Skan
1194169689Skan/*
1195169689Skan * Handle a bio-instigated command that has been completed.
1196169689Skan */
1197169689Skanstatic void
1198169689Skanaac_bio_complete(struct aac_command *cm)
1199169689Skan{
1200169689Skan	struct aac_blockread_response *brr;
1201169689Skan	struct aac_blockwrite_response *bwr;
1202169689Skan	struct bio *bp;
1203169689Skan	AAC_FSAStatus status;
1204169689Skan
1205169689Skan	/* fetch relevant status and then release the command */
1206169689Skan	bp = (struct bio *)cm->cm_private;
1207169689Skan	if (bp->bio_cmd == BIO_READ) {
1208169689Skan		brr = (struct aac_blockread_response *)&cm->cm_fib->data[0];
1209169689Skan		status = brr->Status;
1210169689Skan	} else {
1211169689Skan		bwr = (struct aac_blockwrite_response *)&cm->cm_fib->data[0];
1212169689Skan		status = bwr->Status;
1213169689Skan	}
1214169689Skan	aac_release_command(cm);
1215169689Skan
1216169689Skan	/* fix up the bio based on status */
1217169689Skan	if (status == ST_OK) {
1218169689Skan		bp->bio_resid = 0;
1219169689Skan	} else {
1220169689Skan		bp->bio_error = EIO;
1221169689Skan		bp->bio_flags |= BIO_ERROR;
1222169689Skan		/* pass an error string out to the disk layer */
1223169689Skan		bp->bio_driver1 = aac_describe_code(aac_command_status_table,
1224169689Skan						    status);
1225169689Skan	}
1226169689Skan	aac_biodone(bp);
1227169689Skan}
1228169689Skan
1229169689Skan/*
1230169689Skan * Submit a command to the controller, return when it completes.
1231169689Skan * XXX This is very dangerous!  If the card has gone out to lunch, we could
1232169689Skan *     be stuck here forever.  At the same time, signals are not caught
1233169689Skan *     because there is a risk that a signal could wakeup the sleep before
1234169689Skan *     the card has a chance to complete the command.  Since there is no way
1235169689Skan *     to cancel a command that is in progress, we can't protect against the
1236169689Skan *     card completing a command late and spamming the command and data
1237169689Skan *     memory.  So, we are held hostage until the command completes.
1238169689Skan */
1239169689Skanstatic int
1240169689Skanaac_wait_command(struct aac_command *cm)
1241169689Skan{
1242169689Skan	struct aac_softc *sc;
1243169689Skan	int error;
1244169689Skan
1245169689Skan	debug_called(2);
1246169689Skan
1247169689Skan	sc = cm->cm_sc;
1248169689Skan
1249169689Skan	/* Put the command on the ready queue and get things going */
1250169689Skan	cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
1251169689Skan	aac_enqueue_ready(cm);
1252169689Skan	aac_startio(sc);
1253169689Skan	error = msleep(cm, &sc->aac_io_lock, PRIBIO, "aacwait", 0);
1254169689Skan	return(error);
1255169689Skan}
1256169689Skan
1257169689Skan/*
1258169689Skan *Command Buffer Management
1259169689Skan */
1260169689Skan
1261169689Skan/*
1262169689Skan * Allocate a command.
1263169689Skan */
1264169689Skanint
1265169689Skanaac_alloc_command(struct aac_softc *sc, struct aac_command **cmp)
1266169689Skan{
1267169689Skan	struct aac_command *cm;
1268169689Skan
1269169689Skan	debug_called(3);
1270169689Skan
1271169689Skan	if ((cm = aac_dequeue_free(sc)) == NULL) {
1272169689Skan		if (sc->total_fibs < sc->aac_max_fibs) {
1273169689Skan			sc->aifflags |= AAC_AIFFLAGS_ALLOCFIBS;
1274169689Skan			wakeup(sc->aifthread);
1275169689Skan		}
1276169689Skan		return (EBUSY);
1277169689Skan	}
1278169689Skan
1279169689Skan	*cmp = cm;
1280169689Skan	return(0);
1281169689Skan}
1282169689Skan
1283169689Skan/*
1284169689Skan * Release a command back to the freelist.
1285169689Skan */
1286169689Skanvoid
1287169689Skanaac_release_command(struct aac_command *cm)
1288169689Skan{
1289169689Skan	struct aac_event *event;
1290169689Skan	struct aac_softc *sc;
1291169689Skan
1292169689Skan	debug_called(3);
1293169689Skan
1294169689Skan	/* (re)initialize the command/FIB */
1295169689Skan	cm->cm_sgtable = NULL;
1296169689Skan	cm->cm_flags = 0;
1297169689Skan	cm->cm_complete = NULL;
1298169689Skan	cm->cm_private = NULL;
1299169689Skan	cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY;
1300234855Sgonzo	cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB;
1301234855Sgonzo	cm->cm_fib->Header.Flags = 0;
1302169689Skan	cm->cm_fib->Header.SenderSize = cm->cm_sc->aac_max_fib_size;
1303234855Sgonzo
1304234855Sgonzo	/*
1305234855Sgonzo	 * These are duplicated in aac_start to cover the case where an
1306234855Sgonzo	 * intermediate stage may have destroyed them.  They're left
1307234855Sgonzo	 * initialized here for debugging purposes only.
1308234855Sgonzo	 */
1309234855Sgonzo	cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys;
1310234855Sgonzo	cm->cm_fib->Header.SenderData = 0;
1311234855Sgonzo
1312234855Sgonzo	aac_enqueue_free(cm);
1313234855Sgonzo
1314234855Sgonzo	/*
1315169689Skan	 * Dequeue all events so that there's no risk of events getting
1316169689Skan	 * stranded.
1317169689Skan	 */
1318169689Skan	sc = cm->cm_sc;
1319169689Skan	while ((event = TAILQ_FIRST(&sc->aac_ev_cmfree)) != NULL) {
1320169689Skan		TAILQ_REMOVE(&sc->aac_ev_cmfree, event, ev_links);
1321169689Skan		event->ev_callback(sc, event, event->ev_arg);
1322169689Skan	}
1323169689Skan}
1324169689Skan
1325169689Skan/*
1326169689Skan * Map helper for command/FIB allocation.
1327169689Skan */
1328169689Skanstatic void
1329169689Skanaac_map_command_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1330169689Skan{
1331169689Skan	uint64_t	*fibphys;
1332169689Skan
1333169689Skan	fibphys = (uint64_t *)arg;
1334169689Skan
1335169689Skan	debug_called(3);
1336169689Skan
1337169689Skan	*fibphys = segs[0].ds_addr;
1338169689Skan}
1339169689Skan
1340169689Skan/*
1341169689Skan * Allocate and initialize commands/FIBs for this adapter.
1342169689Skan */
1343169689Skanstatic int
1344169689Skanaac_alloc_commands(struct aac_softc *sc)
1345169689Skan{
1346169689Skan	struct aac_command *cm;
1347169689Skan	struct aac_fibmap *fm;
1348169689Skan	uint64_t fibphys;
1349169689Skan	int i, error;
1350169689Skan
1351169689Skan	debug_called(2);
1352169689Skan
1353169689Skan	if (sc->total_fibs + sc->aac_max_fibs_alloc > sc->aac_max_fibs)
1354169689Skan		return (ENOMEM);
1355169689Skan
1356169689Skan	fm = malloc(sizeof(struct aac_fibmap), M_AACBUF, M_NOWAIT|M_ZERO);
1357169689Skan	if (fm == NULL)
1358169689Skan		return (ENOMEM);
1359169689Skan
1360169689Skan	/* allocate the FIBs in DMAable memory and load them */
1361169689Skan	if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&fm->aac_fibs,
1362169689Skan			     BUS_DMA_NOWAIT, &fm->aac_fibmap)) {
1363169689Skan		device_printf(sc->aac_dev,
1364169689Skan			      "Not enough contiguous memory available.\n");
1365169689Skan		free(fm, M_AACBUF);
1366169689Skan		return (ENOMEM);
1367169689Skan	}
1368169689Skan
1369169689Skan	/* Ignore errors since this doesn't bounce */
1370169689Skan	(void)bus_dmamap_load(sc->aac_fib_dmat, fm->aac_fibmap, fm->aac_fibs,
1371169689Skan			      sc->aac_max_fibs_alloc * sc->aac_max_fib_size,
1372169689Skan			      aac_map_command_helper, &fibphys, 0);
1373169689Skan
1374169689Skan	/* initialize constant fields in the command structure */
1375169689Skan	bzero(fm->aac_fibs, sc->aac_max_fibs_alloc * sc->aac_max_fib_size);
1376169689Skan	for (i = 0; i < sc->aac_max_fibs_alloc; i++) {
1377169689Skan		cm = sc->aac_commands + sc->total_fibs;
1378169689Skan		fm->aac_commands = cm;
1379169689Skan		cm->cm_sc = sc;
1380169689Skan		cm->cm_fib = (struct aac_fib *)
1381169689Skan			((u_int8_t *)fm->aac_fibs + i*sc->aac_max_fib_size);
1382169689Skan		cm->cm_fibphys = fibphys + i*sc->aac_max_fib_size;
1383169689Skan		cm->cm_index = sc->total_fibs;
1384169689Skan
1385169689Skan		if ((error = bus_dmamap_create(sc->aac_buffer_dmat, 0,
1386169689Skan					       &cm->cm_datamap)) != 0)
1387169689Skan			break;
1388169689Skan		mtx_lock(&sc->aac_io_lock);
1389169689Skan		aac_release_command(cm);
1390169689Skan		sc->total_fibs++;
1391169689Skan		mtx_unlock(&sc->aac_io_lock);
1392169689Skan	}
1393169689Skan
1394169689Skan	if (i > 0) {
1395169689Skan		mtx_lock(&sc->aac_io_lock);
1396169689Skan		TAILQ_INSERT_TAIL(&sc->aac_fibmap_tqh, fm, fm_link);
1397169689Skan		debug(1, "total_fibs= %d\n", sc->total_fibs);
1398169689Skan		mtx_unlock(&sc->aac_io_lock);
1399169689Skan		return (0);
1400169689Skan	}
1401169689Skan
1402169689Skan	bus_dmamap_unload(sc->aac_fib_dmat, fm->aac_fibmap);
1403169689Skan	bus_dmamem_free(sc->aac_fib_dmat, fm->aac_fibs, fm->aac_fibmap);
1404169689Skan	free(fm, M_AACBUF);
1405169689Skan	return (ENOMEM);
1406169689Skan}
1407169689Skan
1408169689Skan/*
1409169689Skan * Free FIBs owned by this adapter.
1410169689Skan */
1411169689Skanstatic void
1412169689Skanaac_free_commands(struct aac_softc *sc)
1413169689Skan{
1414169689Skan	struct aac_fibmap *fm;
1415169689Skan	struct aac_command *cm;
1416169689Skan	int i;
1417169689Skan
1418169689Skan	debug_called(1);
1419169689Skan
1420169689Skan	while ((fm = TAILQ_FIRST(&sc->aac_fibmap_tqh)) != NULL) {
1421169689Skan
1422169689Skan		TAILQ_REMOVE(&sc->aac_fibmap_tqh, fm, fm_link);
1423169689Skan		/*
1424169689Skan		 * We check against total_fibs to handle partially
1425169689Skan		 * allocated blocks.
1426169689Skan		 */
1427169689Skan		for (i = 0; i < sc->aac_max_fibs_alloc && sc->total_fibs--; i++) {
1428169689Skan			cm = fm->aac_commands + i;
1429169689Skan			bus_dmamap_destroy(sc->aac_buffer_dmat, cm->cm_datamap);
1430169689Skan		}
1431169689Skan		bus_dmamap_unload(sc->aac_fib_dmat, fm->aac_fibmap);
1432169689Skan		bus_dmamem_free(sc->aac_fib_dmat, fm->aac_fibs, fm->aac_fibmap);
1433169689Skan		free(fm, M_AACBUF);
1434169689Skan	}
1435169689Skan}
1436169689Skan
1437169689Skan/*
1438169689Skan * Command-mapping helper function - populate this command's s/g table.
1439169689Skan */
1440169689Skanstatic void
1441169689Skanaac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1442169689Skan{
1443169689Skan	struct aac_softc *sc;
1444169689Skan	struct aac_command *cm;
1445169689Skan	struct aac_fib *fib;
1446169689Skan	int i;
1447169689Skan
1448169689Skan	debug_called(3);
1449169689Skan
1450169689Skan	cm = (struct aac_command *)arg;
1451169689Skan	sc = cm->cm_sc;
1452169689Skan	fib = cm->cm_fib;
1453169689Skan
1454169689Skan	/* copy into the FIB */
1455169689Skan	if (cm->cm_sgtable != NULL) {
1456169689Skan		if (fib->Header.Command == RawIo) {
1457169689Skan			struct aac_sg_tableraw *sg;
1458169689Skan			sg = (struct aac_sg_tableraw *)cm->cm_sgtable;
1459169689Skan			sg->SgCount = nseg;
1460169689Skan			for (i = 0; i < nseg; i++) {
1461169689Skan				sg->SgEntryRaw[i].SgAddress = segs[i].ds_addr;
1462169689Skan				sg->SgEntryRaw[i].SgByteCount = segs[i].ds_len;
1463169689Skan				sg->SgEntryRaw[i].Next = 0;
1464169689Skan				sg->SgEntryRaw[i].Prev = 0;
1465169689Skan				sg->SgEntryRaw[i].Flags = 0;
1466169689Skan			}
1467169689Skan			/* update the FIB size for the s/g count */
1468169689Skan			fib->Header.Size += nseg*sizeof(struct aac_sg_entryraw);
1469169689Skan		} else if ((cm->cm_sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
1470169689Skan			struct aac_sg_table *sg;
1471169689Skan			sg = cm->cm_sgtable;
1472169689Skan			sg->SgCount = nseg;
1473169689Skan			for (i = 0; i < nseg; i++) {
1474169689Skan				sg->SgEntry[i].SgAddress = segs[i].ds_addr;
1475169689Skan				sg->SgEntry[i].SgByteCount = segs[i].ds_len;
1476169689Skan			}
1477169689Skan			/* update the FIB size for the s/g count */
1478169689Skan			fib->Header.Size += nseg*sizeof(struct aac_sg_entry);
1479169689Skan		} else {
1480169689Skan			struct aac_sg_table64 *sg;
1481169689Skan			sg = (struct aac_sg_table64 *)cm->cm_sgtable;
1482169689Skan			sg->SgCount = nseg;
1483169689Skan			for (i = 0; i < nseg; i++) {
1484169689Skan				sg->SgEntry64[i].SgAddress = segs[i].ds_addr;
1485169689Skan				sg->SgEntry64[i].SgByteCount = segs[i].ds_len;
1486169689Skan			}
1487169689Skan			/* update the FIB size for the s/g count */
1488169689Skan			fib->Header.Size += nseg*sizeof(struct aac_sg_entry64);
1489169689Skan		}
1490169689Skan	}
1491169689Skan
1492169689Skan	/* Fix up the address values in the FIB.  Use the command array index
1493169689Skan	 * instead of a pointer since these fields are only 32 bits.  Shift
1494169689Skan	 * the SenderFibAddress over to make room for the fast response bit
1495169689Skan	 * and for the AIF bit
1496169689Skan	 */
1497169689Skan	cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 2);
1498169689Skan	cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys;
1499169689Skan
1500169689Skan	/* save a pointer to the command for speedy reverse-lookup */
1501169689Skan	cm->cm_fib->Header.SenderData = cm->cm_index;
1502169689Skan
1503169689Skan	if (cm->cm_flags & AAC_CMD_DATAIN)
1504169689Skan		bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
1505169689Skan				BUS_DMASYNC_PREREAD);
1506169689Skan	if (cm->cm_flags & AAC_CMD_DATAOUT)
1507169689Skan		bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
1508169689Skan				BUS_DMASYNC_PREWRITE);
1509169689Skan	cm->cm_flags |= AAC_CMD_MAPPED;
1510169689Skan
1511169689Skan	if (sc->flags & AAC_FLAGS_NEW_COMM) {
1512169689Skan		int count = 10000000L;
1513169689Skan		while (AAC_SEND_COMMAND(sc, cm) != 0) {
1514169689Skan			if (--count == 0) {
1515169689Skan				aac_unmap_command(cm);
1516169689Skan				sc->flags |= AAC_QUEUE_FRZN;
1517169689Skan				aac_requeue_ready(cm);
1518169689Skan			}
1519169689Skan			DELAY(5);			/* wait 5 usec. */
1520169689Skan		}
1521169689Skan	} else {
1522169689Skan		/* Put the FIB on the outbound queue */
1523169689Skan		if (aac_enqueue_fib(sc, cm->cm_queue, cm) == EBUSY) {
1524169689Skan			aac_unmap_command(cm);
1525169689Skan			sc->flags |= AAC_QUEUE_FRZN;
1526169689Skan			aac_requeue_ready(cm);
1527169689Skan		}
1528169689Skan	}
1529169689Skan
1530169689Skan	return;
1531169689Skan}
1532169689Skan
1533169689Skan/*
1534169689Skan * Unmap a command from controller-visible space.
1535169689Skan */
1536169689Skanstatic void
1537169689Skanaac_unmap_command(struct aac_command *cm)
1538169689Skan{
1539169689Skan	struct aac_softc *sc;
1540169689Skan
1541169689Skan	debug_called(2);
1542169689Skan
1543169689Skan	sc = cm->cm_sc;
1544169689Skan
1545169689Skan	if (!(cm->cm_flags & AAC_CMD_MAPPED))
1546169689Skan		return;
1547169689Skan
1548169689Skan	if (cm->cm_datalen != 0) {
1549169689Skan		if (cm->cm_flags & AAC_CMD_DATAIN)
1550169689Skan			bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
1551234855Sgonzo					BUS_DMASYNC_POSTREAD);
1552234855Sgonzo		if (cm->cm_flags & AAC_CMD_DATAOUT)
1553234855Sgonzo			bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
1554234855Sgonzo					BUS_DMASYNC_POSTWRITE);
1555234855Sgonzo
1556234855Sgonzo		bus_dmamap_unload(sc->aac_buffer_dmat, cm->cm_datamap);
1557234855Sgonzo	}
1558234855Sgonzo	cm->cm_flags &= ~AAC_CMD_MAPPED;
1559234855Sgonzo}
1560234855Sgonzo
1561169689Skan/*
1562169689Skan * Hardware Interface
1563169689Skan */
1564169689Skan
1565169689Skan/*
1566169689Skan * Initialize the adapter.
1567169689Skan */
1568169689Skanstatic void
1569169689Skanaac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1570169689Skan{
1571169689Skan	struct aac_softc *sc;
1572169689Skan
1573169689Skan	debug_called(1);
1574169689Skan
1575169689Skan	sc = (struct aac_softc *)arg;
1576169689Skan
1577169689Skan	sc->aac_common_busaddr = segs[0].ds_addr;
1578169689Skan}
1579169689Skan
1580169689Skanstatic int
1581169689Skanaac_check_firmware(struct aac_softc *sc)
1582169689Skan{
1583169689Skan	u_int32_t major, minor, options = 0, atu_size = 0;
1584169689Skan	int status;
1585169689Skan
1586169689Skan	debug_called(1);
1587169689Skan
1588169689Skan	/*
1589169689Skan	 * Retrieve the firmware version numbers.  Dell PERC2/QC cards with
1590169689Skan	 * firmware version 1.x are not compatible with this driver.
1591169689Skan	 */
1592169689Skan	if (sc->flags & AAC_FLAGS_PERC2QC) {
1593169689Skan		if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
1594169689Skan				     NULL)) {
1595169689Skan			device_printf(sc->aac_dev,
1596169689Skan				      "Error reading firmware version\n");
1597169689Skan			return (EIO);
1598169689Skan		}
1599169689Skan
1600169689Skan		/* These numbers are stored as ASCII! */
1601169689Skan		major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
1602169689Skan		minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
1603169689Skan		if (major == 1) {
1604169689Skan			device_printf(sc->aac_dev,
1605169689Skan			    "Firmware version %d.%d is not supported.\n",
1606169689Skan			    major, minor);
1607169689Skan			return (EINVAL);
1608169689Skan		}
1609169689Skan	}
1610169689Skan
1611169689Skan	/*
1612169689Skan	 * Retrieve the capabilities/supported options word so we know what
1613169689Skan	 * work-arounds to enable.  Some firmware revs don't support this
1614169689Skan	 * command.
1615169689Skan	 */
1616169689Skan	if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status)) {
1617169689Skan		if (status != AAC_SRB_STS_INVALID_REQUEST) {
1618169689Skan			device_printf(sc->aac_dev,
1619169689Skan			     "RequestAdapterInfo failed\n");
1620169689Skan			return (EIO);
1621169689Skan		}
1622169689Skan	} else {
1623169689Skan		options = AAC_GET_MAILBOX(sc, 1);
1624169689Skan		atu_size = AAC_GET_MAILBOX(sc, 2);
1625169689Skan		sc->supported_options = options;
1626169689Skan
1627169689Skan		if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 &&
1628169689Skan		    (sc->flags & AAC_FLAGS_NO4GB) == 0)
1629169689Skan			sc->flags |= AAC_FLAGS_4GB_WINDOW;
1630169689Skan		if (options & AAC_SUPPORTED_NONDASD)
1631169689Skan			sc->flags |= AAC_FLAGS_ENABLE_CAM;
1632169689Skan		if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0
1633169689Skan		     && (sizeof(bus_addr_t) > 4)) {
1634169689Skan			device_printf(sc->aac_dev,
1635169689Skan			    "Enabling 64-bit address support\n");
1636169689Skan			sc->flags |= AAC_FLAGS_SG_64BIT;
1637169689Skan		}
1638169689Skan		if ((options & AAC_SUPPORTED_NEW_COMM)
1639169689Skan		 && sc->aac_if.aif_send_command)
1640169689Skan			sc->flags |= AAC_FLAGS_NEW_COMM;
1641169689Skan		if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE)
1642169689Skan			sc->flags |= AAC_FLAGS_ARRAY_64BIT;
1643169689Skan	}
1644169689Skan
1645169689Skan	/* Check for broken hardware that does a lower number of commands */
1646169689Skan	sc->aac_max_fibs = (sc->flags & AAC_FLAGS_256FIBS ? 256:512);
1647169689Skan
1648169689Skan	/* Remap mem. resource, if required */
1649169689Skan	if ((sc->flags & AAC_FLAGS_NEW_COMM) &&
1650169689Skan		atu_size > rman_get_size(sc->aac_regs_resource)) {
1651169689Skan		bus_release_resource(
1652169689Skan			sc->aac_dev, SYS_RES_MEMORY,
1653169689Skan			sc->aac_regs_rid, sc->aac_regs_resource);
1654169689Skan		sc->aac_regs_resource = bus_alloc_resource(
1655169689Skan			sc->aac_dev, SYS_RES_MEMORY, &sc->aac_regs_rid,
1656169689Skan			0ul, ~0ul, atu_size, RF_ACTIVE);
1657169689Skan		if (sc->aac_regs_resource == NULL) {
1658169689Skan			sc->aac_regs_resource = bus_alloc_resource_any(
1659169689Skan				sc->aac_dev, SYS_RES_MEMORY,
1660169689Skan				&sc->aac_regs_rid, RF_ACTIVE);
1661169689Skan			if (sc->aac_regs_resource == NULL) {
1662169689Skan				device_printf(sc->aac_dev,
1663169689Skan				    "couldn't allocate register window\n");
1664169689Skan				return (ENXIO);
1665169689Skan			}
1666169689Skan			sc->flags &= ~AAC_FLAGS_NEW_COMM;
1667169689Skan		}
1668169689Skan		sc->aac_btag = rman_get_bustag(sc->aac_regs_resource);
1669169689Skan		sc->aac_bhandle = rman_get_bushandle(sc->aac_regs_resource);
1670169689Skan	}
1671169689Skan
1672169689Skan	/* Read preferred settings */
1673169689Skan	sc->aac_max_fib_size = sizeof(struct aac_fib);
1674169689Skan	sc->aac_max_sectors = 128;				/* 64KB */
1675169689Skan	if (sc->flags & AAC_FLAGS_SG_64BIT)
1676169689Skan		sc->aac_sg_tablesize = (AAC_FIB_DATASIZE
1677169689Skan		 - sizeof(struct aac_blockwrite64))
1678169689Skan		 / sizeof(struct aac_sg_entry64);
1679169689Skan	else
1680169689Skan		sc->aac_sg_tablesize = (AAC_FIB_DATASIZE
1681169689Skan		 - sizeof(struct aac_blockwrite))
1682169689Skan		 / sizeof(struct aac_sg_entry);
1683169689Skan
1684169689Skan	if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) {
1685169689Skan		options = AAC_GET_MAILBOX(sc, 1);
1686169689Skan		sc->aac_max_fib_size = (options & 0xFFFF);
1687169689Skan		sc->aac_max_sectors = (options >> 16) << 1;
1688169689Skan		options = AAC_GET_MAILBOX(sc, 2);
1689169689Skan		sc->aac_sg_tablesize = (options >> 16);
1690169689Skan		options = AAC_GET_MAILBOX(sc, 3);
1691169689Skan		sc->aac_max_fibs = (options & 0xFFFF);
1692169689Skan	}
1693169689Skan	if (sc->aac_max_fib_size > PAGE_SIZE)
1694169689Skan		sc->aac_max_fib_size = PAGE_SIZE;
1695169689Skan	sc->aac_max_fibs_alloc = PAGE_SIZE / sc->aac_max_fib_size;
1696169689Skan
1697169689Skan	if (sc->aac_max_fib_size > sizeof(struct aac_fib)) {
1698169689Skan		sc->flags |= AAC_FLAGS_RAW_IO;
1699169689Skan		device_printf(sc->aac_dev, "Enable Raw I/O\n");
1700169689Skan	}
1701169689Skan
1702169689Skan	return (0);
1703169689Skan}
1704169689Skan
1705169689Skanstatic int
1706169689Skanaac_init(struct aac_softc *sc)
1707169689Skan{
1708169689Skan	struct aac_adapter_init	*ip;
1709169689Skan	time_t then;
1710169689Skan	u_int32_t code, qoffset;
1711169689Skan	int error;
1712169689Skan
1713169689Skan	debug_called(1);
1714169689Skan
1715169689Skan	/*
1716169689Skan	 * First wait for the adapter to come ready.
1717169689Skan	 */
1718169689Skan	then = time_uptime;
1719169689Skan	do {
1720169689Skan		code = AAC_GET_FWSTATUS(sc);
1721169689Skan		if (code & AAC_SELF_TEST_FAILED) {
1722169689Skan			device_printf(sc->aac_dev, "FATAL: selftest failed\n");
1723169689Skan			return(ENXIO);
1724169689Skan		}
1725169689Skan		if (code & AAC_KERNEL_PANIC) {
1726169689Skan			device_printf(sc->aac_dev,
1727169689Skan				      "FATAL: controller kernel panic\n");
1728169689Skan			return(ENXIO);
1729169689Skan		}
1730169689Skan		if (time_uptime > (then + AAC_BOOT_TIMEOUT)) {
1731169689Skan			device_printf(sc->aac_dev,
1732169689Skan				      "FATAL: controller not coming ready, "
1733169689Skan					   "status %x\n", code);
1734169689Skan			return(ENXIO);
1735169689Skan		}
1736169689Skan	} while (!(code & AAC_UP_AND_RUNNING));
1737169689Skan
1738169689Skan	error = ENOMEM;
1739169689Skan	/*
1740169689Skan	 * Create DMA tag for mapping buffers into controller-addressable space.
1741169689Skan	 */
1742169689Skan	if (bus_dma_tag_create(sc->aac_parent_dmat, 	/* parent */
1743169689Skan			       1, 0, 			/* algnmnt, boundary */
1744169689Skan			       (sc->flags & AAC_FLAGS_SG_64BIT) ?
1745169689Skan			       BUS_SPACE_MAXADDR :
1746169689Skan			       BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
1747169689Skan			       BUS_SPACE_MAXADDR, 	/* highaddr */
1748169689Skan			       NULL, NULL, 		/* filter, filterarg */
1749169689Skan			       MAXBSIZE,		/* maxsize */
1750169689Skan			       sc->aac_sg_tablesize,	/* nsegments */
1751169689Skan			       MAXBSIZE,		/* maxsegsize */
1752169689Skan			       BUS_DMA_ALLOCNOW,	/* flags */
1753169689Skan			       busdma_lock_mutex,	/* lockfunc */
1754169689Skan			       &sc->aac_io_lock,	/* lockfuncarg */
1755169689Skan			       &sc->aac_buffer_dmat)) {
1756169689Skan		device_printf(sc->aac_dev, "can't allocate buffer DMA tag\n");
1757169689Skan		goto out;
1758169689Skan	}
1759169689Skan
1760169689Skan	/*
1761169689Skan	 * Create DMA tag for mapping FIBs into controller-addressable space..
1762169689Skan	 */
1763169689Skan	if (bus_dma_tag_create(sc->aac_parent_dmat,	/* parent */
1764169689Skan			       1, 0, 			/* algnmnt, boundary */
1765169689Skan			       (sc->flags & AAC_FLAGS_4GB_WINDOW) ?
1766169689Skan			       BUS_SPACE_MAXADDR_32BIT :
1767169689Skan			       0x7fffffff,		/* lowaddr */
1768169689Skan			       BUS_SPACE_MAXADDR, 	/* highaddr */
1769169689Skan			       NULL, NULL, 		/* filter, filterarg */
1770169689Skan			       sc->aac_max_fibs_alloc *
1771169689Skan			       sc->aac_max_fib_size,  /* maxsize */
1772169689Skan			       1,			/* nsegments */
1773169689Skan			       sc->aac_max_fibs_alloc *
1774169689Skan			       sc->aac_max_fib_size,	/* maxsegsize */
1775169689Skan			       0,			/* flags */
1776169689Skan			       NULL, NULL,		/* No locking needed */
1777169689Skan			       &sc->aac_fib_dmat)) {
1778169689Skan		device_printf(sc->aac_dev, "can't allocate FIB DMA tag\n");;
1779169689Skan		goto out;
1780169689Skan	}
1781169689Skan
1782169689Skan	/*
1783169689Skan	 * Create DMA tag for the common structure and allocate it.
1784169689Skan	 */
1785169689Skan	if (bus_dma_tag_create(sc->aac_parent_dmat, 	/* parent */
1786169689Skan			       1, 0,			/* algnmnt, boundary */
1787169689Skan			       (sc->flags & AAC_FLAGS_4GB_WINDOW) ?
1788169689Skan			       BUS_SPACE_MAXADDR_32BIT :
1789169689Skan			       0x7fffffff,		/* lowaddr */
1790169689Skan			       BUS_SPACE_MAXADDR, 	/* highaddr */
1791169689Skan			       NULL, NULL, 		/* filter, filterarg */
1792169689Skan			       8192 + sizeof(struct aac_common), /* maxsize */
1793169689Skan			       1,			/* nsegments */
1794169689Skan			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
1795169689Skan			       0,			/* flags */
1796169689Skan			       NULL, NULL,		/* No locking needed */
1797169689Skan			       &sc->aac_common_dmat)) {
1798169689Skan		device_printf(sc->aac_dev,
1799169689Skan			      "can't allocate common structure DMA tag\n");
1800169689Skan		goto out;
1801169689Skan	}
1802169689Skan	if (bus_dmamem_alloc(sc->aac_common_dmat, (void **)&sc->aac_common,
1803169689Skan			     BUS_DMA_NOWAIT, &sc->aac_common_dmamap)) {
1804169689Skan		device_printf(sc->aac_dev, "can't allocate common structure\n");
1805169689Skan		goto out;
1806169689Skan	}
1807169689Skan
1808169689Skan	/*
1809169689Skan	 * Work around a bug in the 2120 and 2200 that cannot DMA commands
1810169689Skan	 * below address 8192 in physical memory.
1811169689Skan	 * XXX If the padding is not needed, can it be put to use instead
1812169689Skan	 * of ignored?
1813169689Skan	 */
1814169689Skan	(void)bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap,
1815169689Skan			sc->aac_common, 8192 + sizeof(*sc->aac_common),
1816169689Skan			aac_common_map, sc, 0);
1817169689Skan
1818169689Skan	if (sc->aac_common_busaddr < 8192) {
1819169689Skan		sc->aac_common = (struct aac_common *)
1820169689Skan		    ((uint8_t *)sc->aac_common + 8192);
1821169689Skan		sc->aac_common_busaddr += 8192;
1822169689Skan	}
1823169689Skan	bzero(sc->aac_common, sizeof(*sc->aac_common));
1824169689Skan
1825169689Skan	/* Allocate some FIBs and associated command structs */
1826169689Skan	TAILQ_INIT(&sc->aac_fibmap_tqh);
1827169689Skan	sc->aac_commands = malloc(sc->aac_max_fibs * sizeof(struct aac_command),
1828169689Skan				  M_AACBUF, M_WAITOK|M_ZERO);
1829169689Skan	while (sc->total_fibs < AAC_PREALLOCATE_FIBS) {
1830169689Skan		if (aac_alloc_commands(sc) != 0)
1831169689Skan			break;
1832169689Skan	}
1833169689Skan	if (sc->total_fibs == 0)
1834169689Skan		goto out;
1835169689Skan
1836169689Skan	/*
1837169689Skan	 * Fill in the init structure.  This tells the adapter about the
1838169689Skan	 * physical location of various important shared data structures.
1839169689Skan	 */
1840169689Skan	ip = &sc->aac_common->ac_init;
1841169689Skan	ip->InitStructRevision = AAC_INIT_STRUCT_REVISION;
1842169689Skan	if (sc->aac_max_fib_size > sizeof(struct aac_fib)) {
1843169689Skan		ip->InitStructRevision = AAC_INIT_STRUCT_REVISION_4;
1844169689Skan		sc->flags |= AAC_FLAGS_RAW_IO;
1845169689Skan	}
1846169689Skan	ip->MiniPortRevision = AAC_INIT_STRUCT_MINIPORT_REVISION;
1847169689Skan
1848169689Skan	ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr +
1849169689Skan					 offsetof(struct aac_common, ac_fibs);
1850169689Skan	ip->AdapterFibsVirtualAddress = 0;
1851169689Skan	ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib);
1852169689Skan	ip->AdapterFibAlign = sizeof(struct aac_fib);
1853169689Skan
1854169689Skan	ip->PrintfBufferAddress = sc->aac_common_busaddr +
1855169689Skan				  offsetof(struct aac_common, ac_printf);
1856169689Skan	ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE;
1857169689Skan
1858169689Skan	/*
1859169689Skan	 * The adapter assumes that pages are 4K in size, except on some
1860169689Skan 	 * broken firmware versions that do the page->byte conversion twice,
1861169689Skan	 * therefore 'assuming' that this value is in 16MB units (2^24).
1862169689Skan	 * Round up since the granularity is so high.
1863169689Skan	 */
1864169689Skan	ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE;
1865169689Skan	if (sc->flags & AAC_FLAGS_BROKEN_MEMMAP) {
1866169689Skan		ip->HostPhysMemPages =
1867169689Skan		    (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE;
1868169689Skan	}
1869169689Skan	ip->HostElapsedSeconds = time_uptime;	/* reset later if invalid */
1870169689Skan
1871169689Skan	ip->InitFlags = 0;
1872169689Skan	if (sc->flags & AAC_FLAGS_NEW_COMM) {
1873169689Skan		ip->InitFlags = INITFLAGS_NEW_COMM_SUPPORTED;
1874169689Skan		device_printf(sc->aac_dev, "New comm. interface enabled\n");
1875169689Skan	}
1876169689Skan
1877169689Skan	ip->MaxIoCommands = sc->aac_max_fibs;
1878169689Skan	ip->MaxIoSize = sc->aac_max_sectors << 9;
1879169689Skan	ip->MaxFibSize = sc->aac_max_fib_size;
1880169689Skan
1881169689Skan	/*
1882169689Skan	 * Initialize FIB queues.  Note that it appears that the layout of the
1883169689Skan	 * indexes and the segmentation of the entries may be mandated by the
1884169689Skan	 * adapter, which is only told about the base of the queue index fields.
1885169689Skan	 *
1886169689Skan	 * The initial values of the indices are assumed to inform the adapter
1887169689Skan	 * of the sizes of the respective queues, and theoretically it could
1888169689Skan	 * work out the entire layout of the queue structures from this.  We
1889169689Skan	 * take the easy route and just lay this area out like everyone else
1890169689Skan	 * does.
1891169689Skan	 *
1892169689Skan	 * The Linux driver uses a much more complex scheme whereby several
1893169689Skan	 * header records are kept for each queue.  We use a couple of generic
1894169689Skan	 * list manipulation functions which 'know' the size of each list by
1895169689Skan	 * virtue of a table.
1896169689Skan	 */
1897169689Skan	qoffset = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
1898169689Skan	qoffset &= ~(AAC_QUEUE_ALIGN - 1);
1899169689Skan	sc->aac_queues =
1900169689Skan	    (struct aac_queue_table *)((uintptr_t)sc->aac_common + qoffset);
1901169689Skan	ip->CommHeaderAddress = sc->aac_common_busaddr + qoffset;
1902169689Skan
1903169689Skan	sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1904169689Skan		AAC_HOST_NORM_CMD_ENTRIES;
1905169689Skan	sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1906169689Skan		AAC_HOST_NORM_CMD_ENTRIES;
1907169689Skan	sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1908169689Skan		AAC_HOST_HIGH_CMD_ENTRIES;
1909169689Skan	sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1910169689Skan		AAC_HOST_HIGH_CMD_ENTRIES;
1911169689Skan	sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1912169689Skan		AAC_ADAP_NORM_CMD_ENTRIES;
1913169689Skan	sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1914169689Skan		AAC_ADAP_NORM_CMD_ENTRIES;
1915169689Skan	sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
1916169689Skan		AAC_ADAP_HIGH_CMD_ENTRIES;
1917169689Skan	sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
1918169689Skan		AAC_ADAP_HIGH_CMD_ENTRIES;
1919169689Skan	sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1920169689Skan		AAC_HOST_NORM_RESP_ENTRIES;
1921169689Skan	sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1922169689Skan		AAC_HOST_NORM_RESP_ENTRIES;
1923169689Skan	sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1924169689Skan		AAC_HOST_HIGH_RESP_ENTRIES;
1925169689Skan	sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1926169689Skan		AAC_HOST_HIGH_RESP_ENTRIES;
1927169689Skan	sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1928169689Skan		AAC_ADAP_NORM_RESP_ENTRIES;
1929169689Skan	sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1930169689Skan		AAC_ADAP_NORM_RESP_ENTRIES;
1931169689Skan	sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]=
1932169689Skan		AAC_ADAP_HIGH_RESP_ENTRIES;
1933169689Skan	sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]=
1934169689Skan		AAC_ADAP_HIGH_RESP_ENTRIES;
1935169689Skan	sc->aac_qentries[AAC_HOST_NORM_CMD_QUEUE] =
1936169689Skan		&sc->aac_queues->qt_HostNormCmdQueue[0];
1937169689Skan	sc->aac_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
1938169689Skan		&sc->aac_queues->qt_HostHighCmdQueue[0];
1939169689Skan	sc->aac_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
1940169689Skan		&sc->aac_queues->qt_AdapNormCmdQueue[0];
1941169689Skan	sc->aac_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
1942169689Skan		&sc->aac_queues->qt_AdapHighCmdQueue[0];
1943169689Skan	sc->aac_qentries[AAC_HOST_NORM_RESP_QUEUE] =
1944169689Skan		&sc->aac_queues->qt_HostNormRespQueue[0];
1945169689Skan	sc->aac_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
1946169689Skan		&sc->aac_queues->qt_HostHighRespQueue[0];
1947169689Skan	sc->aac_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
1948169689Skan		&sc->aac_queues->qt_AdapNormRespQueue[0];
1949169689Skan	sc->aac_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
1950169689Skan		&sc->aac_queues->qt_AdapHighRespQueue[0];
1951169689Skan
1952169689Skan	/*
1953169689Skan	 * Do controller-type-specific initialisation
1954169689Skan	 */
1955169689Skan	switch (sc->aac_hwif) {
1956169689Skan	case AAC_HWIF_I960RX:
1957169689Skan		AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
1958169689Skan		break;
1959169689Skan	case AAC_HWIF_RKT:
1960169689Skan		AAC_SETREG4(sc, AAC_RKT_ODBR, ~0);
1961169689Skan		break;
1962169689Skan	default:
1963169689Skan		break;
1964169689Skan	}
1965169689Skan
1966169689Skan	/*
1967169689Skan	 * Give the init structure to the controller.
1968169689Skan	 */
1969169689Skan	if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
1970169689Skan			     sc->aac_common_busaddr +
1971169689Skan			     offsetof(struct aac_common, ac_init), 0, 0, 0,
1972169689Skan			     NULL)) {
1973169689Skan		device_printf(sc->aac_dev,
1974169689Skan			      "error establishing init structure\n");
1975169689Skan		error = EIO;
1976169689Skan		goto out;
1977169689Skan	}
1978169689Skan
1979169689Skan	error = 0;
1980169689Skanout:
1981169689Skan	return(error);
1982169689Skan}
1983169689Skan
1984169689Skan/*
1985169689Skan * Send a synchronous command to the controller and wait for a result.
1986169689Skan * Indicate if the controller completed the command with an error status.
1987169689Skan */
1988169689Skanstatic int
1989169689Skanaac_sync_command(struct aac_softc *sc, u_int32_t command,
1990169689Skan		 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3,
1991169689Skan		 u_int32_t *sp)
1992169689Skan{
1993169689Skan	time_t then;
1994169689Skan	u_int32_t status;
1995169689Skan
1996169689Skan	debug_called(3);
1997169689Skan
1998169689Skan	/* populate the mailbox */
1999169689Skan	AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
2000169689Skan
2001169689Skan	/* ensure the sync command doorbell flag is cleared */
2002169689Skan	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
2003169689Skan
2004169689Skan	/* then set it to signal the adapter */
2005169689Skan	AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
2006169689Skan
2007169689Skan	/* spin waiting for the command to complete */
2008169689Skan	then = time_uptime;
2009169689Skan	do {
2010169689Skan		if (time_uptime > (then + AAC_IMMEDIATE_TIMEOUT)) {
2011169689Skan			debug(1, "timed out");
2012169689Skan			return(EIO);
2013169689Skan		}
2014169689Skan	} while (!(AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND));
2015169689Skan
2016169689Skan	/* clear the completion flag */
2017169689Skan	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
2018169689Skan
2019169689Skan	/* get the command status */
2020169689Skan	status = AAC_GET_MAILBOX(sc, 0);
2021169689Skan	if (sp != NULL)
2022169689Skan		*sp = status;
2023169689Skan
2024169689Skan	if (status != AAC_SRB_STS_SUCCESS)
2025169689Skan		return (-1);
2026169689Skan	return(0);
2027169689Skan}
2028169689Skan
2029169689Skanint
2030169689Skanaac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
2031169689Skan		 struct aac_fib *fib, u_int16_t datasize)
2032169689Skan{
2033169689Skan	debug_called(3);
2034169689Skan	mtx_assert(&sc->aac_io_lock, MA_OWNED);
2035169689Skan
2036169689Skan	if (datasize > AAC_FIB_DATASIZE)
2037169689Skan		return(EINVAL);
2038169689Skan
2039169689Skan	/*
2040169689Skan	 * Set up the sync FIB
2041169689Skan	 */
2042169689Skan	fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED |
2043169689Skan				AAC_FIBSTATE_INITIALISED |
2044169689Skan				AAC_FIBSTATE_EMPTY;
2045169689Skan	fib->Header.XferState |= xferstate;
2046169689Skan	fib->Header.Command = command;
2047169689Skan	fib->Header.StructType = AAC_FIBTYPE_TFIB;
2048169689Skan	fib->Header.Size = sizeof(struct aac_fib) + datasize;
2049169689Skan	fib->Header.SenderSize = sizeof(struct aac_fib);
2050169689Skan	fib->Header.SenderFibAddress = 0;	/* Not needed */
2051169689Skan	fib->Header.ReceiverFibAddress = sc->aac_common_busaddr +
2052169689Skan					 offsetof(struct aac_common,
2053169689Skan						  ac_sync_fib);
2054169689Skan
2055169689Skan	/*
2056169689Skan	 * Give the FIB to the controller, wait for a response.
2057169689Skan	 */
2058169689Skan	if (aac_sync_command(sc, AAC_MONKER_SYNCFIB,
2059169689Skan			     fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) {
2060169689Skan		debug(2, "IO error");
2061169689Skan		return(EIO);
2062169689Skan	}
2063169689Skan
2064169689Skan	return (0);
2065169689Skan}
2066169689Skan
2067169689Skan/*
2068169689Skan * Adapter-space FIB queue manipulation
2069169689Skan *
2070169689Skan * Note that the queue implementation here is a little funky; neither the PI or
2071169689Skan * CI will ever be zero.  This behaviour is a controller feature.
2072169689Skan */
2073169689Skanstatic struct {
2074169689Skan	int		size;
2075169689Skan	int		notify;
2076169689Skan} aac_qinfo[] = {
2077169689Skan	{AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL},
2078169689Skan	{AAC_HOST_HIGH_CMD_ENTRIES, 0},
2079169689Skan	{AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY},
2080169689Skan	{AAC_ADAP_HIGH_CMD_ENTRIES, 0},
2081169689Skan	{AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL},
2082169689Skan	{AAC_HOST_HIGH_RESP_ENTRIES, 0},
2083169689Skan	{AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY},
2084169689Skan	{AAC_ADAP_HIGH_RESP_ENTRIES, 0}
2085169689Skan};
2086169689Skan
2087169689Skan/*
2088169689Skan * Atomically insert an entry into the nominated queue, returns 0 on success or
2089169689Skan * EBUSY if the queue is full.
2090169689Skan *
2091169689Skan * Note: it would be more efficient to defer notifying the controller in
2092169689Skan *	 the case where we may be inserting several entries in rapid succession,
2093169689Skan *	 but implementing this usefully may be difficult (it would involve a
2094169689Skan *	 separate queue/notify interface).
2095169689Skan */
2096169689Skanstatic int
2097169689Skanaac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
2098169689Skan{
2099169689Skan	u_int32_t pi, ci;
2100169689Skan	int error;
2101169689Skan	u_int32_t fib_size;
2102169689Skan	u_int32_t fib_addr;
2103169689Skan
2104169689Skan	debug_called(3);
2105169689Skan
2106169689Skan	fib_size = cm->cm_fib->Header.Size;
2107169689Skan	fib_addr = cm->cm_fib->Header.ReceiverFibAddress;
2108169689Skan
2109169689Skan	/* get the producer/consumer indices */
2110169689Skan	pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
2111169689Skan	ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
2112169689Skan
2113169689Skan	/* wrap the queue? */
2114169689Skan	if (pi >= aac_qinfo[queue].size)
2115169689Skan		pi = 0;
2116169689Skan
2117169689Skan	/* check for queue full */
2118169689Skan	if ((pi + 1) == ci) {
2119169689Skan		error = EBUSY;
2120169689Skan		goto out;
2121169689Skan	}
2122169689Skan
2123169689Skan	/*
2124169689Skan	 * To avoid a race with its completion interrupt, place this command on
2125169689Skan	 * the busy queue prior to advertising it to the controller.
2126169689Skan	 */
2127169689Skan	aac_enqueue_busy(cm);
2128169689Skan
2129169689Skan	/* populate queue entry */
2130169689Skan	(sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
2131169689Skan	(sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
2132169689Skan
2133169689Skan	/* update producer index */
2134169689Skan	sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
2135169689Skan
2136169689Skan	/* notify the adapter if we know how */
2137169689Skan	if (aac_qinfo[queue].notify != 0)
2138169689Skan		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
2139169689Skan
2140169689Skan	error = 0;
2141169689Skan
2142169689Skanout:
2143169689Skan	return(error);
2144169689Skan}
2145169689Skan
2146169689Skan/*
2147169689Skan * Atomically remove one entry from the nominated queue, returns 0 on
2148169689Skan * success or ENOENT if the queue is empty.
2149169689Skan */
2150169689Skanstatic int
2151169689Skanaac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
2152169689Skan		struct aac_fib **fib_addr)
2153169689Skan{
2154169689Skan	u_int32_t pi, ci;
2155169689Skan	u_int32_t fib_index;
2156169689Skan	int error;
2157169689Skan	int notify;
2158169689Skan
2159169689Skan	debug_called(3);
2160169689Skan
2161169689Skan	/* get the producer/consumer indices */
2162169689Skan	pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
2163169689Skan	ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
2164169689Skan
2165169689Skan	/* check for queue empty */
2166169689Skan	if (ci == pi) {
2167169689Skan		error = ENOENT;
2168169689Skan		goto out;
2169169689Skan	}
2170169689Skan
2171169689Skan	/* wrap the pi so the following test works */
2172169689Skan	if (pi >= aac_qinfo[queue].size)
2173169689Skan		pi = 0;
2174169689Skan
2175169689Skan	notify = 0;
2176169689Skan	if (ci == pi + 1)
2177169689Skan		notify++;
2178169689Skan
2179169689Skan	/* wrap the queue? */
2180169689Skan	if (ci >= aac_qinfo[queue].size)
2181169689Skan		ci = 0;
2182169689Skan
2183169689Skan	/* fetch the entry */
2184169689Skan	*fib_size = (sc->aac_qentries[queue] + ci)->aq_fib_size;
2185169689Skan
2186169689Skan	switch (queue) {
2187169689Skan	case AAC_HOST_NORM_CMD_QUEUE:
2188169689Skan	case AAC_HOST_HIGH_CMD_QUEUE:
2189169689Skan		/*
2190169689Skan		 * The aq_fib_addr is only 32 bits wide so it can't be counted
2191169689Skan		 * on to hold an address.  For AIF's, the adapter assumes
2192169689Skan		 * that it's giving us an address into the array of AIF fibs.
2193169689Skan		 * Therefore, we have to convert it to an index.
2194169689Skan		 */
2195169689Skan		fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr /
2196169689Skan			sizeof(struct aac_fib);
2197169689Skan		*fib_addr = &sc->aac_common->ac_fibs[fib_index];
2198169689Skan		break;
2199169689Skan
2200169689Skan	case AAC_HOST_NORM_RESP_QUEUE:
2201169689Skan	case AAC_HOST_HIGH_RESP_QUEUE:
2202169689Skan	{
2203169689Skan		struct aac_command *cm;
2204169689Skan
2205169689Skan		/*
2206169689Skan		 * As above, an index is used instead of an actual address.
2207169689Skan		 * Gotta shift the index to account for the fast response
2208169689Skan		 * bit.  No other correction is needed since this value was
2209169689Skan		 * originally provided by the driver via the SenderFibAddress
2210169689Skan		 * field.
2211169689Skan		 */
2212169689Skan		fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr;
2213169689Skan		cm = sc->aac_commands + (fib_index >> 2);
2214169689Skan		*fib_addr = cm->cm_fib;
2215169689Skan
2216169689Skan		/*
2217169689Skan		 * Is this a fast response? If it is, update the fib fields in
2218169689Skan		 * local memory since the whole fib isn't DMA'd back up.
2219169689Skan		 */
2220169689Skan		if (fib_index & 0x01) {
2221169689Skan			(*fib_addr)->Header.XferState |= AAC_FIBSTATE_DONEADAP;
2222169689Skan			*((u_int32_t*)((*fib_addr)->data)) = AAC_ERROR_NORMAL;
2223169689Skan		}
2224169689Skan		break;
2225169689Skan	}
2226169689Skan	default:
2227169689Skan		panic("Invalid queue in aac_dequeue_fib()");
2228169689Skan		break;
2229169689Skan	}
2230169689Skan
2231169689Skan	/* update consumer index */
2232169689Skan	sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
2233169689Skan
2234169689Skan	/* if we have made the queue un-full, notify the adapter */
2235169689Skan	if (notify && (aac_qinfo[queue].notify != 0))
2236169689Skan		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
2237169689Skan	error = 0;
2238169689Skan
2239169689Skanout:
2240169689Skan	return(error);
2241169689Skan}
2242169689Skan
2243169689Skan/*
2244169689Skan * Put our response to an Adapter Initialed Fib on the response queue
2245169689Skan */
2246169689Skanstatic int
2247169689Skanaac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
2248169689Skan{
2249169689Skan	u_int32_t pi, ci;
2250169689Skan	int error;
2251169689Skan	u_int32_t fib_size;
2252169689Skan	u_int32_t fib_addr;
2253169689Skan
2254169689Skan	debug_called(1);
2255169689Skan
2256169689Skan	/* Tell the adapter where the FIB is */
2257169689Skan	fib_size = fib->Header.Size;
2258169689Skan	fib_addr = fib->Header.SenderFibAddress;
2259169689Skan	fib->Header.ReceiverFibAddress = fib_addr;
2260169689Skan
2261169689Skan	/* get the producer/consumer indices */
2262169689Skan	pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
2263169689Skan	ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
2264169689Skan
2265169689Skan	/* wrap the queue? */
2266169689Skan	if (pi >= aac_qinfo[queue].size)
2267169689Skan		pi = 0;
2268169689Skan
2269169689Skan	/* check for queue full */
2270169689Skan	if ((pi + 1) == ci) {
2271169689Skan		error = EBUSY;
2272169689Skan		goto out;
2273169689Skan	}
2274169689Skan
2275169689Skan	/* populate queue entry */
2276169689Skan	(sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
2277169689Skan	(sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
2278169689Skan
2279169689Skan	/* update producer index */
2280169689Skan	sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
2281169689Skan
2282169689Skan	/* notify the adapter if we know how */
2283169689Skan	if (aac_qinfo[queue].notify != 0)
2284169689Skan		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
2285169689Skan
2286169689Skan	error = 0;
2287169689Skan
2288169689Skanout:
2289169689Skan	return(error);
2290169689Skan}
2291169689Skan
2292169689Skan/*
2293169689Skan * Check for commands that have been outstanding for a suspiciously long time,
2294169689Skan * and complain about them.
2295169689Skan */
2296169689Skanstatic void
2297169689Skanaac_timeout(struct aac_softc *sc)
2298169689Skan{
2299169689Skan	struct aac_command *cm;
2300169689Skan	time_t deadline;
2301169689Skan	int timedout, code;
2302169689Skan
2303169689Skan	/*
2304169689Skan	 * Traverse the busy command list, bitch about late commands once
2305169689Skan	 * only.
2306169689Skan	 */
2307169689Skan	timedout = 0;
2308169689Skan	deadline = time_uptime - AAC_CMD_TIMEOUT;
2309169689Skan	TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) {
2310169689Skan		if ((cm->cm_timestamp  < deadline)
2311169689Skan			/* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) {
2312169689Skan			cm->cm_flags |= AAC_CMD_TIMEDOUT;
2313169689Skan			device_printf(sc->aac_dev,
2314169689Skan				      "COMMAND %p TIMEOUT AFTER %d SECONDS\n",
2315169689Skan				      cm, (int)(time_uptime-cm->cm_timestamp));
2316169689Skan			AAC_PRINT_FIB(sc, cm->cm_fib);
2317169689Skan			timedout++;
2318169689Skan		}
2319169689Skan	}
2320169689Skan
2321169689Skan	if (timedout) {
2322169689Skan		code = AAC_GET_FWSTATUS(sc);
2323169689Skan		if (code != AAC_UP_AND_RUNNING) {
2324169689Skan			device_printf(sc->aac_dev, "WARNING! Controller is no "
2325169689Skan				      "longer running! code= 0x%x\n", code);
2326169689Skan		}
2327169689Skan	}
2328169689Skan	return;
2329169689Skan}
2330169689Skan
2331169689Skan/*
2332169689Skan * Interface Function Vectors
2333169689Skan */
2334169689Skan
2335169689Skan/*
2336169689Skan * Read the current firmware status word.
2337169689Skan */
2338169689Skanstatic int
2339169689Skanaac_sa_get_fwstatus(struct aac_softc *sc)
2340169689Skan{
2341169689Skan	debug_called(3);
2342169689Skan
2343169689Skan	return(AAC_GETREG4(sc, AAC_SA_FWSTATUS));
2344169689Skan}
2345169689Skan
2346169689Skanstatic int
2347169689Skanaac_rx_get_fwstatus(struct aac_softc *sc)
2348169689Skan{
2349169689Skan	debug_called(3);
2350169689Skan
2351169689Skan	return(AAC_GETREG4(sc, AAC_RX_FWSTATUS));
2352169689Skan}
2353169689Skan
2354169689Skanstatic int
2355169689Skanaac_fa_get_fwstatus(struct aac_softc *sc)
2356169689Skan{
2357169689Skan	int val;
2358169689Skan
2359169689Skan	debug_called(3);
2360169689Skan
2361169689Skan	val = AAC_GETREG4(sc, AAC_FA_FWSTATUS);
2362169689Skan	return (val);
2363169689Skan}
2364169689Skan
2365169689Skanstatic int
2366169689Skanaac_rkt_get_fwstatus(struct aac_softc *sc)
2367169689Skan{
2368169689Skan	debug_called(3);
2369169689Skan
2370169689Skan	return(AAC_GETREG4(sc, AAC_RKT_FWSTATUS));
2371169689Skan}
2372169689Skan
2373169689Skan/*
2374169689Skan * Notify the controller of a change in a given queue
2375169689Skan */
2376169689Skan
2377169689Skanstatic void
2378169689Skanaac_sa_qnotify(struct aac_softc *sc, int qbit)
2379169689Skan{
2380169689Skan	debug_called(3);
2381169689Skan
2382169689Skan	AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit);
2383169689Skan}
2384169689Skan
2385169689Skanstatic void
2386169689Skanaac_rx_qnotify(struct aac_softc *sc, int qbit)
2387169689Skan{
2388169689Skan	debug_called(3);
2389169689Skan
2390169689Skan	AAC_SETREG4(sc, AAC_RX_IDBR, qbit);
2391169689Skan}
2392169689Skan
2393169689Skanstatic void
2394169689Skanaac_fa_qnotify(struct aac_softc *sc, int qbit)
2395169689Skan{
2396169689Skan	debug_called(3);
2397169689Skan
2398169689Skan	AAC_SETREG2(sc, AAC_FA_DOORBELL1, qbit);
2399169689Skan	AAC_FA_HACK(sc);
2400169689Skan}
2401169689Skan
2402169689Skanstatic void
2403169689Skanaac_rkt_qnotify(struct aac_softc *sc, int qbit)
2404169689Skan{
2405169689Skan	debug_called(3);
2406169689Skan
2407169689Skan	AAC_SETREG4(sc, AAC_RKT_IDBR, qbit);
2408169689Skan}
2409169689Skan
2410169689Skan/*
2411169689Skan * Get the interrupt reason bits
2412169689Skan */
2413169689Skanstatic int
2414169689Skanaac_sa_get_istatus(struct aac_softc *sc)
2415169689Skan{
2416169689Skan	debug_called(3);
2417169689Skan
2418169689Skan	return(AAC_GETREG2(sc, AAC_SA_DOORBELL0));
2419169689Skan}
2420169689Skan
2421169689Skanstatic int
2422169689Skanaac_rx_get_istatus(struct aac_softc *sc)
2423169689Skan{
2424169689Skan	debug_called(3);
2425169689Skan
2426169689Skan	return(AAC_GETREG4(sc, AAC_RX_ODBR));
2427169689Skan}
2428169689Skan
2429169689Skanstatic int
2430169689Skanaac_fa_get_istatus(struct aac_softc *sc)
2431169689Skan{
2432169689Skan	int val;
2433169689Skan
2434169689Skan	debug_called(3);
2435169689Skan
2436169689Skan	val = AAC_GETREG2(sc, AAC_FA_DOORBELL0);
2437169689Skan	return (val);
2438169689Skan}
2439169689Skan
2440169689Skanstatic int
2441169689Skanaac_rkt_get_istatus(struct aac_softc *sc)
2442169689Skan{
2443169689Skan	debug_called(3);
2444169689Skan
2445169689Skan	return(AAC_GETREG4(sc, AAC_RKT_ODBR));
2446169689Skan}
2447169689Skan
2448169689Skan/*
2449169689Skan * Clear some interrupt reason bits
2450169689Skan */
2451169689Skanstatic void
2452169689Skanaac_sa_clear_istatus(struct aac_softc *sc, int mask)
2453169689Skan{
2454169689Skan	debug_called(3);
2455169689Skan
2456169689Skan	AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask);
2457169689Skan}
2458169689Skan
2459169689Skanstatic void
2460169689Skanaac_rx_clear_istatus(struct aac_softc *sc, int mask)
2461169689Skan{
2462169689Skan	debug_called(3);
2463169689Skan
2464169689Skan	AAC_SETREG4(sc, AAC_RX_ODBR, mask);
2465169689Skan}
2466169689Skan
2467169689Skanstatic void
2468169689Skanaac_fa_clear_istatus(struct aac_softc *sc, int mask)
2469169689Skan{
2470169689Skan	debug_called(3);
2471169689Skan
2472169689Skan	AAC_SETREG2(sc, AAC_FA_DOORBELL0_CLEAR, mask);
2473169689Skan	AAC_FA_HACK(sc);
2474169689Skan}
2475169689Skan
2476169689Skanstatic void
2477169689Skanaac_rkt_clear_istatus(struct aac_softc *sc, int mask)
2478169689Skan{
2479169689Skan	debug_called(3);
2480169689Skan
2481169689Skan	AAC_SETREG4(sc, AAC_RKT_ODBR, mask);
2482169689Skan}
2483169689Skan
2484169689Skan/*
2485169689Skan * Populate the mailbox and set the command word
2486169689Skan */
2487169689Skanstatic void
2488169689Skanaac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
2489169689Skan		u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2490169689Skan{
2491169689Skan	debug_called(4);
2492169689Skan
2493169689Skan	AAC_SETREG4(sc, AAC_SA_MAILBOX, command);
2494169689Skan	AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0);
2495169689Skan	AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1);
2496169689Skan	AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2);
2497169689Skan	AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3);
2498169689Skan}
2499169689Skan
2500169689Skanstatic void
2501169689Skanaac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command,
2502169689Skan		u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2503169689Skan{
2504169689Skan	debug_called(4);
2505169689Skan
2506169689Skan	AAC_SETREG4(sc, AAC_RX_MAILBOX, command);
2507169689Skan	AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0);
2508169689Skan	AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1);
2509169689Skan	AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2);
2510169689Skan	AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3);
2511169689Skan}
2512169689Skan
2513169689Skanstatic void
2514169689Skanaac_fa_set_mailbox(struct aac_softc *sc, u_int32_t command,
2515169689Skan		u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2516169689Skan{
2517169689Skan	debug_called(4);
2518169689Skan
2519169689Skan	AAC_SETREG4(sc, AAC_FA_MAILBOX, command);
2520169689Skan	AAC_FA_HACK(sc);
2521169689Skan	AAC_SETREG4(sc, AAC_FA_MAILBOX + 4, arg0);
2522169689Skan	AAC_FA_HACK(sc);
2523169689Skan	AAC_SETREG4(sc, AAC_FA_MAILBOX + 8, arg1);
2524169689Skan	AAC_FA_HACK(sc);
2525169689Skan	AAC_SETREG4(sc, AAC_FA_MAILBOX + 12, arg2);
2526169689Skan	AAC_FA_HACK(sc);
2527169689Skan	AAC_SETREG4(sc, AAC_FA_MAILBOX + 16, arg3);
2528169689Skan	AAC_FA_HACK(sc);
2529169689Skan}
2530169689Skan
2531169689Skanstatic void
2532169689Skanaac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
2533169689Skan		    u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
2534169689Skan{
2535169689Skan	debug_called(4);
2536169689Skan
2537169689Skan	AAC_SETREG4(sc, AAC_RKT_MAILBOX, command);
2538169689Skan	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0);
2539169689Skan	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1);
2540169689Skan	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2);
2541169689Skan	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3);
2542169689Skan}
2543169689Skan
2544169689Skan/*
2545169689Skan * Fetch the immediate command status word
2546169689Skan */
2547169689Skanstatic int
2548169689Skanaac_sa_get_mailbox(struct aac_softc *sc, int mb)
2549169689Skan{
2550169689Skan	debug_called(4);
2551169689Skan
2552169689Skan	return(AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4)));
2553169689Skan}
2554169689Skan
2555169689Skanstatic int
2556169689Skanaac_rx_get_mailbox(struct aac_softc *sc, int mb)
2557169689Skan{
2558169689Skan	debug_called(4);
2559169689Skan
2560169689Skan	return(AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4)));
2561169689Skan}
2562169689Skan
2563169689Skanstatic int
2564169689Skanaac_fa_get_mailbox(struct aac_softc *sc, int mb)
2565169689Skan{
2566169689Skan	int val;
2567169689Skan
2568169689Skan	debug_called(4);
2569169689Skan
2570169689Skan	val = AAC_GETREG4(sc, AAC_FA_MAILBOX + (mb * 4));
2571169689Skan	return (val);
2572169689Skan}
2573169689Skan
2574169689Skanstatic int
2575169689Skanaac_rkt_get_mailbox(struct aac_softc *sc, int mb)
2576169689Skan{
2577169689Skan	debug_called(4);
2578169689Skan
2579169689Skan	return(AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4)));
2580169689Skan}
2581169689Skan
2582169689Skan/*
2583169689Skan * Set/clear interrupt masks
2584169689Skan */
2585169689Skanstatic void
2586169689Skanaac_sa_set_interrupts(struct aac_softc *sc, int enable)
2587169689Skan{
2588169689Skan	debug(2, "%sable interrupts", enable ? "en" : "dis");
2589169689Skan
2590169689Skan	if (enable) {
2591169689Skan		AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
2592169689Skan	} else {
2593169689Skan		AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0);
2594169689Skan	}
2595169689Skan}
2596169689Skan
2597169689Skanstatic void
2598169689Skanaac_rx_set_interrupts(struct aac_softc *sc, int enable)
2599169689Skan{
2600169689Skan	debug(2, "%sable interrupts", enable ? "en" : "dis");
2601169689Skan
2602169689Skan	if (enable) {
2603169689Skan		if (sc->flags & AAC_FLAGS_NEW_COMM)
2604169689Skan			AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INT_NEW_COMM);
2605169689Skan		else
2606169689Skan			AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
2607169689Skan	} else {
2608169689Skan		AAC_SETREG4(sc, AAC_RX_OIMR, ~0);
2609169689Skan	}
2610169689Skan}
2611169689Skan
2612169689Skanstatic void
2613169689Skanaac_fa_set_interrupts(struct aac_softc *sc, int enable)
2614169689Skan{
2615169689Skan	debug(2, "%sable interrupts", enable ? "en" : "dis");
2616169689Skan
2617169689Skan	if (enable) {
2618169689Skan		AAC_SETREG2((sc), AAC_FA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
2619169689Skan		AAC_FA_HACK(sc);
2620169689Skan	} else {
2621169689Skan		AAC_SETREG2((sc), AAC_FA_MASK0, ~0);
2622169689Skan		AAC_FA_HACK(sc);
2623169689Skan	}
2624169689Skan}
2625169689Skan
2626169689Skanstatic void
2627169689Skanaac_rkt_set_interrupts(struct aac_softc *sc, int enable)
2628169689Skan{
2629169689Skan	debug(2, "%sable interrupts", enable ? "en" : "dis");
2630169689Skan
2631169689Skan	if (enable) {
2632169689Skan		if (sc->flags & AAC_FLAGS_NEW_COMM)
2633169689Skan			AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INT_NEW_COMM);
2634169689Skan		else
2635169689Skan			AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS);
2636169689Skan	} else {
2637169689Skan		AAC_SETREG4(sc, AAC_RKT_OIMR, ~0);
2638169689Skan	}
2639169689Skan}
2640169689Skan
2641169689Skan/*
2642169689Skan * New comm. interface: Send command functions
2643169689Skan */
2644169689Skanstatic int
2645169689Skanaac_rx_send_command(struct aac_softc *sc, struct aac_command *cm)
2646169689Skan{
2647169689Skan	u_int32_t index, device;
2648169689Skan
2649169689Skan	debug(2, "send command (new comm.)");
2650169689Skan
2651169689Skan	index = AAC_GETREG4(sc, AAC_RX_IQUE);
2652169689Skan	if (index == 0xffffffffL)
2653169689Skan		index = AAC_GETREG4(sc, AAC_RX_IQUE);
2654169689Skan	if (index == 0xffffffffL)
2655169689Skan		return index;
2656169689Skan	aac_enqueue_busy(cm);
2657169689Skan	device = index;
2658169689Skan	AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys & 0xffffffffUL));
2659169689Skan	device += 4;
2660169689Skan	AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys >> 32));
2661169689Skan	device += 4;
2662169689Skan	AAC_SETREG4(sc, device, cm->cm_fib->Header.Size);
2663169689Skan	AAC_SETREG4(sc, AAC_RX_IQUE, index);
2664169689Skan	return 0;
2665169689Skan}
2666169689Skan
2667169689Skanstatic int
2668169689Skanaac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm)
2669169689Skan{
2670169689Skan	u_int32_t index, device;
2671169689Skan
2672169689Skan	debug(2, "send command (new comm.)");
2673169689Skan
2674169689Skan	index = AAC_GETREG4(sc, AAC_RKT_IQUE);
2675169689Skan	if (index == 0xffffffffL)
2676169689Skan		index = AAC_GETREG4(sc, AAC_RKT_IQUE);
2677169689Skan	if (index == 0xffffffffL)
2678169689Skan		return index;
2679169689Skan	aac_enqueue_busy(cm);
2680169689Skan	device = index;
2681169689Skan	AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys & 0xffffffffUL));
2682169689Skan	device += 4;
2683169689Skan	AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys >> 32));
2684169689Skan	device += 4;
2685169689Skan	AAC_SETREG4(sc, device, cm->cm_fib->Header.Size);
2686169689Skan	AAC_SETREG4(sc, AAC_RKT_IQUE, index);
2687169689Skan	return 0;
2688169689Skan}
2689169689Skan
2690169689Skan/*
2691169689Skan * New comm. interface: get, set outbound queue index
2692169689Skan */
2693169689Skanstatic int
2694169689Skanaac_rx_get_outb_queue(struct aac_softc *sc)
2695169689Skan{
2696169689Skan	debug_called(3);
2697169689Skan
2698169689Skan	return(AAC_GETREG4(sc, AAC_RX_OQUE));
2699169689Skan}
2700169689Skan
2701169689Skanstatic int
2702169689Skanaac_rkt_get_outb_queue(struct aac_softc *sc)
2703169689Skan{
2704169689Skan	debug_called(3);
2705169689Skan
2706169689Skan	return(AAC_GETREG4(sc, AAC_RKT_OQUE));
2707169689Skan}
2708169689Skan
2709169689Skanstatic void
2710169689Skanaac_rx_set_outb_queue(struct aac_softc *sc, int index)
2711169689Skan{
2712169689Skan	debug_called(3);
2713169689Skan
2714169689Skan	AAC_SETREG4(sc, AAC_RX_OQUE, index);
2715169689Skan}
2716169689Skan
2717169689Skanstatic void
2718169689Skanaac_rkt_set_outb_queue(struct aac_softc *sc, int index)
2719169689Skan{
2720169689Skan	debug_called(3);
2721169689Skan
2722169689Skan	AAC_SETREG4(sc, AAC_RKT_OQUE, index);
2723169689Skan}
2724169689Skan
2725169689Skan/*
2726169689Skan * Debugging and Diagnostics
2727169689Skan */
2728169689Skan
2729169689Skan/*
2730169689Skan * Print some information about the controller.
2731169689Skan */
2732169689Skanstatic void
2733169689Skanaac_describe_controller(struct aac_softc *sc)
2734169689Skan{
2735169689Skan	struct aac_fib *fib;
2736169689Skan	struct aac_adapter_info	*info;
2737169689Skan	char *adapter_type = "Adaptec RAID controller";
2738169689Skan
2739169689Skan	debug_called(2);
2740169689Skan
2741169689Skan	mtx_lock(&sc->aac_io_lock);
2742169689Skan	aac_alloc_sync_fib(sc, &fib);
2743169689Skan
2744169689Skan	if (sc->supported_options & AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO) {
2745169689Skan		fib->data[0] = 0;
2746169689Skan		if (aac_sync_fib(sc, RequestSupplementAdapterInfo, 0, fib, 1))
2747169689Skan			device_printf(sc->aac_dev,
2748169689Skan			    "RequestSupplementAdapterInfo failed\n");
2749169689Skan		else
2750169689Skan			adapter_type = ((struct aac_supplement_adapter_info *)
2751169689Skan			    &fib->data[0])->AdapterTypeText;
2752169689Skan	}
2753169689Skan	device_printf(sc->aac_dev, "%s, aac driver %d.%d.%d-%d\n",
2754169689Skan		adapter_type,
2755169689Skan		AAC_DRIVER_VERSION >> 24,
2756169689Skan		(AAC_DRIVER_VERSION >> 16) & 0xFF,
2757169689Skan		AAC_DRIVER_VERSION & 0xFF,
2758169689Skan		AAC_DRIVER_BUILD);
2759169689Skan
2760169689Skan	fib->data[0] = 0;
2761169689Skan	if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) {
2762169689Skan		device_printf(sc->aac_dev, "RequestAdapterInfo failed\n");
2763169689Skan		aac_release_sync_fib(sc);
2764169689Skan		mtx_unlock(&sc->aac_io_lock);
2765169689Skan		return;
2766169689Skan	}
2767169689Skan
2768169689Skan	/* save the kernel revision structure for later use */
2769169689Skan	info = (struct aac_adapter_info *)&fib->data[0];
2770169689Skan	sc->aac_revision = info->KernelRevision;
2771169689Skan
2772169689Skan
2773169689Skan	if (bootverbose) {
2774169689Skan		device_printf(sc->aac_dev, "%s %dMHz, %dMB memory "
2775169689Skan		    "(%dMB cache, %dMB execution), %s\n",
2776169689Skan		    aac_describe_code(aac_cpu_variant, info->CpuVariant),
2777169689Skan		    info->ClockSpeed, info->TotalMem / (1024 * 1024),
2778169689Skan		    info->BufferMem / (1024 * 1024),
2779169689Skan		    info->ExecutionMem / (1024 * 1024),
2780169689Skan		    aac_describe_code(aac_battery_platform,
2781169689Skan		    info->batteryPlatform));
2782169689Skan
2783169689Skan		device_printf(sc->aac_dev,
2784169689Skan		    "Kernel %d.%d-%d, Build %d, S/N %6X\n",
2785169689Skan		    info->KernelRevision.external.comp.major,
2786169689Skan		    info->KernelRevision.external.comp.minor,
2787169689Skan		    info->KernelRevision.external.comp.dash,
2788169689Skan		    info->KernelRevision.buildNumber,
2789169689Skan		    (u_int32_t)(info->SerialNumber & 0xffffff));
2790169689Skan
2791169689Skan		device_printf(sc->aac_dev, "Supported Options=%b\n",
2792169689Skan			      sc->supported_options,
2793169689Skan			      "\20"
2794169689Skan			      "\1SNAPSHOT"
2795169689Skan			      "\2CLUSTERS"
2796169689Skan			      "\3WCACHE"
2797169689Skan			      "\4DATA64"
2798169689Skan			      "\5HOSTTIME"
2799169689Skan			      "\6RAID50"
2800169689Skan			      "\7WINDOW4GB"
2801169689Skan			      "\10SCSIUPGD"
2802169689Skan			      "\11SOFTERR"
2803169689Skan			      "\12NORECOND"
2804169689Skan			      "\13SGMAP64"
2805169689Skan			      "\14ALARM"
2806169689Skan			      "\15NONDASD"
2807169689Skan			      "\16SCSIMGT"
2808169689Skan			      "\17RAIDSCSI"
2809169689Skan			      "\21ADPTINFO"
2810169689Skan			      "\22NEWCOMM"
2811169689Skan			      "\23ARRAY64BIT"
2812169689Skan			      "\24HEATSENSOR");
2813169689Skan	}
2814169689Skan	aac_release_sync_fib(sc);
2815169689Skan	mtx_unlock(&sc->aac_io_lock);
2816169689Skan}
2817169689Skan
2818169689Skan/*
2819169689Skan * Look up a text description of a numeric error code and return a pointer to
2820169689Skan * same.
2821169689Skan */
2822169689Skanstatic char *
2823169689Skanaac_describe_code(struct aac_code_lookup *table, u_int32_t code)
2824169689Skan{
2825169689Skan	int i;
2826169689Skan
2827169689Skan	for (i = 0; table[i].string != NULL; i++)
2828169689Skan		if (table[i].code == code)
2829169689Skan			return(table[i].string);
2830169689Skan	return(table[i + 1].string);
2831169689Skan}
2832169689Skan
2833169689Skan/*
2834169689Skan * Management Interface
2835169689Skan */
2836169689Skan
2837169689Skanstatic int
2838169689Skanaac_open(struct cdev *dev, int flags, int fmt, d_thread_t *td)
2839169689Skan{
2840169689Skan	struct aac_softc *sc;
2841169689Skan
2842169689Skan	debug_called(2);
2843169689Skan
2844169689Skan	sc = dev->si_drv1;
2845169689Skan	sc->aac_open_cnt++;
2846169689Skan	sc->aac_state |= AAC_STATE_OPEN;
2847169689Skan
2848169689Skan	return 0;
2849169689Skan}
2850169689Skan
2851169689Skanstatic int
2852169689Skanaac_close(struct cdev *dev, int flags, int fmt, d_thread_t *td)
2853169689Skan{
2854169689Skan	struct aac_softc *sc;
2855169689Skan
2856169689Skan	debug_called(2);
2857169689Skan
2858169689Skan	sc = dev->si_drv1;
2859169689Skan	sc->aac_open_cnt--;
2860169689Skan	/* Mark this unit as no longer open  */
2861169689Skan	if (sc->aac_open_cnt == 0)
2862169689Skan		sc->aac_state &= ~AAC_STATE_OPEN;
2863169689Skan
2864169689Skan	return 0;
2865169689Skan}
2866169689Skan
2867169689Skanstatic int
2868169689Skanaac_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
2869169689Skan{
2870169689Skan	union aac_statrequest *as;
2871169689Skan	struct aac_softc *sc;
2872169689Skan	int error = 0;
2873169689Skan
2874169689Skan	debug_called(2);
2875169689Skan
2876169689Skan	as = (union aac_statrequest *)arg;
2877169689Skan	sc = dev->si_drv1;
2878169689Skan
2879169689Skan	switch (cmd) {
2880169689Skan	case AACIO_STATS:
2881169689Skan		switch (as->as_item) {
2882169689Skan		case AACQ_FREE:
2883169689Skan		case AACQ_BIO:
2884169689Skan		case AACQ_READY:
2885169689Skan		case AACQ_BUSY:
2886169689Skan			bcopy(&sc->aac_qstat[as->as_item], &as->as_qstat,
2887169689Skan			      sizeof(struct aac_qstat));
2888169689Skan			break;
2889169689Skan		default:
2890169689Skan			error = ENOENT;
2891169689Skan			break;
2892169689Skan		}
2893169689Skan	break;
2894169689Skan
2895169689Skan	case FSACTL_SENDFIB:
2896169689Skan	case FSACTL_SEND_LARGE_FIB:
2897169689Skan		arg = *(caddr_t*)arg;
2898169689Skan	case FSACTL_LNX_SENDFIB:
2899169689Skan	case FSACTL_LNX_SEND_LARGE_FIB:
2900169689Skan		debug(1, "FSACTL_SENDFIB");
2901169689Skan		error = aac_ioctl_sendfib(sc, arg);
2902169689Skan		break;
2903169689Skan	case FSACTL_SEND_RAW_SRB:
2904169689Skan		arg = *(caddr_t*)arg;
2905169689Skan	case FSACTL_LNX_SEND_RAW_SRB:
2906169689Skan		debug(1, "FSACTL_SEND_RAW_SRB");
2907169689Skan		error = aac_ioctl_send_raw_srb(sc, arg);
2908169689Skan		break;
2909169689Skan	case FSACTL_AIF_THREAD:
2910169689Skan	case FSACTL_LNX_AIF_THREAD:
2911169689Skan		debug(1, "FSACTL_AIF_THREAD");
2912169689Skan		error = EINVAL;
2913169689Skan		break;
2914169689Skan	case FSACTL_OPEN_GET_ADAPTER_FIB:
2915169689Skan		arg = *(caddr_t*)arg;
2916169689Skan	case FSACTL_LNX_OPEN_GET_ADAPTER_FIB:
2917169689Skan		debug(1, "FSACTL_OPEN_GET_ADAPTER_FIB");
2918169689Skan		error = aac_open_aif(sc, arg);
2919169689Skan		break;
2920169689Skan	case FSACTL_GET_NEXT_ADAPTER_FIB:
2921169689Skan		arg = *(caddr_t*)arg;
2922169689Skan	case FSACTL_LNX_GET_NEXT_ADAPTER_FIB:
2923169689Skan		debug(1, "FSACTL_GET_NEXT_ADAPTER_FIB");
2924169689Skan		error = aac_getnext_aif(sc, arg);
2925169689Skan		break;
2926169689Skan	case FSACTL_CLOSE_GET_ADAPTER_FIB:
2927169689Skan		arg = *(caddr_t*)arg;
2928169689Skan	case FSACTL_LNX_CLOSE_GET_ADAPTER_FIB:
2929169689Skan		debug(1, "FSACTL_CLOSE_GET_ADAPTER_FIB");
2930169689Skan		error = aac_close_aif(sc, arg);
2931169689Skan		break;
2932169689Skan	case FSACTL_MINIPORT_REV_CHECK:
2933169689Skan		arg = *(caddr_t*)arg;
2934169689Skan	case FSACTL_LNX_MINIPORT_REV_CHECK:
2935169689Skan		debug(1, "FSACTL_MINIPORT_REV_CHECK");
2936169689Skan		error = aac_rev_check(sc, arg);
2937169689Skan		break;
2938169689Skan	case FSACTL_QUERY_DISK:
2939169689Skan		arg = *(caddr_t*)arg;
2940169689Skan	case FSACTL_LNX_QUERY_DISK:
2941169689Skan		debug(1, "FSACTL_QUERY_DISK");
2942169689Skan		error = aac_query_disk(sc, arg);
2943169689Skan		break;
2944169689Skan	case FSACTL_DELETE_DISK:
2945169689Skan	case FSACTL_LNX_DELETE_DISK:
2946169689Skan		/*
2947169689Skan		 * We don't trust the underland to tell us when to delete a
2948169689Skan		 * container, rather we rely on an AIF coming from the
2949169689Skan		 * controller
2950169689Skan		 */
2951169689Skan		error = 0;
2952169689Skan		break;
2953169689Skan	case FSACTL_GET_PCI_INFO:
2954169689Skan		arg = *(caddr_t*)arg;
2955169689Skan	case FSACTL_LNX_GET_PCI_INFO:
2956169689Skan		debug(1, "FSACTL_GET_PCI_INFO");
2957169689Skan		error = aac_get_pci_info(sc, arg);
2958169689Skan		break;
2959169689Skan	default:
2960169689Skan		debug(1, "unsupported cmd 0x%lx\n", cmd);
2961169689Skan		error = EINVAL;
2962169689Skan		break;
2963169689Skan	}
2964169689Skan	return(error);
2965169689Skan}
2966169689Skan
2967169689Skanstatic int
2968169689Skanaac_poll(struct cdev *dev, int poll_events, d_thread_t *td)
2969169689Skan{
2970169689Skan	struct aac_softc *sc;
2971169689Skan	int revents;
2972169689Skan
2973169689Skan	sc = dev->si_drv1;
2974169689Skan	revents = 0;
2975169689Skan
2976169689Skan	mtx_lock(&sc->aac_aifq_lock);
2977169689Skan	if ((poll_events & (POLLRDNORM | POLLIN)) != 0) {
2978169689Skan		if (sc->aifq_idx != 0 || sc->aifq_filled)
2979169689Skan			revents |= poll_events & (POLLIN | POLLRDNORM);
2980169689Skan	}
2981169689Skan	mtx_unlock(&sc->aac_aifq_lock);
2982169689Skan
2983169689Skan	if (revents == 0) {
2984169689Skan		if (poll_events & (POLLIN | POLLRDNORM))
2985169689Skan			selrecord(td, &sc->rcv_select);
2986169689Skan	}
2987169689Skan
2988169689Skan	return (revents);
2989169689Skan}
2990169689Skan
2991169689Skanstatic void
2992169689Skanaac_ioctl_event(struct aac_softc *sc, struct aac_event *event, void *arg)
2993169689Skan{
2994169689Skan
2995169689Skan	switch (event->ev_type) {
2996169689Skan	case AAC_EVENT_CMFREE:
2997169689Skan		mtx_assert(&sc->aac_io_lock, MA_OWNED);
2998169689Skan		if (aac_alloc_command(sc, (struct aac_command **)arg)) {
2999169689Skan			aac_add_event(sc, event);
3000169689Skan			return;
3001169689Skan		}
3002169689Skan		free(event, M_AACBUF);
3003169689Skan		wakeup(arg);
3004169689Skan		break;
3005169689Skan	default:
3006169689Skan		break;
3007169689Skan	}
3008169689Skan}
3009169689Skan
3010169689Skan/*
3011169689Skan * Send a FIB supplied from userspace
3012169689Skan */
3013169689Skanstatic int
3014169689Skanaac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib)
3015169689Skan{
3016169689Skan	struct aac_command *cm;
3017169689Skan	int size, error;
3018169689Skan
3019169689Skan	debug_called(2);
3020169689Skan
3021169689Skan	cm = NULL;
3022169689Skan
3023169689Skan	/*
3024169689Skan	 * Get a command
3025169689Skan	 */
3026169689Skan	mtx_lock(&sc->aac_io_lock);
3027169689Skan	if (aac_alloc_command(sc, &cm)) {
3028169689Skan		struct aac_event *event;
3029169689Skan
3030169689Skan		event = malloc(sizeof(struct aac_event), M_AACBUF,
3031169689Skan		    M_NOWAIT | M_ZERO);
3032169689Skan		if (event == NULL) {
3033169689Skan			error = EBUSY;
3034169689Skan			mtx_unlock(&sc->aac_io_lock);
3035169689Skan			goto out;
3036169689Skan		}
3037169689Skan		event->ev_type = AAC_EVENT_CMFREE;
3038169689Skan		event->ev_callback = aac_ioctl_event;
3039169689Skan		event->ev_arg = &cm;
3040169689Skan		aac_add_event(sc, event);
3041169689Skan		msleep(&cm, &sc->aac_io_lock, 0, "sendfib", 0);
3042169689Skan	}
3043169689Skan	mtx_unlock(&sc->aac_io_lock);
3044169689Skan
3045169689Skan	/*
3046169689Skan	 * Fetch the FIB header, then re-copy to get data as well.
3047169689Skan	 */
3048169689Skan	if ((error = copyin(ufib, cm->cm_fib,
3049169689Skan			    sizeof(struct aac_fib_header))) != 0)
3050169689Skan		goto out;
3051169689Skan	size = cm->cm_fib->Header.Size + sizeof(struct aac_fib_header);
3052169689Skan	if (size > sc->aac_max_fib_size) {
3053169689Skan		device_printf(sc->aac_dev, "incoming FIB oversized (%d > %d)\n",
3054169689Skan			      size, sc->aac_max_fib_size);
3055169689Skan		size = sc->aac_max_fib_size;
3056169689Skan	}
3057169689Skan	if ((error = copyin(ufib, cm->cm_fib, size)) != 0)
3058169689Skan		goto out;
3059169689Skan	cm->cm_fib->Header.Size = size;
3060169689Skan	cm->cm_timestamp = time_uptime;
3061169689Skan
3062169689Skan	/*
3063169689Skan	 * Pass the FIB to the controller, wait for it to complete.
3064169689Skan	 */
3065169689Skan	mtx_lock(&sc->aac_io_lock);
3066169689Skan	error = aac_wait_command(cm);
3067169689Skan	mtx_unlock(&sc->aac_io_lock);
3068169689Skan	if (error != 0) {
3069169689Skan		device_printf(sc->aac_dev,
3070169689Skan			      "aac_wait_command return %d\n", error);
3071169689Skan		goto out;
3072169689Skan	}
3073169689Skan
3074169689Skan	/*
3075169689Skan	 * Copy the FIB and data back out to the caller.
3076169689Skan	 */
3077169689Skan	size = cm->cm_fib->Header.Size;
3078169689Skan	if (size > sc->aac_max_fib_size) {
3079169689Skan		device_printf(sc->aac_dev, "outbound FIB oversized (%d > %d)\n",
3080169689Skan			      size, sc->aac_max_fib_size);
3081169689Skan		size = sc->aac_max_fib_size;
3082169689Skan	}
3083169689Skan	error = copyout(cm->cm_fib, ufib, size);
3084169689Skan
3085169689Skanout:
3086169689Skan	if (cm != NULL) {
3087169689Skan		mtx_lock(&sc->aac_io_lock);
3088169689Skan		aac_release_command(cm);
3089169689Skan		mtx_unlock(&sc->aac_io_lock);
3090169689Skan	}
3091169689Skan	return(error);
3092169689Skan}
3093169689Skan
3094169689Skan/*
3095169689Skan * Send a passthrough FIB supplied from userspace
3096169689Skan */
3097169689Skanstatic int
3098169689Skanaac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg)
3099169689Skan{
3100169689Skan	return (EINVAL);
3101169689Skan}
3102169689Skan
3103169689Skan/*
3104169689Skan * Handle an AIF sent to us by the controller; queue it for later reference.
3105169689Skan * If the queue fills up, then drop the older entries.
3106169689Skan */
3107169689Skanstatic void
3108169689Skanaac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
3109169689Skan{
3110169689Skan	struct aac_aif_command *aif;
3111169689Skan	struct aac_container *co, *co_next;
3112169689Skan	struct aac_fib_context *ctx;
3113169689Skan	struct aac_mntinfo *mi;
3114169689Skan	struct aac_mntinforesp *mir = NULL;
3115169689Skan	u_int16_t rsize;
3116169689Skan	int next, current, found;
3117169689Skan	int count = 0, added = 0, i = 0;
3118169689Skan
3119169689Skan	debug_called(2);
3120169689Skan
3121169689Skan	aif = (struct aac_aif_command*)&fib->data[0];
3122169689Skan	aac_print_aif(sc, aif);
3123169689Skan
3124169689Skan	/* Is it an event that we should care about? */
3125169689Skan	switch (aif->command) {
3126169689Skan	case AifCmdEventNotify:
3127169689Skan		switch (aif->data.EN.type) {
3128169689Skan		case AifEnAddContainer:
3129169689Skan		case AifEnDeleteContainer:
3130169689Skan			/*
3131169689Skan			 * A container was added or deleted, but the message
3132169689Skan			 * doesn't tell us anything else!  Re-enumerate the
3133169689Skan			 * containers and sort things out.
3134169689Skan			 */
3135169689Skan			aac_alloc_sync_fib(sc, &fib);
3136169689Skan			mi = (struct aac_mntinfo *)&fib->data[0];
3137169689Skan			do {
3138169689Skan				/*
3139169689Skan				 * Ask the controller for its containers one at
3140169689Skan				 * a time.
3141169689Skan				 * XXX What if the controller's list changes
3142169689Skan				 * midway through this enumaration?
3143169689Skan				 * XXX This should be done async.
3144169689Skan				 */
3145169689Skan				bzero(mi, sizeof(struct aac_mntinfo));
3146169689Skan				mi->Command = VM_NameServe;
3147169689Skan				mi->MntType = FT_FILESYS;
3148169689Skan				mi->MntCount = i;
3149169689Skan				rsize = sizeof(mir);
3150169689Skan				if (aac_sync_fib(sc, ContainerCommand, 0, fib,
3151169689Skan						 sizeof(struct aac_mntinfo))) {
3152169689Skan					printf("Error probing container %d\n",
3153169689Skan					      i);
3154169689Skan					continue;
3155169689Skan				}
3156169689Skan				mir = (struct aac_mntinforesp *)&fib->data[0];
3157169689Skan				/* XXX Need to check if count changed */
3158169689Skan				count = mir->MntRespCount;
3159169689Skan				/*
3160169689Skan				 * Check the container against our list.
3161169689Skan				 * co->co_found was already set to 0 in a
3162169689Skan				 * previous run.
3163169689Skan				 */
3164169689Skan				if ((mir->Status == ST_OK) &&
3165169689Skan				    (mir->MntTable[0].VolType != CT_NONE)) {
3166169689Skan					found = 0;
3167169689Skan					TAILQ_FOREACH(co,
3168169689Skan						      &sc->aac_container_tqh,
3169169689Skan						      co_link) {
3170169689Skan						if (co->co_mntobj.ObjectId ==
3171169689Skan						    mir->MntTable[0].ObjectId) {
3172169689Skan							co->co_found = 1;
3173169689Skan							found = 1;
3174169689Skan							break;
3175169689Skan						}
3176169689Skan					}
3177169689Skan					/*
3178169689Skan					 * If the container matched, continue
3179169689Skan					 * in the list.
3180169689Skan					 */
3181169689Skan					if (found) {
3182169689Skan						i++;
3183169689Skan						continue;
3184169689Skan					}
3185169689Skan
3186169689Skan					/*
3187169689Skan					 * This is a new container.  Do all the
3188169689Skan					 * appropriate things to set it up.
3189169689Skan					 */
3190169689Skan					aac_add_container(sc, mir, 1);
3191169689Skan					added = 1;
3192169689Skan				}
3193169689Skan				i++;
3194169689Skan			} while ((i < count) && (i < AAC_MAX_CONTAINERS));
3195169689Skan			aac_release_sync_fib(sc);
3196169689Skan
3197169689Skan			/*
3198169689Skan			 * Go through our list of containers and see which ones
3199169689Skan			 * were not marked 'found'.  Since the controller didn't
3200169689Skan			 * list them they must have been deleted.  Do the
3201169689Skan			 * appropriate steps to destroy the device.  Also reset
3202169689Skan			 * the co->co_found field.
3203169689Skan			 */
3204169689Skan			co = TAILQ_FIRST(&sc->aac_container_tqh);
3205169689Skan			while (co != NULL) {
3206169689Skan				if (co->co_found == 0) {
3207169689Skan					mtx_unlock(&sc->aac_io_lock);
3208169689Skan					mtx_lock(&Giant);
3209169689Skan					device_delete_child(sc->aac_dev,
3210169689Skan							    co->co_disk);
3211169689Skan					mtx_unlock(&Giant);
3212169689Skan					mtx_lock(&sc->aac_io_lock);
3213169689Skan					co_next = TAILQ_NEXT(co, co_link);
3214169689Skan					mtx_lock(&sc->aac_container_lock);
3215169689Skan					TAILQ_REMOVE(&sc->aac_container_tqh, co,
3216169689Skan						     co_link);
3217169689Skan					mtx_unlock(&sc->aac_container_lock);
3218169689Skan					free(co, M_AACBUF);
3219169689Skan					co = co_next;
3220169689Skan				} else {
3221169689Skan					co->co_found = 0;
3222169689Skan					co = TAILQ_NEXT(co, co_link);
3223169689Skan				}
3224169689Skan			}
3225169689Skan
3226169689Skan			/* Attach the newly created containers */
3227169689Skan			if (added) {
3228169689Skan				mtx_unlock(&sc->aac_io_lock);
3229169689Skan				mtx_lock(&Giant);
3230169689Skan				bus_generic_attach(sc->aac_dev);
3231169689Skan				mtx_unlock(&Giant);
3232169689Skan				mtx_lock(&sc->aac_io_lock);
3233169689Skan			}
3234169689Skan
3235169689Skan			break;
3236169689Skan
3237169689Skan		default:
3238169689Skan			break;
3239169689Skan		}
3240169689Skan
3241169689Skan	default:
3242169689Skan		break;
3243169689Skan	}
3244169689Skan
3245169689Skan	/* Copy the AIF data to the AIF queue for ioctl retrieval */
3246169689Skan	mtx_lock(&sc->aac_aifq_lock);
3247169689Skan	current = sc->aifq_idx;
3248169689Skan	next = (current + 1) % AAC_AIFQ_LENGTH;
3249169689Skan	if (next == 0)
3250169689Skan		sc->aifq_filled = 1;
3251169689Skan	bcopy(fib, &sc->aac_aifq[current], sizeof(struct aac_fib));
3252169689Skan	/* modify AIF contexts */
3253169689Skan	if (sc->aifq_filled) {
3254169689Skan		for (ctx = sc->fibctx; ctx; ctx = ctx->next) {
3255169689Skan			if (next == ctx->ctx_idx)
3256169689Skan				ctx->ctx_wrap = 1;
3257169689Skan			else if (current == ctx->ctx_idx && ctx->ctx_wrap)
3258169689Skan				ctx->ctx_idx = next;
3259169689Skan		}
3260169689Skan	}
3261169689Skan	sc->aifq_idx = next;
3262169689Skan	/* On the off chance that someone is sleeping for an aif... */
3263169689Skan	if (sc->aac_state & AAC_STATE_AIF_SLEEPER)
3264169689Skan		wakeup(sc->aac_aifq);
3265169689Skan	/* Wakeup any poll()ers */
3266169689Skan	selwakeuppri(&sc->rcv_select, PRIBIO);
3267169689Skan	mtx_unlock(&sc->aac_aifq_lock);
3268169689Skan
3269169689Skan	return;
3270169689Skan}
3271169689Skan
3272169689Skan/*
3273169689Skan * Return the Revision of the driver to userspace and check to see if the
3274169689Skan * userspace app is possibly compatible.  This is extremely bogus since
3275169689Skan * our driver doesn't follow Adaptec's versioning system.  Cheat by just
3276169689Skan * returning what the card reported.
3277169689Skan */
3278169689Skanstatic int
3279169689Skanaac_rev_check(struct aac_softc *sc, caddr_t udata)
3280169689Skan{
3281169689Skan	struct aac_rev_check rev_check;
3282169689Skan	struct aac_rev_check_resp rev_check_resp;
3283169689Skan	int error = 0;
3284169689Skan
3285169689Skan	debug_called(2);
3286169689Skan
3287169689Skan	/*
3288169689Skan	 * Copyin the revision struct from userspace
3289169689Skan	 */
3290169689Skan	if ((error = copyin(udata, (caddr_t)&rev_check,
3291169689Skan			sizeof(struct aac_rev_check))) != 0) {
3292169689Skan		return error;
3293169689Skan	}
3294169689Skan
3295169689Skan	debug(2, "Userland revision= %d\n",
3296169689Skan	      rev_check.callingRevision.buildNumber);
3297169689Skan
3298169689Skan	/*
3299169689Skan	 * Doctor up the response struct.
3300169689Skan	 */
3301169689Skan	rev_check_resp.possiblyCompatible = 1;
3302169689Skan	rev_check_resp.adapterSWRevision.external.ul =
3303169689Skan	    sc->aac_revision.external.ul;
3304169689Skan	rev_check_resp.adapterSWRevision.buildNumber =
3305169689Skan	    sc->aac_revision.buildNumber;
3306169689Skan
3307169689Skan	return(copyout((caddr_t)&rev_check_resp, udata,
3308169689Skan			sizeof(struct aac_rev_check_resp)));
3309169689Skan}
3310169689Skan
3311169689Skan/*
3312169689Skan * Pass the fib context to the caller
3313169689Skan */
3314169689Skanstatic int
3315169689Skanaac_open_aif(struct aac_softc *sc, caddr_t arg)
3316169689Skan{
3317169689Skan	struct aac_fib_context *fibctx, *ctx;
3318169689Skan	int error = 0;
3319169689Skan
3320169689Skan	debug_called(2);
3321169689Skan
3322169689Skan	fibctx = malloc(sizeof(struct aac_fib_context), M_AACBUF, M_NOWAIT|M_ZERO);
3323169689Skan	if (fibctx == NULL)
3324169689Skan		return (ENOMEM);
3325169689Skan
3326169689Skan	mtx_lock(&sc->aac_aifq_lock);
3327169689Skan	/* all elements are already 0, add to queue */
3328169689Skan	if (sc->fibctx == NULL)
3329169689Skan		sc->fibctx = fibctx;
3330169689Skan	else {
3331169689Skan		for (ctx = sc->fibctx; ctx->next; ctx = ctx->next)
3332169689Skan			;
3333169689Skan		ctx->next = fibctx;
3334169689Skan		fibctx->prev = ctx;
3335169689Skan	}
3336169689Skan
3337169689Skan	/* evaluate unique value */
3338169689Skan	fibctx->unique = (*(u_int32_t *)&fibctx & 0xffffffff);
3339169689Skan	ctx = sc->fibctx;
3340169689Skan	while (ctx != fibctx) {
3341169689Skan		if (ctx->unique == fibctx->unique) {
3342169689Skan			fibctx->unique++;
3343169689Skan			ctx = sc->fibctx;
3344169689Skan		} else {
3345169689Skan			ctx = ctx->next;
3346169689Skan		}
3347169689Skan	}
3348169689Skan	mtx_unlock(&sc->aac_aifq_lock);
3349169689Skan
3350169689Skan	error = copyout(&fibctx->unique, (void *)arg, sizeof(u_int32_t));
3351169689Skan	if (error)
3352169689Skan		aac_close_aif(sc, (caddr_t)ctx);
3353169689Skan	return error;
3354169689Skan}
3355169689Skan
3356169689Skan/*
3357169689Skan * Close the caller's fib context
3358169689Skan */
3359169689Skanstatic int
3360169689Skanaac_close_aif(struct aac_softc *sc, caddr_t arg)
3361169689Skan{
3362169689Skan	struct aac_fib_context *ctx;
3363169689Skan
3364169689Skan	debug_called(2);
3365169689Skan
3366169689Skan	mtx_lock(&sc->aac_aifq_lock);
3367169689Skan	for (ctx = sc->fibctx; ctx; ctx = ctx->next) {
3368169689Skan		if (ctx->unique == *(uint32_t *)&arg) {
3369169689Skan			if (ctx == sc->fibctx)
3370169689Skan				sc->fibctx = NULL;
3371169689Skan			else {
3372169689Skan				ctx->prev->next = ctx->next;
3373169689Skan				if (ctx->next)
3374169689Skan					ctx->next->prev = ctx->prev;
3375169689Skan			}
3376169689Skan			break;
3377169689Skan		}
3378169689Skan	}
3379169689Skan	mtx_unlock(&sc->aac_aifq_lock);
3380169689Skan	if (ctx)
3381169689Skan		free(ctx, M_AACBUF);
3382169689Skan
3383169689Skan	return 0;
3384169689Skan}
3385169689Skan
3386169689Skan/*
3387169689Skan * Pass the caller the next AIF in their queue
3388169689Skan */
3389169689Skanstatic int
3390169689Skanaac_getnext_aif(struct aac_softc *sc, caddr_t arg)
3391169689Skan{
3392169689Skan	struct get_adapter_fib_ioctl agf;
3393169689Skan	struct aac_fib_context *ctx;
3394169689Skan	int error;
3395169689Skan
3396169689Skan	debug_called(2);
3397169689Skan
3398169689Skan	if ((error = copyin(arg, &agf, sizeof(agf))) == 0) {
3399169689Skan		for (ctx = sc->fibctx; ctx; ctx = ctx->next) {
3400169689Skan			if (agf.AdapterFibContext == ctx->unique)
3401169689Skan				break;
3402169689Skan		}
3403169689Skan		if (!ctx)
3404169689Skan			return (EFAULT);
3405169689Skan
3406169689Skan		error = aac_return_aif(sc, ctx, agf.AifFib);
3407169689Skan		if (error == EAGAIN && agf.Wait) {
3408169689Skan			debug(2, "aac_getnext_aif(): waiting for AIF");
3409169689Skan			sc->aac_state |= AAC_STATE_AIF_SLEEPER;
3410169689Skan			while (error == EAGAIN) {
3411169689Skan				error = tsleep(sc->aac_aifq, PRIBIO |
3412169689Skan					       PCATCH, "aacaif", 0);
3413169689Skan				if (error == 0)
3414169689Skan					error = aac_return_aif(sc, ctx, agf.AifFib);
3415169689Skan			}
3416169689Skan			sc->aac_state &= ~AAC_STATE_AIF_SLEEPER;
3417169689Skan		}
3418169689Skan	}
3419169689Skan	return(error);
3420169689Skan}
3421169689Skan
3422169689Skan/*
3423169689Skan * Hand the next AIF off the top of the queue out to userspace.
3424169689Skan */
3425169689Skanstatic int
3426169689Skanaac_return_aif(struct aac_softc *sc, struct aac_fib_context *ctx, caddr_t uptr)
3427169689Skan{
3428169689Skan	int current, error;
3429169689Skan
3430169689Skan	debug_called(2);
3431169689Skan
3432169689Skan	mtx_lock(&sc->aac_aifq_lock);
3433169689Skan	current = ctx->ctx_idx;
3434169689Skan	if (current == sc->aifq_idx && !ctx->ctx_wrap) {
3435169689Skan		/* empty */
3436169689Skan		mtx_unlock(&sc->aac_aifq_lock);
3437169689Skan		return (EAGAIN);
3438169689Skan	}
3439169689Skan	error =
3440169689Skan		copyout(&sc->aac_aifq[current], (void *)uptr, sizeof(struct aac_fib));
3441169689Skan	if (error)
3442169689Skan		device_printf(sc->aac_dev,
3443169689Skan		    "aac_return_aif: copyout returned %d\n", error);
3444169689Skan	else {
3445169689Skan		ctx->ctx_wrap = 0;
3446169689Skan		ctx->ctx_idx = (current + 1) % AAC_AIFQ_LENGTH;
3447169689Skan	}
3448169689Skan	mtx_unlock(&sc->aac_aifq_lock);
3449169689Skan	return(error);
3450169689Skan}
3451169689Skan
3452169689Skanstatic int
3453169689Skanaac_get_pci_info(struct aac_softc *sc, caddr_t uptr)
3454169689Skan{
3455169689Skan	struct aac_pci_info {
3456169689Skan		u_int32_t bus;
3457169689Skan		u_int32_t slot;
3458169689Skan	} pciinf;
3459169689Skan	int error;
3460169689Skan
3461169689Skan	debug_called(2);
3462169689Skan
3463169689Skan	pciinf.bus = pci_get_bus(sc->aac_dev);
3464169689Skan	pciinf.slot = pci_get_slot(sc->aac_dev);
3465169689Skan
3466169689Skan	error = copyout((caddr_t)&pciinf, uptr,
3467169689Skan			sizeof(struct aac_pci_info));
3468169689Skan
3469169689Skan	return (error);
3470169689Skan}
3471169689Skan
3472169689Skan/*
3473169689Skan * Give the userland some information about the container.  The AAC arch
3474169689Skan * expects the driver to be a SCSI passthrough type driver, so it expects
3475169689Skan * the containers to have b:t:l numbers.  Fake it.
3476169689Skan */
3477169689Skanstatic int
3478169689Skanaac_query_disk(struct aac_softc *sc, caddr_t uptr)
3479169689Skan{
3480169689Skan	struct aac_query_disk query_disk;
3481169689Skan	struct aac_container *co;
3482169689Skan	struct aac_disk	*disk;
3483169689Skan	int error, id;
3484169689Skan
3485169689Skan	debug_called(2);
3486169689Skan
3487169689Skan	disk = NULL;
3488169689Skan
3489169689Skan	error = copyin(uptr, (caddr_t)&query_disk,
3490169689Skan		       sizeof(struct aac_query_disk));
3491169689Skan	if (error)
3492169689Skan		return (error);
3493169689Skan
3494169689Skan	id = query_disk.ContainerNumber;
3495169689Skan	if (id == -1)
3496169689Skan		return (EINVAL);
3497169689Skan
3498169689Skan	mtx_lock(&sc->aac_container_lock);
3499169689Skan	TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) {
3500169689Skan		if (co->co_mntobj.ObjectId == id)
3501169689Skan			break;
3502169689Skan		}
3503169689Skan
3504169689Skan	if (co == NULL) {
3505169689Skan			query_disk.Valid = 0;
3506169689Skan			query_disk.Locked = 0;
3507169689Skan			query_disk.Deleted = 1;		/* XXX is this right? */
3508169689Skan	} else {
3509169689Skan		disk = device_get_softc(co->co_disk);
3510169689Skan		query_disk.Valid = 1;
3511169689Skan		query_disk.Locked =
3512169689Skan		    (disk->ad_flags & AAC_DISK_OPEN) ? 1 : 0;
3513169689Skan		query_disk.Deleted = 0;
3514169689Skan		query_disk.Bus = device_get_unit(sc->aac_dev);
3515169689Skan		query_disk.Target = disk->unit;
3516169689Skan		query_disk.Lun = 0;
3517169689Skan		query_disk.UnMapped = 0;
3518169689Skan		sprintf(&query_disk.diskDeviceName[0], "%s%d",
3519169689Skan		        disk->ad_disk->d_name, disk->ad_disk->d_unit);
3520169689Skan	}
3521169689Skan	mtx_unlock(&sc->aac_container_lock);
3522169689Skan
3523169689Skan	error = copyout((caddr_t)&query_disk, uptr,
3524169689Skan			sizeof(struct aac_query_disk));
3525169689Skan
3526169689Skan	return (error);
3527169689Skan}
3528169689Skan
3529169689Skanstatic void
3530169689Skanaac_get_bus_info(struct aac_softc *sc)
3531169689Skan{
3532169689Skan	struct aac_fib *fib;
3533169689Skan	struct aac_ctcfg *c_cmd;
3534169689Skan	struct aac_ctcfg_resp *c_resp;
3535169689Skan	struct aac_vmioctl *vmi;
3536169689Skan	struct aac_vmi_businf_resp *vmi_resp;
3537169689Skan	struct aac_getbusinf businfo;
3538169689Skan	struct aac_sim *caminf;
3539169689Skan	device_t child;
3540169689Skan	int i, found, error;
3541169689Skan
3542169689Skan	mtx_lock(&sc->aac_io_lock);
3543169689Skan	aac_alloc_sync_fib(sc, &fib);
3544169689Skan	c_cmd = (struct aac_ctcfg *)&fib->data[0];
3545169689Skan	bzero(c_cmd, sizeof(struct aac_ctcfg));
3546169689Skan
3547169689Skan	c_cmd->Command = VM_ContainerConfig;
3548169689Skan	c_cmd->cmd = CT_GET_SCSI_METHOD;
3549169689Skan	c_cmd->param = 0;
3550169689Skan
3551169689Skan	error = aac_sync_fib(sc, ContainerCommand, 0, fib,
3552169689Skan	    sizeof(struct aac_ctcfg));
3553169689Skan	if (error) {
3554169689Skan		device_printf(sc->aac_dev, "Error %d sending "
3555169689Skan		    "VM_ContainerConfig command\n", error);
3556169689Skan		aac_release_sync_fib(sc);
3557169689Skan		mtx_unlock(&sc->aac_io_lock);
3558169689Skan		return;
3559169689Skan	}
3560169689Skan
3561169689Skan	c_resp = (struct aac_ctcfg_resp *)&fib->data[0];
3562169689Skan	if (c_resp->Status != ST_OK) {
3563169689Skan		device_printf(sc->aac_dev, "VM_ContainerConfig returned 0x%x\n",
3564169689Skan		    c_resp->Status);
3565169689Skan		aac_release_sync_fib(sc);
3566169689Skan		mtx_unlock(&sc->aac_io_lock);
3567169689Skan		return;
3568169689Skan	}
3569169689Skan
3570169689Skan	sc->scsi_method_id = c_resp->param;
3571169689Skan
3572169689Skan	vmi = (struct aac_vmioctl *)&fib->data[0];
3573169689Skan	bzero(vmi, sizeof(struct aac_vmioctl));
3574169689Skan
3575169689Skan	vmi->Command = VM_Ioctl;
3576169689Skan	vmi->ObjType = FT_DRIVE;
3577169689Skan	vmi->MethId = sc->scsi_method_id;
3578169689Skan	vmi->ObjId = 0;
3579169689Skan	vmi->IoctlCmd = GetBusInfo;
3580169689Skan
3581169689Skan	error = aac_sync_fib(sc, ContainerCommand, 0, fib,
3582169689Skan	    sizeof(struct aac_vmioctl));
3583169689Skan	if (error) {
3584169689Skan		device_printf(sc->aac_dev, "Error %d sending VMIoctl command\n",
3585169689Skan		    error);
3586169689Skan		aac_release_sync_fib(sc);
3587169689Skan		mtx_unlock(&sc->aac_io_lock);
3588169689Skan		return;
3589169689Skan	}
3590169689Skan
3591169689Skan	vmi_resp = (struct aac_vmi_businf_resp *)&fib->data[0];
3592169689Skan	if (vmi_resp->Status != ST_OK) {
3593169689Skan		device_printf(sc->aac_dev, "VM_Ioctl returned %d\n",
3594169689Skan		    vmi_resp->Status);
3595169689Skan		aac_release_sync_fib(sc);
3596169689Skan		mtx_unlock(&sc->aac_io_lock);
3597169689Skan		return;
3598169689Skan	}
3599169689Skan
3600169689Skan	bcopy(&vmi_resp->BusInf, &businfo, sizeof(struct aac_getbusinf));
3601169689Skan	aac_release_sync_fib(sc);
3602169689Skan	mtx_unlock(&sc->aac_io_lock);
3603169689Skan
3604169689Skan	found = 0;
3605169689Skan	for (i = 0; i < businfo.BusCount; i++) {
3606169689Skan		if (businfo.BusValid[i] != AAC_BUS_VALID)
3607169689Skan			continue;
3608169689Skan
3609169689Skan		caminf = (struct aac_sim *)malloc( sizeof(struct aac_sim),
3610169689Skan		    M_AACBUF, M_NOWAIT | M_ZERO);
3611169689Skan		if (caminf == NULL) {
3612169689Skan			device_printf(sc->aac_dev,
3613169689Skan			    "No memory to add passthrough bus %d\n", i);
3614169689Skan			break;
3615169689Skan		};
3616169689Skan
3617169689Skan		child = device_add_child(sc->aac_dev, "aacp", -1);
3618169689Skan		if (child == NULL) {
3619169689Skan			device_printf(sc->aac_dev,
3620169689Skan			    "device_add_child failed for passthrough bus %d\n",
3621169689Skan			    i);
3622169689Skan			free(caminf, M_AACBUF);
3623169689Skan			break;
3624169689Skan		}
3625169689Skan
3626169689Skan		caminf->TargetsPerBus = businfo.TargetsPerBus;
3627169689Skan		caminf->BusNumber = i;
3628169689Skan		caminf->InitiatorBusId = businfo.InitiatorBusId[i];
3629169689Skan		caminf->aac_sc = sc;
3630169689Skan		caminf->sim_dev = child;
3631169689Skan
3632169689Skan		device_set_ivars(child, caminf);
3633169689Skan		device_set_desc(child, "SCSI Passthrough Bus");
3634169689Skan		TAILQ_INSERT_TAIL(&sc->aac_sim_tqh, caminf, sim_link);
3635169689Skan
3636169689Skan		found = 1;
3637169689Skan	}
3638169689Skan
3639169689Skan	if (found)
3640169689Skan		bus_generic_attach(sc->aac_dev);
3641169689Skan
3642169689Skan	return;
3643169689Skan}
3644169689Skan