xref: /netbsd-src/sys/dev/pci/aac_pci.c (revision 13d4bb4cc874de96add7fc4227d38a1d656b03d1)
1*13d4bb4cSthorpej /*	$NetBSD: aac_pci.c,v 1.42 2022/09/25 17:52:25 thorpej Exp $	*/
277e08f05Sad 
377e08f05Sad /*-
477e08f05Sad  * Copyright (c) 2002 The NetBSD Foundation, Inc.
577e08f05Sad  * All rights reserved.
677e08f05Sad  *
777e08f05Sad  * This code is derived from software contributed to The NetBSD Foundation
877e08f05Sad  * by Andrew Doran.
977e08f05Sad  *
1077e08f05Sad  * Redistribution and use in source and binary forms, with or without
1177e08f05Sad  * modification, are permitted provided that the following conditions
1277e08f05Sad  * are met:
1377e08f05Sad  * 1. Redistributions of source code must retain the above copyright
1477e08f05Sad  *    notice, this list of conditions and the following disclaimer.
1577e08f05Sad  * 2. Redistributions in binary form must reproduce the above copyright
1677e08f05Sad  *    notice, this list of conditions and the following disclaimer in the
1777e08f05Sad  *    documentation and/or other materials provided with the distribution.
1877e08f05Sad  *
1977e08f05Sad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2077e08f05Sad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2177e08f05Sad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2277e08f05Sad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2377e08f05Sad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2477e08f05Sad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2577e08f05Sad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2677e08f05Sad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2777e08f05Sad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2877e08f05Sad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2977e08f05Sad  * POSSIBILITY OF SUCH DAMAGE.
3077e08f05Sad  */
3177e08f05Sad 
3277e08f05Sad /*-
3377e08f05Sad  * Copyright (c) 2000 Michael Smith
3477e08f05Sad  * Copyright (c) 2000 BSDi
3577e08f05Sad  * Copyright (c) 2000 Niklas Hallqvist
3677e08f05Sad  * All rights reserved.
3777e08f05Sad  *
3877e08f05Sad  * Redistribution and use in source and binary forms, with or without
3977e08f05Sad  * modification, are permitted provided that the following conditions
4077e08f05Sad  * are met:
4177e08f05Sad  * 1. Redistributions of source code must retain the above copyright
4277e08f05Sad  *    notice, this list of conditions and the following disclaimer.
4377e08f05Sad  * 2. Redistributions in binary form must reproduce the above copyright
4477e08f05Sad  *    notice, this list of conditions and the following disclaimer in the
4577e08f05Sad  *    documentation and/or other materials provided with the distribution.
4677e08f05Sad  *
4777e08f05Sad  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4877e08f05Sad  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4977e08f05Sad  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5077e08f05Sad  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
5177e08f05Sad  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5277e08f05Sad  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5377e08f05Sad  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5477e08f05Sad  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5577e08f05Sad  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5677e08f05Sad  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5777e08f05Sad  * SUCH DAMAGE.
5877e08f05Sad  *
5977e08f05Sad  * from FreeBSD: aac_pci.c,v 1.1 2000/09/13 03:20:34 msmith Exp
6077e08f05Sad  * via OpenBSD: aac_pci.c,v 1.7 2002/03/14 01:26:58 millert Exp
6177e08f05Sad  */
6277e08f05Sad 
6377e08f05Sad /*
6477e08f05Sad  * PCI front-end for the `aac' driver.
6577e08f05Sad  */
6677e08f05Sad 
6777e08f05Sad #include <sys/cdefs.h>
68*13d4bb4cSthorpej __KERNEL_RCSID(0, "$NetBSD: aac_pci.c,v 1.42 2022/09/25 17:52:25 thorpej Exp $");
6977e08f05Sad 
7077e08f05Sad #include <sys/param.h>
7177e08f05Sad #include <sys/systm.h>
7277e08f05Sad #include <sys/device.h>
7377e08f05Sad #include <sys/kernel.h>
7477e08f05Sad #include <sys/queue.h>
7577e08f05Sad 
76a2a38285Sad #include <sys/bus.h>
7777e08f05Sad #include <machine/endian.h>
78a2a38285Sad #include <sys/intr.h>
7977e08f05Sad 
8077e08f05Sad #include <dev/pci/pcidevs.h>
8177e08f05Sad #include <dev/pci/pcireg.h>
8277e08f05Sad #include <dev/pci/pcivar.h>
8377e08f05Sad 
8477e08f05Sad #include <dev/ic/aacreg.h>
8577e08f05Sad #include <dev/ic/aacvar.h>
8677e08f05Sad 
87f82d990bSbriggs struct aac_pci_softc {
88f82d990bSbriggs 	struct aac_softc	sc_aac;
89f82d990bSbriggs 	pci_chipset_tag_t	sc_pc;
90f82d990bSbriggs 	pci_intr_handle_t	sc_ih;
91f82d990bSbriggs };
92f82d990bSbriggs 
9377e08f05Sad /* i960Rx interface */
94d36c43c5Sthorpej static int	aac_rx_get_fwstatus(struct aac_softc *);
95d36c43c5Sthorpej static void	aac_rx_qnotify(struct aac_softc *, int);
96d36c43c5Sthorpej static int	aac_rx_get_istatus(struct aac_softc *);
97d36c43c5Sthorpej static void	aac_rx_clear_istatus(struct aac_softc *, int);
98d36c43c5Sthorpej static void	aac_rx_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
9977e08f05Sad 			   u_int32_t, u_int32_t, u_int32_t);
100d36c43c5Sthorpej static uint32_t aac_rx_get_mailbox(struct aac_softc *, int);
101d36c43c5Sthorpej static void	aac_rx_set_interrupts(struct aac_softc *, int);
102f82d990bSbriggs static int	aac_rx_send_command(struct aac_softc *, struct aac_ccb *);
103f82d990bSbriggs static int	aac_rx_get_outb_queue(struct aac_softc *);
104f82d990bSbriggs static void	aac_rx_set_outb_queue(struct aac_softc *, int);
10577e08f05Sad 
10677e08f05Sad /* StrongARM interface */
107d36c43c5Sthorpej static int	aac_sa_get_fwstatus(struct aac_softc *);
108d36c43c5Sthorpej static void	aac_sa_qnotify(struct aac_softc *, int);
109d36c43c5Sthorpej static int	aac_sa_get_istatus(struct aac_softc *);
110d36c43c5Sthorpej static void	aac_sa_clear_istatus(struct aac_softc *, int);
111d36c43c5Sthorpej static void	aac_sa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
11277e08f05Sad 			   u_int32_t, u_int32_t, u_int32_t);
113d36c43c5Sthorpej static uint32_t aac_sa_get_mailbox(struct aac_softc *, int);
114d36c43c5Sthorpej static void	aac_sa_set_interrupts(struct aac_softc *, int);
11577e08f05Sad 
116f82d990bSbriggs /* Rocket/MIPS interface */
117f82d990bSbriggs static int	aac_rkt_get_fwstatus(struct aac_softc *);
118f82d990bSbriggs static void	aac_rkt_qnotify(struct aac_softc *, int);
119f82d990bSbriggs static int	aac_rkt_get_istatus(struct aac_softc *);
120f82d990bSbriggs static void	aac_rkt_clear_istatus(struct aac_softc *, int);
121f82d990bSbriggs static void	aac_rkt_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
122f82d990bSbriggs 			   u_int32_t, u_int32_t, u_int32_t);
123f82d990bSbriggs static uint32_t aac_rkt_get_mailbox(struct aac_softc *, int);
124f82d990bSbriggs static void	aac_rkt_set_interrupts(struct aac_softc *, int);
125f82d990bSbriggs static int	aac_rkt_send_command(struct aac_softc *, struct aac_ccb *);
126f82d990bSbriggs static int	aac_rkt_get_outb_queue(struct aac_softc *);
127f82d990bSbriggs static void	aac_rkt_set_outb_queue(struct aac_softc *, int);
128f82d990bSbriggs 
129d36c43c5Sthorpej static const struct aac_interface aac_rx_interface = {
13077e08f05Sad 	aac_rx_get_fwstatus,
13177e08f05Sad 	aac_rx_qnotify,
13277e08f05Sad 	aac_rx_get_istatus,
13377e08f05Sad 	aac_rx_clear_istatus,
13477e08f05Sad 	aac_rx_set_mailbox,
13580240054Sbriggs 	aac_rx_get_mailbox,
136f82d990bSbriggs 	aac_rx_set_interrupts,
137f82d990bSbriggs 	aac_rx_send_command,
138f82d990bSbriggs 	aac_rx_get_outb_queue,
139f82d990bSbriggs 	aac_rx_set_outb_queue
14077e08f05Sad };
14177e08f05Sad 
142d36c43c5Sthorpej static const struct aac_interface aac_sa_interface = {
14377e08f05Sad 	aac_sa_get_fwstatus,
14477e08f05Sad 	aac_sa_qnotify,
14577e08f05Sad 	aac_sa_get_istatus,
14677e08f05Sad 	aac_sa_clear_istatus,
14777e08f05Sad 	aac_sa_set_mailbox,
14880240054Sbriggs 	aac_sa_get_mailbox,
149f82d990bSbriggs 	aac_sa_set_interrupts,
150f82d990bSbriggs 	NULL, NULL, NULL
151f82d990bSbriggs };
152f82d990bSbriggs 
153f82d990bSbriggs static const struct aac_interface aac_rkt_interface = {
154f82d990bSbriggs 	aac_rkt_get_fwstatus,
155f82d990bSbriggs 	aac_rkt_qnotify,
156f82d990bSbriggs 	aac_rkt_get_istatus,
157f82d990bSbriggs 	aac_rkt_clear_istatus,
158f82d990bSbriggs 	aac_rkt_set_mailbox,
159f82d990bSbriggs 	aac_rkt_get_mailbox,
160f82d990bSbriggs 	aac_rkt_set_interrupts,
161f82d990bSbriggs 	aac_rkt_send_command,
162f82d990bSbriggs 	aac_rkt_get_outb_queue,
163f82d990bSbriggs 	aac_rkt_set_outb_queue
16477e08f05Sad };
16577e08f05Sad 
1662735c718Schristos static struct aac_ident {
16777e08f05Sad 	u_short	vendor;
16877e08f05Sad 	u_short	device;
16977e08f05Sad 	u_short	subvendor;
17077e08f05Sad 	u_short	subdevice;
17177e08f05Sad 	u_short	hwif;
17277e08f05Sad 	u_short	quirks;
17377e08f05Sad 	const char	*prodstr;
1742735c718Schristos } const aac_ident[] = {
17577e08f05Sad 	{
17677e08f05Sad 		PCI_VENDOR_DELL,
17777e08f05Sad 		PCI_PRODUCT_DELL_PERC_2SI,
17877e08f05Sad 		PCI_VENDOR_DELL,
17977e08f05Sad 		PCI_PRODUCT_DELL_PERC_2SI,
18077e08f05Sad 		AAC_HWIF_I960RX,
18177e08f05Sad 		0,
18277e08f05Sad 		"Dell PERC 2/Si"
18377e08f05Sad 	},
18477e08f05Sad 	{
18577e08f05Sad 		PCI_VENDOR_DELL,
18677e08f05Sad 		PCI_PRODUCT_DELL_PERC_3DI,
18777e08f05Sad 		PCI_VENDOR_DELL,
18877e08f05Sad 		PCI_PRODUCT_DELL_PERC_3DI,
18977e08f05Sad 		AAC_HWIF_I960RX,
19077e08f05Sad 		0,
19177e08f05Sad 		"Dell PERC 3/Di"
19277e08f05Sad 	},
19377e08f05Sad 	{
19477e08f05Sad 		PCI_VENDOR_DELL,
19577e08f05Sad 		PCI_PRODUCT_DELL_PERC_3DI,
19677e08f05Sad 		PCI_VENDOR_DELL,
19777e08f05Sad 		PCI_PRODUCT_DELL_PERC_3DI_SUB2,
19877e08f05Sad 		AAC_HWIF_I960RX,
19977e08f05Sad 		0,
20077e08f05Sad 		"Dell PERC 3/Di"
20177e08f05Sad 	},
20277e08f05Sad 	{
20377e08f05Sad 		PCI_VENDOR_DELL,
20477e08f05Sad 		PCI_PRODUCT_DELL_PERC_3DI,
20577e08f05Sad 		PCI_VENDOR_DELL,
20677e08f05Sad 		PCI_PRODUCT_DELL_PERC_3DI_SUB3,
20777e08f05Sad 		AAC_HWIF_I960RX,
20877e08f05Sad 		0,
20977e08f05Sad 		"Dell PERC 3/Di"
21077e08f05Sad 	},
21177e08f05Sad 	{
21277e08f05Sad 		PCI_VENDOR_DELL,
21377e08f05Sad 		PCI_PRODUCT_DELL_PERC_3DI_2,
21477e08f05Sad 		PCI_VENDOR_DELL,
21577e08f05Sad 		PCI_PRODUCT_DELL_PERC_3DI_2_SUB,
21677e08f05Sad 		AAC_HWIF_I960RX,
21777e08f05Sad 		0,
21877e08f05Sad 		"Dell PERC 3/Di"
21977e08f05Sad 	},
22077e08f05Sad         {
22177e08f05Sad 		PCI_VENDOR_DELL,
2227416434aSad 		PCI_PRODUCT_DELL_PERC_3DI_3,
2237416434aSad 		PCI_VENDOR_DELL,
2247416434aSad 		PCI_PRODUCT_DELL_PERC_3DI_3_SUB,
2257416434aSad 		AAC_HWIF_I960RX,
2267416434aSad 		0,
2277416434aSad 		"Dell PERC 3/Di"
2287416434aSad 	},
2297416434aSad 	{
2307416434aSad 		PCI_VENDOR_DELL,
2317416434aSad 		PCI_PRODUCT_DELL_PERC_3DI_3,
2327416434aSad 		PCI_VENDOR_DELL,
2337416434aSad 		PCI_PRODUCT_DELL_PERC_3DI_3_SUB2,
2347416434aSad 		AAC_HWIF_I960RX,
2357416434aSad 		0,
2367416434aSad 		"Dell PERC 3/Di"
2377416434aSad 	},
2387416434aSad 	{
2397416434aSad 		PCI_VENDOR_DELL,
2407416434aSad 		PCI_PRODUCT_DELL_PERC_3DI_3,
2417416434aSad 		PCI_VENDOR_DELL,
2427416434aSad 		PCI_PRODUCT_DELL_PERC_3DI_3_SUB3,
2437416434aSad 		AAC_HWIF_I960RX,
2447416434aSad 		0,
2457416434aSad 		"Dell PERC 3/Di"
2467416434aSad 	},
2477416434aSad 	{
2487416434aSad 		PCI_VENDOR_DELL,
24977e08f05Sad 		PCI_PRODUCT_DELL_PERC_3SI,
25077e08f05Sad 		PCI_VENDOR_DELL,
25177e08f05Sad 		PCI_PRODUCT_DELL_PERC_3SI,
25277e08f05Sad 		AAC_HWIF_I960RX,
25377e08f05Sad 		0,
25477e08f05Sad 		"Dell PERC 3/Si"
25577e08f05Sad 	},
25677e08f05Sad 	{
25777e08f05Sad 		PCI_VENDOR_DELL,
25877e08f05Sad 		PCI_PRODUCT_DELL_PERC_3SI_2,
25977e08f05Sad 		PCI_VENDOR_DELL,
26077e08f05Sad 		PCI_PRODUCT_DELL_PERC_3SI_2_SUB,
26177e08f05Sad 		AAC_HWIF_I960RX,
26277e08f05Sad 		0,
26377e08f05Sad 		"Dell PERC 3/Si"
26477e08f05Sad 	},
26577e08f05Sad 	{
26677e08f05Sad 		PCI_VENDOR_ADP2,
2676fe6af80Smartti 		PCI_PRODUCT_ADP2_ASR2200S,
2686fe6af80Smartti 		PCI_VENDOR_DELL,
2696fe6af80Smartti 		PCI_PRODUCT_DELL_CERC_1_5,
2706fe6af80Smartti 		AAC_HWIF_I960RX,
2716fe6af80Smartti 		AAC_QUIRK_NO4GB,
2726fe6af80Smartti 		"Dell CERC SATA RAID 1.5/6ch"
2736fe6af80Smartti 	},
2746fe6af80Smartti 	{
2756fe6af80Smartti 		PCI_VENDOR_ADP2,
27677e08f05Sad 		PCI_PRODUCT_ADP2_AAC2622,
27777e08f05Sad 		PCI_VENDOR_ADP2,
27877e08f05Sad 		PCI_PRODUCT_ADP2_AAC2622,
27977e08f05Sad 		AAC_HWIF_I960RX,
28077e08f05Sad 		0,
28177e08f05Sad 		"Adaptec ADP-2622"
28277e08f05Sad 	},
28377e08f05Sad 	{
28477e08f05Sad 		PCI_VENDOR_ADP2,
28577e08f05Sad 		PCI_PRODUCT_ADP2_ASR2200S,
28677e08f05Sad 		PCI_VENDOR_ADP2,
287c2db9e9cSgendalia 		PCI_PRODUCT_ADP2_ASR2200S_SUB2M,
288c2db9e9cSgendalia 		AAC_HWIF_I960RX,
289f82d990bSbriggs 		AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS,
290c2db9e9cSgendalia 		"Adaptec ASR-2200S"
291c2db9e9cSgendalia 	},
292c2db9e9cSgendalia 	{
293c2db9e9cSgendalia 		PCI_VENDOR_ADP2,
294c2db9e9cSgendalia 		PCI_PRODUCT_ADP2_ASR2200S,
295c2db9e9cSgendalia 		PCI_VENDOR_DELL,
296c2db9e9cSgendalia 		PCI_PRODUCT_ADP2_ASR2200S_SUB2M,
297c2db9e9cSgendalia 		AAC_HWIF_I960RX,
298f82d990bSbriggs 		AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS,
299c2db9e9cSgendalia 		"Dell PERC 320/DC"
300c2db9e9cSgendalia 	},
301c2db9e9cSgendalia 	{
302c2db9e9cSgendalia 		PCI_VENDOR_ADP2,
303c2db9e9cSgendalia 		PCI_PRODUCT_ADP2_ASR2200S,
304c2db9e9cSgendalia 		PCI_VENDOR_ADP2,
30577e08f05Sad 		PCI_PRODUCT_ADP2_ASR2200S,
30677e08f05Sad 		AAC_HWIF_I960RX,
307f82d990bSbriggs 		AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS,
30877e08f05Sad 		"Adaptec ASR-2200S"
30977e08f05Sad 	},
31077e08f05Sad 	{
31177e08f05Sad 		PCI_VENDOR_ADP2,
31277e08f05Sad 		PCI_PRODUCT_ADP2_ASR2200S,
31377e08f05Sad 		PCI_VENDOR_ADP2,
3144ff7407fSgendalia 		PCI_PRODUCT_ADP2_AAR2810SA,
3154ff7407fSgendalia 		AAC_HWIF_I960RX,
316f82d990bSbriggs 		AAC_QUIRK_NO4GB,
3174ff7407fSgendalia 		"Adaptec AAR-2810SA"
3184ff7407fSgendalia 	},
3194ff7407fSgendalia 	{
3204ff7407fSgendalia 		PCI_VENDOR_ADP2,
3214ff7407fSgendalia 		PCI_PRODUCT_ADP2_ASR2200S,
3224ff7407fSgendalia 		PCI_VENDOR_ADP2,
32377e08f05Sad 		PCI_PRODUCT_ADP2_ASR2120S,
32477e08f05Sad 		AAC_HWIF_I960RX,
325f82d990bSbriggs 		AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS,
32677e08f05Sad 		"Adaptec ASR-2120S"
32777e08f05Sad 	},
32877e08f05Sad 	{
329fb0f2441Sjdolecek 		PCI_VENDOR_ADP2,
330fb0f2441Sjdolecek 		PCI_PRODUCT_ADP2_ASR2200S,
331fb0f2441Sjdolecek 		PCI_VENDOR_ADP2,
332a1b0a426Stron 		PCI_PRODUCT_ADP2_ASR2410SA,
333fb0f2441Sjdolecek 		AAC_HWIF_I960RX,
334f82d990bSbriggs 		AAC_QUIRK_NO4GB,
335fb0f2441Sjdolecek 		"Adaptec ASR-2410SA"
336fb0f2441Sjdolecek 	},
337fb0f2441Sjdolecek 	{
338e8381a07Schristos 		PCI_VENDOR_ADP2,
339e8381a07Schristos 		PCI_PRODUCT_ADP2_ASR2200S,
340e8381a07Schristos 		PCI_VENDOR_HP,
341e8381a07Schristos 		PCI_PRODUCT_ADP2_HP_M110_G2,
342e8381a07Schristos 		AAC_HWIF_I960RX,
343f82d990bSbriggs 		AAC_QUIRK_NO4GB,
344e8381a07Schristos 		"HP ML110 G2 (Adaptec ASR-2610SA)"
345e8381a07Schristos 	},
346e8381a07Schristos 	{
347cfe5fff0Ssborrill 		PCI_VENDOR_ADP2,
348cfe5fff0Ssborrill 		PCI_PRODUCT_ADP2_ASR2120S,
349cfe5fff0Ssborrill 		PCI_VENDOR_IBM,
350cfe5fff0Ssborrill 		PCI_PRODUCT_IBM_SERVERAID8K,
351cfe5fff0Ssborrill 		AAC_HWIF_RKT,
352cfe5fff0Ssborrill 		0,
353cfe5fff0Ssborrill 		"IBM ServeRAID 8k"
354cfe5fff0Ssborrill 	},
35556e0e00bSjmcneill 	{	PCI_VENDOR_ADP2,
35656e0e00bSjmcneill 		PCI_PRODUCT_ADP2_ASR2200S,
35756e0e00bSjmcneill 		PCI_VENDOR_ADP2,
35889b88fd7Schs 		PCI_PRODUCT_ADP2_2405,
35989b88fd7Schs 		AAC_HWIF_I960RX,
36089b88fd7Schs 		0,
36189b88fd7Schs 		"Adaptec RAID 2405"
36289b88fd7Schs 	},
36389b88fd7Schs 	{	PCI_VENDOR_ADP2,
36489b88fd7Schs 		PCI_PRODUCT_ADP2_ASR2200S,
36589b88fd7Schs 		PCI_VENDOR_ADP2,
3666c2db190Suwe 		PCI_PRODUCT_ADP2_2445,
3676c2db190Suwe 		AAC_HWIF_I960RX,
3686c2db190Suwe 		0,
3696c2db190Suwe 		"Adaptec RAID 2445"
3706c2db190Suwe 	},
3716c2db190Suwe 	{	PCI_VENDOR_ADP2,
3726c2db190Suwe 		PCI_PRODUCT_ADP2_ASR2200S,
3736c2db190Suwe 		PCI_VENDOR_ADP2,
3746c2db190Suwe 		PCI_PRODUCT_ADP2_2805,
3756c2db190Suwe 		AAC_HWIF_I960RX,
3766c2db190Suwe 		0,
3776c2db190Suwe 		"Adaptec RAID 2805"
3786c2db190Suwe 	},
3796c2db190Suwe 	{	PCI_VENDOR_ADP2,
3806c2db190Suwe 		PCI_PRODUCT_ADP2_ASR2200S,
3816c2db190Suwe 		PCI_VENDOR_ADP2,
38256e0e00bSjmcneill 		PCI_PRODUCT_ADP2_3405,
38356e0e00bSjmcneill 		AAC_HWIF_I960RX,
38456e0e00bSjmcneill 		0,
38556e0e00bSjmcneill 		"Adaptec RAID 3405"
38656e0e00bSjmcneill 	},
38789b88fd7Schs 	{	PCI_VENDOR_ADP2,
38889b88fd7Schs 		PCI_PRODUCT_ADP2_ASR2200S,
38989b88fd7Schs 		PCI_VENDOR_ADP2,
39089b88fd7Schs 		PCI_PRODUCT_ADP2_3805,
39189b88fd7Schs 		AAC_HWIF_I960RX,
39289b88fd7Schs 		0,
39389b88fd7Schs 		"Adaptec RAID 3805"
39489b88fd7Schs 	},
395cfe5fff0Ssborrill 	{
39677e08f05Sad 		PCI_VENDOR_DEC,
397b058cf77Saugustss 		PCI_PRODUCT_DEC_21554,
39877e08f05Sad 		PCI_VENDOR_ADP2,
39977e08f05Sad 		PCI_PRODUCT_ADP2_AAC364,
40077e08f05Sad 		AAC_HWIF_STRONGARM,
40177e08f05Sad 		0,
40277e08f05Sad 		"Adaptec AAC-364"
40377e08f05Sad 	},
40477e08f05Sad 	{
40577e08f05Sad 		PCI_VENDOR_DEC,
406b058cf77Saugustss 		PCI_PRODUCT_DEC_21554,
40777e08f05Sad 		PCI_VENDOR_ADP2,
40877e08f05Sad 		PCI_PRODUCT_ADP2_ASR5400S,
40977e08f05Sad 		AAC_HWIF_STRONGARM,
410f82d990bSbriggs 		AAC_QUIRK_BROKEN_MMAP,
41177e08f05Sad 		"Adaptec ASR-5400S"
41277e08f05Sad 	},
41377e08f05Sad 	{
41477e08f05Sad 		PCI_VENDOR_DEC,
415b058cf77Saugustss 		PCI_PRODUCT_DEC_21554,
41677e08f05Sad 		PCI_VENDOR_ADP2,
41777e08f05Sad 		PCI_PRODUCT_ADP2_PERC_2QC,
41877e08f05Sad 		AAC_HWIF_STRONGARM,
41977e08f05Sad 		AAC_QUIRK_PERC2QC,
42077e08f05Sad 		"Dell PERC 2/QC"
42177e08f05Sad 	},
42277e08f05Sad 	{
42377e08f05Sad 		PCI_VENDOR_DEC,
424b058cf77Saugustss 		PCI_PRODUCT_DEC_21554,
42577e08f05Sad 		PCI_VENDOR_ADP2,
42677e08f05Sad 		PCI_PRODUCT_ADP2_PERC_3QC,
42777e08f05Sad 		AAC_HWIF_STRONGARM,
42877e08f05Sad 		0,
42977e08f05Sad 		"Dell PERC 3/QC"
43077e08f05Sad 	},
43177e08f05Sad 	{
43277e08f05Sad 		PCI_VENDOR_DEC,
433b058cf77Saugustss 		PCI_PRODUCT_DEC_21554,
43477e08f05Sad 		PCI_VENDOR_HP,
43577e08f05Sad 		PCI_PRODUCT_HP_NETRAID_4M,
43677e08f05Sad 		AAC_HWIF_STRONGARM,
43777e08f05Sad 		0,
43877e08f05Sad 		"HP NetRAID-4M"
43977e08f05Sad 	},
440a038991fSis 	{
441a038991fSis 		PCI_VENDOR_ADP2,
442a038991fSis 		PCI_PRODUCT_ADP2_ASR2200S,
443a038991fSis 		PCI_VENDOR_SUN,
444a038991fSis 		PCI_PRODUCT_ADP2_ASR2120S,
4454fd593c1Sis 		AAC_HWIF_I960RX,
4464fd593c1Sis 		0,
4474fd593c1Sis 		"SG-XPCIESAS-R-IN"
4484fd593c1Sis 	},
44977e08f05Sad };
45077e08f05Sad 
451d36c43c5Sthorpej static const struct aac_ident *
aac_find_ident(struct pci_attach_args * pa)45277e08f05Sad aac_find_ident(struct pci_attach_args *pa)
45377e08f05Sad {
45477e08f05Sad 	const struct aac_ident *m, *mm;
45577e08f05Sad 	u_int32_t subsysid;
45677e08f05Sad 
45777e08f05Sad 	m = aac_ident;
45877e08f05Sad 	mm = aac_ident + (sizeof(aac_ident) / sizeof(aac_ident[0]));
45977e08f05Sad 
46077e08f05Sad 	while (m < mm) {
46177e08f05Sad 		if (m->vendor == PCI_VENDOR(pa->pa_id) &&
46277e08f05Sad 		    m->device == PCI_PRODUCT(pa->pa_id)) {
46377e08f05Sad 			subsysid = pci_conf_read(pa->pa_pc, pa->pa_tag,
46477e08f05Sad 			    PCI_SUBSYS_ID_REG);
46577e08f05Sad 			if (m->subvendor == PCI_VENDOR(subsysid) &&
46677e08f05Sad 			    m->subdevice == PCI_PRODUCT(subsysid))
46777e08f05Sad 				return (m);
46877e08f05Sad 		}
46977e08f05Sad 		m++;
47077e08f05Sad 	}
47177e08f05Sad 
47277e08f05Sad 	return (NULL);
47377e08f05Sad }
47477e08f05Sad 
475d36c43c5Sthorpej static int
aac_pci_intr_set(struct aac_softc * sc,int (* hand)(void *),void * arg)476f82d990bSbriggs aac_pci_intr_set(struct aac_softc *sc, int (*hand)(void*), void *arg)
477f82d990bSbriggs {
478f82d990bSbriggs 	struct aac_pci_softc	*pcisc;
479f82d990bSbriggs 
480f82d990bSbriggs 	pcisc = (struct aac_pci_softc *) sc;
481f82d990bSbriggs 
482f82d990bSbriggs 	pci_intr_disestablish(pcisc->sc_pc, sc->sc_ih);
483d3cda613Sjdolecek 	sc->sc_ih = pci_intr_establish_xname(pcisc->sc_pc, pcisc->sc_ih,
484d3cda613Sjdolecek 	    IPL_BIO, hand, arg, device_xname(sc->sc_dv));
485f82d990bSbriggs 	if (sc->sc_ih == NULL) {
486f82d990bSbriggs 		return ENXIO;
487f82d990bSbriggs 	}
488f82d990bSbriggs 	return 0;
489f82d990bSbriggs }
490f82d990bSbriggs 
491f82d990bSbriggs static int
aac_pci_match(device_t parent,cfdata_t match,void * aux)492a591bc88Scegger aac_pci_match(device_t parent, cfdata_t match, void *aux)
49377e08f05Sad {
49477e08f05Sad 	struct pci_attach_args *pa;
49577e08f05Sad 
49677e08f05Sad 	pa = aux;
49777e08f05Sad 
49877e08f05Sad 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_I2O)
49977e08f05Sad 		return (0);
50077e08f05Sad 
50177e08f05Sad 	return (aac_find_ident(pa) != NULL);
50277e08f05Sad }
50377e08f05Sad 
504d36c43c5Sthorpej static void
aac_pci_attach(device_t parent,device_t self,void * aux)505a591bc88Scegger aac_pci_attach(device_t parent, device_t self, void *aux)
50677e08f05Sad {
50777e08f05Sad 	struct pci_attach_args *pa;
50877e08f05Sad 	pci_chipset_tag_t pc;
509f82d990bSbriggs 	struct aac_pci_softc *pcisc;
51077e08f05Sad 	struct aac_softc *sc;
51177e08f05Sad 	u_int16_t command;
51277e08f05Sad 	bus_addr_t membase;
51377e08f05Sad 	bus_size_t memsize;
51477e08f05Sad 	const char *intrstr;
51577e08f05Sad 	int state;
51677e08f05Sad 	const struct aac_ident *m;
517e58a356cSchristos 	char intrbuf[PCI_INTRSTR_LEN];
51877e08f05Sad 
51977e08f05Sad 	pa = aux;
52077e08f05Sad 	pc = pa->pa_pc;
521b8169823Scegger 	pcisc = device_private(self);
522f82d990bSbriggs 	pcisc->sc_pc = pc;
523f82d990bSbriggs 	sc = &pcisc->sc_aac;
524cbab9cadSchs 	sc->sc_dv = self;
52577e08f05Sad 	state = 0;
52677e08f05Sad 
5277ec10e2dSthorpej 	aprint_naive(": RAID controller\n");
5287ec10e2dSthorpej 	aprint_normal(": ");
52977e08f05Sad 
53077e08f05Sad 	/*
53177e08f05Sad 	 * Verify that the adapter is correctly set up in PCI space.
53277e08f05Sad 	 */
53377e08f05Sad 	command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
53477e08f05Sad 	command |= PCI_COMMAND_MASTER_ENABLE;
53577e08f05Sad 	pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command);
53677e08f05Sad 	command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
53777e08f05Sad 	AAC_DPRINTF(AAC_D_MISC, ("pci command status reg 0x08x "));
53877e08f05Sad 
53977e08f05Sad 	if ((command & PCI_COMMAND_MASTER_ENABLE) == 0) {
5407ec10e2dSthorpej 		aprint_error("can't enable bus-master feature\n");
54177e08f05Sad 		goto bail_out;
54277e08f05Sad 	}
54377e08f05Sad 
54477e08f05Sad 	if ((command & PCI_COMMAND_MEM_ENABLE) == 0) {
5457ec10e2dSthorpej 		aprint_error("memory window not available\n");
54677e08f05Sad 		goto bail_out;
54777e08f05Sad 	}
54877e08f05Sad 
54977e08f05Sad 	/*
55077e08f05Sad 	 * Map control/status registers.
55177e08f05Sad 	 */
55277e08f05Sad 	if (pci_mapreg_map(pa, PCI_MAPREG_START,
55377e08f05Sad 	    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_memt,
55477e08f05Sad 	    &sc->sc_memh, &membase, &memsize)) {
5557ec10e2dSthorpej 		aprint_error("can't find mem space\n");
55677e08f05Sad 		goto bail_out;
55777e08f05Sad 	}
55877e08f05Sad 	state++;
55977e08f05Sad 
560f82d990bSbriggs 	if (pci_intr_map(pa, &pcisc->sc_ih)) {
5617ec10e2dSthorpej 		aprint_error("couldn't map interrupt\n");
56277e08f05Sad 		goto bail_out;
56377e08f05Sad 	}
564e58a356cSchristos 	intrstr = pci_intr_string(pc, pcisc->sc_ih, intrbuf, sizeof(intrbuf));
565d3cda613Sjdolecek 	sc->sc_ih = pci_intr_establish_xname(pc, pcisc->sc_ih, IPL_BIO,
566d3cda613Sjdolecek 	    aac_intr, sc, device_xname(self));
56777e08f05Sad 	if (sc->sc_ih == NULL) {
5687ec10e2dSthorpej 		aprint_error("couldn't establish interrupt");
56977e08f05Sad 		if (intrstr != NULL)
57085cadc23Snjoly 			aprint_error(" at %s", intrstr);
57185cadc23Snjoly 		aprint_error("\n");
57277e08f05Sad 		goto bail_out;
57377e08f05Sad 	}
57477e08f05Sad 	state++;
57577e08f05Sad 
57677e08f05Sad 	sc->sc_dmat = pa->pa_dmat;
57777e08f05Sad 
57877e08f05Sad 	m = aac_find_ident(pa);
5797ec10e2dSthorpej 	aprint_normal("%s\n", m->prodstr);
58077e08f05Sad 	if (intrstr != NULL)
5818bc54e5bSmsaitoh 		aprint_normal_dev(self, "interrupting at %s\n", intrstr);
58277e08f05Sad 
58377e08f05Sad 	sc->sc_hwif = m->hwif;
58477e08f05Sad 	sc->sc_quirks = m->quirks;
58577e08f05Sad 	switch (sc->sc_hwif) {
58677e08f05Sad 		case AAC_HWIF_I960RX:
58777e08f05Sad 			AAC_DPRINTF(AAC_D_MISC,
58877e08f05Sad 			    ("set hardware up for i960Rx"));
58977e08f05Sad 			sc->sc_if = aac_rx_interface;
59077e08f05Sad 			break;
59177e08f05Sad 
59277e08f05Sad 		case AAC_HWIF_STRONGARM:
59377e08f05Sad 			AAC_DPRINTF(AAC_D_MISC,
59477e08f05Sad 			    ("set hardware up for StrongARM"));
59577e08f05Sad 			sc->sc_if = aac_sa_interface;
59677e08f05Sad 			break;
597f82d990bSbriggs 
598f82d990bSbriggs 		case AAC_HWIF_RKT:
599f82d990bSbriggs 			AAC_DPRINTF(AAC_D_MISC,
600f82d990bSbriggs 			    ("set hardware up for MIPS/Rocket"));
601f82d990bSbriggs 			sc->sc_if = aac_rkt_interface;
602f82d990bSbriggs 			break;
60377e08f05Sad 	}
604f82d990bSbriggs 	sc->sc_regsize = memsize;
605f82d990bSbriggs 	sc->sc_intr_set = aac_pci_intr_set;
60677e08f05Sad 
60777e08f05Sad 	if (!aac_attach(sc))
60877e08f05Sad 		return;
60977e08f05Sad 
61077e08f05Sad  bail_out:
61177e08f05Sad 	if (state > 1)
61277e08f05Sad 		pci_intr_disestablish(pc, sc->sc_ih);
61377e08f05Sad 	if (state > 0)
61477e08f05Sad 		bus_space_unmap(sc->sc_memt, sc->sc_memh, memsize);
61577e08f05Sad }
61677e08f05Sad 
617916bdfa5Spgoyette /* ARGSUSED */
618916bdfa5Spgoyette static int
aac_pci_rescan(device_t self,const char * ifattr,const int * locs)6192685996bSthorpej aac_pci_rescan(device_t self, const char *ifattr, const int *locs)
620916bdfa5Spgoyette {
621916bdfa5Spgoyette 
622916bdfa5Spgoyette 	return aac_devscan(device_private(self));
623916bdfa5Spgoyette }
624916bdfa5Spgoyette 
625916bdfa5Spgoyette CFATTACH_DECL3_NEW(aac_pci, sizeof(struct aac_pci_softc),
626916bdfa5Spgoyette     aac_pci_match, aac_pci_attach, NULL, NULL, aac_pci_rescan, NULL, 0);
627d36c43c5Sthorpej 
62877e08f05Sad /*
62977e08f05Sad  * Read the current firmware status word.
63077e08f05Sad  */
631d36c43c5Sthorpej static int
aac_sa_get_fwstatus(struct aac_softc * sc)63277e08f05Sad aac_sa_get_fwstatus(struct aac_softc *sc)
63377e08f05Sad {
63477e08f05Sad 
63577e08f05Sad 	return (AAC_GETREG4(sc, AAC_SA_FWSTATUS));
63677e08f05Sad }
63777e08f05Sad 
638d36c43c5Sthorpej static int
aac_rx_get_fwstatus(struct aac_softc * sc)63977e08f05Sad aac_rx_get_fwstatus(struct aac_softc *sc)
64077e08f05Sad {
64177e08f05Sad 
64277e08f05Sad 	return (AAC_GETREG4(sc, AAC_RX_FWSTATUS));
64377e08f05Sad }
64477e08f05Sad 
645f82d990bSbriggs static int
aac_rkt_get_fwstatus(struct aac_softc * sc)646f82d990bSbriggs aac_rkt_get_fwstatus(struct aac_softc *sc)
647f82d990bSbriggs {
648f82d990bSbriggs 
649f82d990bSbriggs 	return (AAC_GETREG4(sc, AAC_RKT_FWSTATUS));
650f82d990bSbriggs }
651f82d990bSbriggs 
65277e08f05Sad /*
65377e08f05Sad  * Notify the controller of a change in a given queue
65477e08f05Sad  */
65577e08f05Sad 
656d36c43c5Sthorpej static void
aac_sa_qnotify(struct aac_softc * sc,int qbit)65777e08f05Sad aac_sa_qnotify(struct aac_softc *sc, int qbit)
65877e08f05Sad {
65977e08f05Sad 
66077e08f05Sad 	AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit);
66177e08f05Sad }
66277e08f05Sad 
663d36c43c5Sthorpej static void
aac_rx_qnotify(struct aac_softc * sc,int qbit)66477e08f05Sad aac_rx_qnotify(struct aac_softc *sc, int qbit)
66577e08f05Sad {
66677e08f05Sad 
66777e08f05Sad 	AAC_SETREG4(sc, AAC_RX_IDBR, qbit);
66877e08f05Sad }
66977e08f05Sad 
670f82d990bSbriggs static void
aac_rkt_qnotify(struct aac_softc * sc,int qbit)671f82d990bSbriggs aac_rkt_qnotify(struct aac_softc *sc, int qbit)
672f82d990bSbriggs {
673f82d990bSbriggs 
674f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RKT_IDBR, qbit);
675f82d990bSbriggs }
676f82d990bSbriggs 
67777e08f05Sad /*
67877e08f05Sad  * Get the interrupt reason bits
67977e08f05Sad  */
680d36c43c5Sthorpej static int
aac_sa_get_istatus(struct aac_softc * sc)68177e08f05Sad aac_sa_get_istatus(struct aac_softc *sc)
68277e08f05Sad {
68377e08f05Sad 
68477e08f05Sad 	return (AAC_GETREG2(sc, AAC_SA_DOORBELL0));
68577e08f05Sad }
68677e08f05Sad 
687d36c43c5Sthorpej static int
aac_rx_get_istatus(struct aac_softc * sc)68877e08f05Sad aac_rx_get_istatus(struct aac_softc *sc)
68977e08f05Sad {
69077e08f05Sad 
69177e08f05Sad 	return (AAC_GETREG4(sc, AAC_RX_ODBR));
69277e08f05Sad }
69377e08f05Sad 
694f82d990bSbriggs static int
aac_rkt_get_istatus(struct aac_softc * sc)695f82d990bSbriggs aac_rkt_get_istatus(struct aac_softc *sc)
696f82d990bSbriggs {
697f82d990bSbriggs 
698f82d990bSbriggs 	return (AAC_GETREG4(sc, AAC_RKT_ODBR));
699f82d990bSbriggs }
700f82d990bSbriggs 
70177e08f05Sad /*
70277e08f05Sad  * Clear some interrupt reason bits
70377e08f05Sad  */
704d36c43c5Sthorpej static void
aac_sa_clear_istatus(struct aac_softc * sc,int mask)70577e08f05Sad aac_sa_clear_istatus(struct aac_softc *sc, int mask)
70677e08f05Sad {
70777e08f05Sad 
70877e08f05Sad 	AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask);
70977e08f05Sad }
71077e08f05Sad 
711d36c43c5Sthorpej static void
aac_rx_clear_istatus(struct aac_softc * sc,int mask)71277e08f05Sad aac_rx_clear_istatus(struct aac_softc *sc, int mask)
71377e08f05Sad {
71477e08f05Sad 
71577e08f05Sad 	AAC_SETREG4(sc, AAC_RX_ODBR, mask);
71677e08f05Sad }
71777e08f05Sad 
718f82d990bSbriggs static void
aac_rkt_clear_istatus(struct aac_softc * sc,int mask)719f82d990bSbriggs aac_rkt_clear_istatus(struct aac_softc *sc, int mask)
720f82d990bSbriggs {
721f82d990bSbriggs 
722f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RKT_ODBR, mask);
723f82d990bSbriggs }
724f82d990bSbriggs 
72577e08f05Sad /*
72677e08f05Sad  * Populate the mailbox and set the command word
72777e08f05Sad  */
728d36c43c5Sthorpej static void
aac_sa_set_mailbox(struct aac_softc * sc,u_int32_t command,u_int32_t arg0,u_int32_t arg1,u_int32_t arg2,u_int32_t arg3)72977e08f05Sad aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
73077e08f05Sad 		   u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
73177e08f05Sad 		   u_int32_t arg3)
73277e08f05Sad {
73377e08f05Sad 
73477e08f05Sad 	AAC_SETREG4(sc, AAC_SA_MAILBOX, command);
73577e08f05Sad 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0);
73677e08f05Sad 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1);
73777e08f05Sad 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2);
73877e08f05Sad 	AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3);
73977e08f05Sad }
74077e08f05Sad 
741d36c43c5Sthorpej static void
aac_rx_set_mailbox(struct aac_softc * sc,u_int32_t command,u_int32_t arg0,u_int32_t arg1,u_int32_t arg2,u_int32_t arg3)74277e08f05Sad aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command,
74377e08f05Sad 		   u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
74477e08f05Sad 		   u_int32_t arg3)
74577e08f05Sad {
74677e08f05Sad 
74777e08f05Sad 	AAC_SETREG4(sc, AAC_RX_MAILBOX, command);
74877e08f05Sad 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0);
74977e08f05Sad 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1);
75077e08f05Sad 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2);
75177e08f05Sad 	AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3);
75277e08f05Sad }
75377e08f05Sad 
754f82d990bSbriggs static void
aac_rkt_set_mailbox(struct aac_softc * sc,u_int32_t command,u_int32_t arg0,u_int32_t arg1,u_int32_t arg2,u_int32_t arg3)755f82d990bSbriggs aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command,
756f82d990bSbriggs 		    u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
757f82d990bSbriggs 		    u_int32_t arg3)
758f82d990bSbriggs {
759f82d990bSbriggs 
760f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RKT_MAILBOX, command);
761f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0);
762f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1);
763f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2);
764f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3);
765f82d990bSbriggs }
766f82d990bSbriggs 
76777e08f05Sad /*
76880240054Sbriggs  * Fetch the specified mailbox
76977e08f05Sad  */
770d36c43c5Sthorpej static uint32_t
aac_sa_get_mailbox(struct aac_softc * sc,int mb)77180240054Sbriggs aac_sa_get_mailbox(struct aac_softc *sc, int mb)
77277e08f05Sad {
77377e08f05Sad 
77480240054Sbriggs 	return (AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4)));
77577e08f05Sad }
77677e08f05Sad 
777d36c43c5Sthorpej static uint32_t
aac_rx_get_mailbox(struct aac_softc * sc,int mb)77880240054Sbriggs aac_rx_get_mailbox(struct aac_softc *sc, int mb)
77977e08f05Sad {
78077e08f05Sad 
78180240054Sbriggs 	return (AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4)));
78277e08f05Sad }
78377e08f05Sad 
784f82d990bSbriggs static uint32_t
aac_rkt_get_mailbox(struct aac_softc * sc,int mb)785f82d990bSbriggs aac_rkt_get_mailbox(struct aac_softc *sc, int mb)
786f82d990bSbriggs {
787f82d990bSbriggs 
788f82d990bSbriggs 	return (AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4)));
789f82d990bSbriggs }
790f82d990bSbriggs 
79177e08f05Sad /*
79277e08f05Sad  * Set/clear interrupt masks
79377e08f05Sad  */
794d36c43c5Sthorpej static void
aac_sa_set_interrupts(struct aac_softc * sc,int enable)79577e08f05Sad aac_sa_set_interrupts(struct aac_softc *sc, int enable)
79677e08f05Sad {
79777e08f05Sad 
79877e08f05Sad 	if (enable)
79977e08f05Sad 		AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
80077e08f05Sad 	else
80177e08f05Sad 		AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0);
80277e08f05Sad }
80377e08f05Sad 
804d36c43c5Sthorpej static void
aac_rx_set_interrupts(struct aac_softc * sc,int enable)80577e08f05Sad aac_rx_set_interrupts(struct aac_softc *sc, int enable)
80677e08f05Sad {
80777e08f05Sad 
808f82d990bSbriggs 	if (enable) {
809f82d990bSbriggs 		if (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
810f82d990bSbriggs 			AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INT_NEW_COMM);
81177e08f05Sad 		else
812f82d990bSbriggs 			AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
813f82d990bSbriggs 	} else {
81477e08f05Sad 		AAC_SETREG4(sc, AAC_RX_OIMR, ~0);
81577e08f05Sad 	}
816f82d990bSbriggs }
817f82d990bSbriggs 
818f82d990bSbriggs static void
aac_rkt_set_interrupts(struct aac_softc * sc,int enable)819f82d990bSbriggs aac_rkt_set_interrupts(struct aac_softc *sc, int enable)
820f82d990bSbriggs {
821f82d990bSbriggs 
822f82d990bSbriggs 	if (enable) {
823f82d990bSbriggs 		if (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
824f82d990bSbriggs 			AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INT_NEW_COMM);
825f82d990bSbriggs 		else
826f82d990bSbriggs 			AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS);
827f82d990bSbriggs 	} else {
828f82d990bSbriggs 		AAC_SETREG4(sc, AAC_RKT_OIMR, ~0);
829f82d990bSbriggs 	}
830f82d990bSbriggs }
831f82d990bSbriggs 
832f82d990bSbriggs /*
833f82d990bSbriggs  * New comm. interface: Send command functions
834f82d990bSbriggs  */
835f82d990bSbriggs static int
aac_rx_send_command(struct aac_softc * sc,struct aac_ccb * ac)836f82d990bSbriggs aac_rx_send_command(struct aac_softc *sc, struct aac_ccb *ac)
837f82d990bSbriggs {
838f82d990bSbriggs 	u_int32_t	index, device;
839f82d990bSbriggs 
840f82d990bSbriggs 	index = AAC_GETREG4(sc, AAC_RX_IQUE);
841f82d990bSbriggs 	if (index == 0xffffffffL)
842f82d990bSbriggs 		index = AAC_GETREG4(sc, AAC_RX_IQUE);
843f82d990bSbriggs 	if (index == 0xffffffffL)
844f82d990bSbriggs 		return index;
845f82d990bSbriggs #ifdef notyet
846f82d990bSbriggs 	aac_enqueue_busy(ac);
847f82d990bSbriggs #endif
848f82d990bSbriggs 	device = index;
849f82d990bSbriggs 	AAC_SETREG4(sc, device,
850f82d990bSbriggs 	    htole32((u_int32_t)(ac->ac_fibphys & 0xffffffffUL)));
851f82d990bSbriggs 	device += 4;
852f82d990bSbriggs 	if (sizeof(bus_addr_t) > 4) {
853f82d990bSbriggs 		AAC_SETREG4(sc, device,
854f82d990bSbriggs 		    htole32((u_int32_t)((u_int64_t)ac->ac_fibphys >> 32)));
855f82d990bSbriggs 	} else {
856f82d990bSbriggs 		AAC_SETREG4(sc, device, 0);
857f82d990bSbriggs 	}
858f82d990bSbriggs 	device += 4;
859f82d990bSbriggs 	AAC_SETREG4(sc, device, ac->ac_fib->Header.Size);
860f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RX_IQUE, index);
861f82d990bSbriggs 	return 0;
862f82d990bSbriggs }
863f82d990bSbriggs 
864f82d990bSbriggs static int
aac_rkt_send_command(struct aac_softc * sc,struct aac_ccb * ac)865f82d990bSbriggs aac_rkt_send_command(struct aac_softc *sc, struct aac_ccb *ac)
866f82d990bSbriggs {
867f82d990bSbriggs 	u_int32_t	index, device;
868f82d990bSbriggs 
869f82d990bSbriggs 	index = AAC_GETREG4(sc, AAC_RKT_IQUE);
870f82d990bSbriggs 	if (index == 0xffffffffL)
871f82d990bSbriggs 		index = AAC_GETREG4(sc, AAC_RKT_IQUE);
872f82d990bSbriggs 	if (index == 0xffffffffL)
873f82d990bSbriggs 		return index;
874f82d990bSbriggs #ifdef notyet
875f82d990bSbriggs 	aac_enqueue_busy(ac);
876f82d990bSbriggs #endif
877f82d990bSbriggs 	device = index;
878f82d990bSbriggs 	AAC_SETREG4(sc, device,
879f82d990bSbriggs 	    htole32((u_int32_t)(ac->ac_fibphys & 0xffffffffUL)));
880f82d990bSbriggs 	device += 4;
881f82d990bSbriggs 	if (sizeof(bus_addr_t) > 4) {
882f82d990bSbriggs 		AAC_SETREG4(sc, device,
883f82d990bSbriggs 		    htole32((u_int32_t)((u_int64_t)ac->ac_fibphys >> 32)));
884f82d990bSbriggs 	} else {
885f82d990bSbriggs 		AAC_SETREG4(sc, device, 0);
886f82d990bSbriggs 	}
887f82d990bSbriggs 	device += 4;
888f82d990bSbriggs 	AAC_SETREG4(sc, device, ac->ac_fib->Header.Size);
889f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RKT_IQUE, index);
890f82d990bSbriggs 	return 0;
891f82d990bSbriggs }
892f82d990bSbriggs 
893f82d990bSbriggs /*
894f82d990bSbriggs  * New comm. interface: get, set outbound queue index
895f82d990bSbriggs  */
896f82d990bSbriggs static int
aac_rx_get_outb_queue(struct aac_softc * sc)897f82d990bSbriggs aac_rx_get_outb_queue(struct aac_softc *sc)
898f82d990bSbriggs {
899f82d990bSbriggs 
900f82d990bSbriggs 	return AAC_GETREG4(sc, AAC_RX_OQUE);
901f82d990bSbriggs }
902f82d990bSbriggs 
903f82d990bSbriggs static int
aac_rkt_get_outb_queue(struct aac_softc * sc)904f82d990bSbriggs aac_rkt_get_outb_queue(struct aac_softc *sc)
905f82d990bSbriggs {
906f82d990bSbriggs 
907f82d990bSbriggs 	return AAC_GETREG4(sc, AAC_RKT_OQUE);
908f82d990bSbriggs }
909f82d990bSbriggs 
910f82d990bSbriggs static void
aac_rx_set_outb_queue(struct aac_softc * sc,int index)911f82d990bSbriggs aac_rx_set_outb_queue(struct aac_softc *sc, int index)
912f82d990bSbriggs {
913f82d990bSbriggs 
914f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RX_OQUE, index);
915f82d990bSbriggs }
916f82d990bSbriggs 
917f82d990bSbriggs static void
aac_rkt_set_outb_queue(struct aac_softc * sc,int index)918f82d990bSbriggs aac_rkt_set_outb_queue(struct aac_softc *sc, int index)
919f82d990bSbriggs {
920f82d990bSbriggs 
921f82d990bSbriggs 	AAC_SETREG4(sc, AAC_RKT_OQUE, index);
922f82d990bSbriggs }
923