xref: /freebsd/sys/dev/isp/isp_pci.c (revision 218be0b2eebe2a5e5fb290c178a01816e4bdc278)
1aad970f1SDavid E. O'Brien /*-
22df76c16SMatt Jacob  * Copyright (c) 1997-2008 by Matthew Jacob
3e5265237SMatt Jacob  * All rights reserved.
465adb54cSMatt Jacob  *
565adb54cSMatt Jacob  * Redistribution and use in source and binary forms, with or without
665adb54cSMatt Jacob  * modification, are permitted provided that the following conditions
765adb54cSMatt Jacob  * are met:
865adb54cSMatt Jacob  * 1. Redistributions of source code must retain the above copyright
965adb54cSMatt Jacob  *    notice immediately at the beginning of the file, without modification,
1065adb54cSMatt Jacob  *    this list of conditions, and the following disclaimer.
11aa57fd6fSMatt Jacob  * 2. The name of the author may not be used to endorse or promote products
12aa57fd6fSMatt Jacob  *    derived from this software without specific prior written permission.
1365adb54cSMatt Jacob  *
1465adb54cSMatt Jacob  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1565adb54cSMatt Jacob  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1665adb54cSMatt Jacob  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1765adb54cSMatt Jacob  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
1865adb54cSMatt Jacob  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1965adb54cSMatt Jacob  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2065adb54cSMatt Jacob  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2165adb54cSMatt Jacob  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2265adb54cSMatt Jacob  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2365adb54cSMatt Jacob  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2465adb54cSMatt Jacob  * SUCH DAMAGE.
2565adb54cSMatt Jacob  */
26799881e0SMatt Jacob /*
27799881e0SMatt Jacob  * PCI specific probe and attach routines for Qlogic ISP SCSI adapters.
28799881e0SMatt Jacob  * FreeBSD Version.
29799881e0SMatt Jacob  */
30aad970f1SDavid E. O'Brien #include <sys/cdefs.h>
31aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$");
32aad970f1SDavid E. O'Brien 
33960f6939SMatt Jacob #include <sys/param.h>
34960f6939SMatt Jacob #include <sys/systm.h>
35960f6939SMatt Jacob #include <sys/kernel.h>
36960f6939SMatt Jacob #include <sys/module.h>
379a5af410SMatt Jacob #include <sys/linker.h>
389a5af410SMatt Jacob #include <sys/firmware.h>
39960f6939SMatt Jacob #include <sys/bus.h>
4074a96f43SJohn Baldwin #include <sys/stdint.h>
4177e6a3b2SWarner Losh #include <dev/pci/pcireg.h>
4277e6a3b2SWarner Losh #include <dev/pci/pcivar.h>
43d720e6d5SJustin T. Gibbs #include <machine/bus.h>
44960f6939SMatt Jacob #include <machine/resource.h>
45960f6939SMatt Jacob #include <sys/rman.h>
46960f6939SMatt Jacob #include <sys/malloc.h>
472df76c16SMatt Jacob #include <sys/uio.h>
48960f6939SMatt Jacob 
4917bc427dSMarius Strobl #ifdef __sparc64__
5017bc427dSMarius Strobl #include <dev/ofw/openfirm.h>
5117bc427dSMarius Strobl #include <machine/ofw_machdep.h>
5217bc427dSMarius Strobl #endif
5317bc427dSMarius Strobl 
54960f6939SMatt Jacob #include <dev/isp/isp_freebsd.h>
55d59bd469SMatt Jacob 
5610365e5aSMatt Jacob static uint32_t isp_pci_rd_reg(ispsoftc_t *, int);
5710365e5aSMatt Jacob static void isp_pci_wr_reg(ispsoftc_t *, int, uint32_t);
5810365e5aSMatt Jacob static uint32_t isp_pci_rd_reg_1080(ispsoftc_t *, int);
5910365e5aSMatt Jacob static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint32_t);
6010365e5aSMatt Jacob static uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int);
6110365e5aSMatt Jacob static void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t);
626ce548a1SAlexander Motin static int isp_pci_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
636ce548a1SAlexander Motin static int isp_pci_rd_isr_2300(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
646ce548a1SAlexander Motin static int isp_pci_rd_isr_2400(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
659cd7268eSMatt Jacob static int isp_pci_mbxdma(ispsoftc_t *);
662df76c16SMatt Jacob static int isp_pci_dmasetup(ispsoftc_t *, XS_T *, void *);
679cd7268eSMatt Jacob 
689a5af410SMatt Jacob 
693bda7a83SMatt Jacob static void isp_pci_reset0(ispsoftc_t *);
709cd7268eSMatt Jacob static void isp_pci_reset1(ispsoftc_t *);
719cd7268eSMatt Jacob static void isp_pci_dumpregs(ispsoftc_t *, const char *);
7265adb54cSMatt Jacob 
7365adb54cSMatt Jacob static struct ispmdvec mdvec = {
74126ec864SMatt Jacob 	isp_pci_rd_isr,
7565adb54cSMatt Jacob 	isp_pci_rd_reg,
7665adb54cSMatt Jacob 	isp_pci_wr_reg,
7765adb54cSMatt Jacob 	isp_pci_mbxdma,
7865adb54cSMatt Jacob 	isp_pci_dmasetup,
790a70657fSMatt Jacob 	isp_common_dmateardown,
803bda7a83SMatt Jacob 	isp_pci_reset0,
8165adb54cSMatt Jacob 	isp_pci_reset1,
8265adb54cSMatt Jacob 	isp_pci_dumpregs,
8356aef503SMatt Jacob 	NULL,
84d02373f1SMatt Jacob 	BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
8565adb54cSMatt Jacob };
8665adb54cSMatt Jacob 
87d59bd469SMatt Jacob static struct ispmdvec mdvec_1080 = {
88126ec864SMatt Jacob 	isp_pci_rd_isr,
89d59bd469SMatt Jacob 	isp_pci_rd_reg_1080,
90d59bd469SMatt Jacob 	isp_pci_wr_reg_1080,
91d59bd469SMatt Jacob 	isp_pci_mbxdma,
92d59bd469SMatt Jacob 	isp_pci_dmasetup,
930a70657fSMatt Jacob 	isp_common_dmateardown,
943bda7a83SMatt Jacob 	isp_pci_reset0,
95d59bd469SMatt Jacob 	isp_pci_reset1,
96d59bd469SMatt Jacob 	isp_pci_dumpregs,
9756aef503SMatt Jacob 	NULL,
98d02373f1SMatt Jacob 	BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
99d59bd469SMatt Jacob };
100d59bd469SMatt Jacob 
101960f6939SMatt Jacob static struct ispmdvec mdvec_12160 = {
102126ec864SMatt Jacob 	isp_pci_rd_isr,
103960f6939SMatt Jacob 	isp_pci_rd_reg_1080,
104960f6939SMatt Jacob 	isp_pci_wr_reg_1080,
105960f6939SMatt Jacob 	isp_pci_mbxdma,
106960f6939SMatt Jacob 	isp_pci_dmasetup,
1070a70657fSMatt Jacob 	isp_common_dmateardown,
1083bda7a83SMatt Jacob 	isp_pci_reset0,
109960f6939SMatt Jacob 	isp_pci_reset1,
110960f6939SMatt Jacob 	isp_pci_dumpregs,
11156aef503SMatt Jacob 	NULL,
112d02373f1SMatt Jacob 	BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
113960f6939SMatt Jacob };
114960f6939SMatt Jacob 
11565adb54cSMatt Jacob static struct ispmdvec mdvec_2100 = {
116126ec864SMatt Jacob 	isp_pci_rd_isr,
11765adb54cSMatt Jacob 	isp_pci_rd_reg,
11865adb54cSMatt Jacob 	isp_pci_wr_reg,
11965adb54cSMatt Jacob 	isp_pci_mbxdma,
12065adb54cSMatt Jacob 	isp_pci_dmasetup,
1210a70657fSMatt Jacob 	isp_common_dmateardown,
1223bda7a83SMatt Jacob 	isp_pci_reset0,
12365adb54cSMatt Jacob 	isp_pci_reset1,
124d02373f1SMatt Jacob 	isp_pci_dumpregs
12565adb54cSMatt Jacob };
126222bb542SMatt Jacob 
127222bb542SMatt Jacob static struct ispmdvec mdvec_2200 = {
128126ec864SMatt Jacob 	isp_pci_rd_isr,
129126ec864SMatt Jacob 	isp_pci_rd_reg,
130126ec864SMatt Jacob 	isp_pci_wr_reg,
131126ec864SMatt Jacob 	isp_pci_mbxdma,
132126ec864SMatt Jacob 	isp_pci_dmasetup,
1330a70657fSMatt Jacob 	isp_common_dmateardown,
1343bda7a83SMatt Jacob 	isp_pci_reset0,
135126ec864SMatt Jacob 	isp_pci_reset1,
136126ec864SMatt Jacob 	isp_pci_dumpregs
137126ec864SMatt Jacob };
138126ec864SMatt Jacob 
139126ec864SMatt Jacob static struct ispmdvec mdvec_2300 = {
140126ec864SMatt Jacob 	isp_pci_rd_isr_2300,
141222bb542SMatt Jacob 	isp_pci_rd_reg,
142222bb542SMatt Jacob 	isp_pci_wr_reg,
143222bb542SMatt Jacob 	isp_pci_mbxdma,
144222bb542SMatt Jacob 	isp_pci_dmasetup,
1450a70657fSMatt Jacob 	isp_common_dmateardown,
1463bda7a83SMatt Jacob 	isp_pci_reset0,
147222bb542SMatt Jacob 	isp_pci_reset1,
148d02373f1SMatt Jacob 	isp_pci_dumpregs
149222bb542SMatt Jacob };
150d951bbcaSMatt Jacob 
15110365e5aSMatt Jacob static struct ispmdvec mdvec_2400 = {
15210365e5aSMatt Jacob 	isp_pci_rd_isr_2400,
15310365e5aSMatt Jacob 	isp_pci_rd_reg_2400,
15410365e5aSMatt Jacob 	isp_pci_wr_reg_2400,
15510365e5aSMatt Jacob 	isp_pci_mbxdma,
15610365e5aSMatt Jacob 	isp_pci_dmasetup,
1570a70657fSMatt Jacob 	isp_common_dmateardown,
1583bda7a83SMatt Jacob 	isp_pci_reset0,
15910365e5aSMatt Jacob 	isp_pci_reset1,
16010365e5aSMatt Jacob 	NULL
16110365e5aSMatt Jacob };
16210365e5aSMatt Jacob 
1632df76c16SMatt Jacob static struct ispmdvec mdvec_2500 = {
1642df76c16SMatt Jacob 	isp_pci_rd_isr_2400,
1652df76c16SMatt Jacob 	isp_pci_rd_reg_2400,
1662df76c16SMatt Jacob 	isp_pci_wr_reg_2400,
1672df76c16SMatt Jacob 	isp_pci_mbxdma,
1682df76c16SMatt Jacob 	isp_pci_dmasetup,
1692df76c16SMatt Jacob 	isp_common_dmateardown,
1702df76c16SMatt Jacob 	isp_pci_reset0,
1712df76c16SMatt Jacob 	isp_pci_reset1,
1722df76c16SMatt Jacob 	NULL
1732df76c16SMatt Jacob };
1742df76c16SMatt Jacob 
175*218be0b2SAlexander Motin static struct ispmdvec mdvec_2600 = {
176*218be0b2SAlexander Motin 	isp_pci_rd_isr_2400,
177*218be0b2SAlexander Motin 	isp_pci_rd_reg_2400,
178*218be0b2SAlexander Motin 	isp_pci_wr_reg_2400,
179*218be0b2SAlexander Motin 	isp_pci_mbxdma,
180*218be0b2SAlexander Motin 	isp_pci_dmasetup,
181*218be0b2SAlexander Motin 	isp_common_dmateardown,
182*218be0b2SAlexander Motin 	isp_pci_reset0,
183*218be0b2SAlexander Motin 	isp_pci_reset1,
184*218be0b2SAlexander Motin 	NULL
185*218be0b2SAlexander Motin };
186*218be0b2SAlexander Motin 
18765adb54cSMatt Jacob #ifndef	PCIM_CMD_INVEN
18865adb54cSMatt Jacob #define	PCIM_CMD_INVEN			0x10
18965adb54cSMatt Jacob #endif
19065adb54cSMatt Jacob #ifndef	PCIM_CMD_BUSMASTEREN
19165adb54cSMatt Jacob #define	PCIM_CMD_BUSMASTEREN		0x0004
19265adb54cSMatt Jacob #endif
193d951bbcaSMatt Jacob #ifndef	PCIM_CMD_PERRESPEN
194d951bbcaSMatt Jacob #define	PCIM_CMD_PERRESPEN		0x0040
195d951bbcaSMatt Jacob #endif
196d951bbcaSMatt Jacob #ifndef	PCIM_CMD_SEREN
197d951bbcaSMatt Jacob #define	PCIM_CMD_SEREN			0x0100
198d951bbcaSMatt Jacob #endif
1998a97c03aSMatt Jacob #ifndef	PCIM_CMD_INTX_DISABLE
2008a97c03aSMatt Jacob #define	PCIM_CMD_INTX_DISABLE		0x0400
2018a97c03aSMatt Jacob #endif
202d951bbcaSMatt Jacob 
203d951bbcaSMatt Jacob #ifndef	PCIR_COMMAND
204d951bbcaSMatt Jacob #define	PCIR_COMMAND			0x04
205d951bbcaSMatt Jacob #endif
206d951bbcaSMatt Jacob 
207d951bbcaSMatt Jacob #ifndef	PCIR_CACHELNSZ
208d951bbcaSMatt Jacob #define	PCIR_CACHELNSZ			0x0c
209d951bbcaSMatt Jacob #endif
210d951bbcaSMatt Jacob 
211d951bbcaSMatt Jacob #ifndef	PCIR_LATTIMER
212d951bbcaSMatt Jacob #define	PCIR_LATTIMER			0x0d
213d951bbcaSMatt Jacob #endif
214d951bbcaSMatt Jacob 
215ab6d0040SMatt Jacob #ifndef	PCIR_ROMADDR
216ab6d0040SMatt Jacob #define	PCIR_ROMADDR			0x30
217ab6d0040SMatt Jacob #endif
218ab6d0040SMatt Jacob 
21965adb54cSMatt Jacob #ifndef	PCI_VENDOR_QLOGIC
22065adb54cSMatt Jacob #define	PCI_VENDOR_QLOGIC		0x1077
22165adb54cSMatt Jacob #endif
22265adb54cSMatt Jacob 
22365adb54cSMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP1020
22465adb54cSMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP1020	0x1020
22565adb54cSMatt Jacob #endif
22665adb54cSMatt Jacob 
227d59bd469SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP1080
228d59bd469SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP1080	0x1080
229d59bd469SMatt Jacob #endif
230d59bd469SMatt Jacob 
231f556e83bSMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP10160
232f556e83bSMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP10160	0x1016
233f556e83bSMatt Jacob #endif
234f556e83bSMatt Jacob 
235960f6939SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP12160
236960f6939SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP12160	0x1216
237960f6939SMatt Jacob #endif
238960f6939SMatt Jacob 
239d59bd469SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP1240
240d59bd469SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP1240	0x1240
241d59bd469SMatt Jacob #endif
24265adb54cSMatt Jacob 
24322e1dc85SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP1280
24422e1dc85SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP1280	0x1280
24522e1dc85SMatt Jacob #endif
24622e1dc85SMatt Jacob 
24765adb54cSMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP2100
24865adb54cSMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP2100	0x2100
24965adb54cSMatt Jacob #endif
25065adb54cSMatt Jacob 
251222bb542SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP2200
252222bb542SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP2200	0x2200
253222bb542SMatt Jacob #endif
254222bb542SMatt Jacob 
255126ec864SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP2300
256126ec864SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP2300	0x2300
257126ec864SMatt Jacob #endif
258126ec864SMatt Jacob 
259126ec864SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP2312
260126ec864SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP2312	0x2312
261126ec864SMatt Jacob #endif
262126ec864SMatt Jacob 
263e5265237SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP2322
264e5265237SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP2322	0x2322
265e5265237SMatt Jacob #endif
266e5265237SMatt Jacob 
2678872e3d7SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP2422
2688872e3d7SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP2422	0x2422
2698872e3d7SMatt Jacob #endif
2708872e3d7SMatt Jacob 
27141675df0SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP2432
27241675df0SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP2432	0x2432
27341675df0SMatt Jacob #endif
27441675df0SMatt Jacob 
2752df76c16SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP2532
2762df76c16SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP2532	0x2532
2772df76c16SMatt Jacob #endif
2782df76c16SMatt Jacob 
279dd1419abSMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP6312
280dd1419abSMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP6312	0x6312
281dd1419abSMatt Jacob #endif
282dd1419abSMatt Jacob 
2839a5af410SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP6322
2849a5af410SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP6322	0x6322
2859a5af410SMatt Jacob #endif
2869a5af410SMatt Jacob 
287a959d921SMatt Jacob #ifndef        PCI_PRODUCT_QLOGIC_ISP5432
288a959d921SMatt Jacob #define        PCI_PRODUCT_QLOGIC_ISP5432      0x5432
289a959d921SMatt Jacob #endif
290a959d921SMatt Jacob 
291*218be0b2SAlexander Motin #ifndef	PCI_PRODUCT_QLOGIC_ISP2031
292*218be0b2SAlexander Motin #define	PCI_PRODUCT_QLOGIC_ISP2031	0x2031
293*218be0b2SAlexander Motin #endif
294*218be0b2SAlexander Motin 
295a959d921SMatt Jacob #define        PCI_QLOGIC_ISP5432      \
296a959d921SMatt Jacob        ((PCI_PRODUCT_QLOGIC_ISP5432 << 16) | PCI_VENDOR_QLOGIC)
2979a5af410SMatt Jacob 
29856aef503SMatt Jacob #define	PCI_QLOGIC_ISP1020	\
29956aef503SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC)
300d59bd469SMatt Jacob 
301d59bd469SMatt Jacob #define	PCI_QLOGIC_ISP1080	\
302d59bd469SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC)
303d59bd469SMatt Jacob 
304f556e83bSMatt Jacob #define	PCI_QLOGIC_ISP10160	\
305f556e83bSMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP10160 << 16) | PCI_VENDOR_QLOGIC)
306f556e83bSMatt Jacob 
307960f6939SMatt Jacob #define	PCI_QLOGIC_ISP12160	\
308960f6939SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC)
309960f6939SMatt Jacob 
310d59bd469SMatt Jacob #define	PCI_QLOGIC_ISP1240	\
311d59bd469SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC)
312d59bd469SMatt Jacob 
31322e1dc85SMatt Jacob #define	PCI_QLOGIC_ISP1280	\
31422e1dc85SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC)
31522e1dc85SMatt Jacob 
31665adb54cSMatt Jacob #define	PCI_QLOGIC_ISP2100	\
31765adb54cSMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC)
31865adb54cSMatt Jacob 
319222bb542SMatt Jacob #define	PCI_QLOGIC_ISP2200	\
320222bb542SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC)
321222bb542SMatt Jacob 
322126ec864SMatt Jacob #define	PCI_QLOGIC_ISP2300	\
323126ec864SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC)
324126ec864SMatt Jacob 
325126ec864SMatt Jacob #define	PCI_QLOGIC_ISP2312	\
326126ec864SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC)
327126ec864SMatt Jacob 
328e5265237SMatt Jacob #define	PCI_QLOGIC_ISP2322	\
329e5265237SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP2322 << 16) | PCI_VENDOR_QLOGIC)
330e5265237SMatt Jacob 
3316c426685SMatt Jacob #define	PCI_QLOGIC_ISP2422	\
3326c426685SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP2422 << 16) | PCI_VENDOR_QLOGIC)
3336c426685SMatt Jacob 
33441675df0SMatt Jacob #define	PCI_QLOGIC_ISP2432	\
33541675df0SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP2432 << 16) | PCI_VENDOR_QLOGIC)
33641675df0SMatt Jacob 
3372df76c16SMatt Jacob #define	PCI_QLOGIC_ISP2532	\
3382df76c16SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP2532 << 16) | PCI_VENDOR_QLOGIC)
3392df76c16SMatt Jacob 
340dd1419abSMatt Jacob #define	PCI_QLOGIC_ISP6312	\
341dd1419abSMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC)
342dd1419abSMatt Jacob 
3439a5af410SMatt Jacob #define	PCI_QLOGIC_ISP6322	\
3449a5af410SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP6322 << 16) | PCI_VENDOR_QLOGIC)
3459a5af410SMatt Jacob 
346*218be0b2SAlexander Motin #define	PCI_QLOGIC_ISP2031	\
347*218be0b2SAlexander Motin 	((PCI_PRODUCT_QLOGIC_ISP2031 << 16) | PCI_VENDOR_QLOGIC)
348*218be0b2SAlexander Motin 
349e11a1ee8SMatt Jacob /*
350e11a1ee8SMatt Jacob  * Odd case for some AMI raid cards... We need to *not* attach to this.
351e11a1ee8SMatt Jacob  */
352e11a1ee8SMatt Jacob #define	AMI_RAID_SUBVENDOR_ID	0x101e
353e11a1ee8SMatt Jacob 
354d951bbcaSMatt Jacob #define	PCI_DFLT_LTNCY	0x40
355d951bbcaSMatt Jacob #define	PCI_DFLT_LNSZ	0x10
35665adb54cSMatt Jacob 
357960f6939SMatt Jacob static int isp_pci_probe (device_t);
358960f6939SMatt Jacob static int isp_pci_attach (device_t);
35910365e5aSMatt Jacob static int isp_pci_detach (device_t);
36065adb54cSMatt Jacob 
3611923f739SMatt Jacob 
3620230a28bSMatt Jacob #define	ISP_PCD(isp)	((struct isp_pcisoftc *)isp)->pci_dev
36365adb54cSMatt Jacob struct isp_pcisoftc {
3649cd7268eSMatt Jacob 	ispsoftc_t			pci_isp;
365960f6939SMatt Jacob 	device_t			pci_dev;
366e95725cbSMatt Jacob 	struct resource *		regs;
367e95725cbSMatt Jacob 	void *				irq;
368e95725cbSMatt Jacob 	int				iqd;
369e95725cbSMatt Jacob 	int				rtp;
370e95725cbSMatt Jacob 	int				rgd;
371960f6939SMatt Jacob 	void *				ih;
372d59bd469SMatt Jacob 	int16_t				pci_poff[_NREG_BLKS];
3731923f739SMatt Jacob 	bus_dma_tag_t			dmat;
3740a70657fSMatt Jacob 	int				msicount;
37565adb54cSMatt Jacob };
37665adb54cSMatt Jacob 
37710365e5aSMatt Jacob 
378960f6939SMatt Jacob static device_method_t isp_pci_methods[] = {
379960f6939SMatt Jacob 	/* Device interface */
380960f6939SMatt Jacob 	DEVMETHOD(device_probe,		isp_pci_probe),
381960f6939SMatt Jacob 	DEVMETHOD(device_attach,	isp_pci_attach),
38210365e5aSMatt Jacob 	DEVMETHOD(device_detach,	isp_pci_detach),
383960f6939SMatt Jacob 	{ 0, 0 }
38465adb54cSMatt Jacob };
38565adb54cSMatt Jacob 
386960f6939SMatt Jacob static driver_t isp_pci_driver = {
387960f6939SMatt Jacob 	"isp", isp_pci_methods, sizeof (struct isp_pcisoftc)
388960f6939SMatt Jacob };
389960f6939SMatt Jacob static devclass_t isp_devclass;
390960f6939SMatt Jacob DRIVER_MODULE(isp, pci, isp_pci_driver, isp_devclass, 0, 0);
391d45ce511SEitan Adler MODULE_DEPEND(isp, cam, 1, 1, 1);
392d45ce511SEitan Adler MODULE_DEPEND(isp, firmware, 1, 1, 1);
3939e7d423dSMatt Jacob static int isp_nvports = 0;
39465adb54cSMatt Jacob 
395960f6939SMatt Jacob static int
396960f6939SMatt Jacob isp_pci_probe(device_t dev)
39765adb54cSMatt Jacob {
398960f6939SMatt Jacob 	switch ((pci_get_device(dev) << 16) | (pci_get_vendor(dev))) {
39956aef503SMatt Jacob 	case PCI_QLOGIC_ISP1020:
400960f6939SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 1020/1040 PCI SCSI Adapter");
40165adb54cSMatt Jacob 		break;
402d59bd469SMatt Jacob 	case PCI_QLOGIC_ISP1080:
403960f6939SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 1080 PCI SCSI Adapter");
404c6608df3SMatt Jacob 		break;
405c6608df3SMatt Jacob 	case PCI_QLOGIC_ISP1240:
406960f6939SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 1240 PCI SCSI Adapter");
407d59bd469SMatt Jacob 		break;
40822e1dc85SMatt Jacob 	case PCI_QLOGIC_ISP1280:
409960f6939SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 1280 PCI SCSI Adapter");
410960f6939SMatt Jacob 		break;
411f556e83bSMatt Jacob 	case PCI_QLOGIC_ISP10160:
412f556e83bSMatt Jacob 		device_set_desc(dev, "Qlogic ISP 10160 PCI SCSI Adapter");
413f556e83bSMatt Jacob 		break;
414960f6939SMatt Jacob 	case PCI_QLOGIC_ISP12160:
415e11a1ee8SMatt Jacob 		if (pci_get_subvendor(dev) == AMI_RAID_SUBVENDOR_ID) {
416e11a1ee8SMatt Jacob 			return (ENXIO);
417e11a1ee8SMatt Jacob 		}
418960f6939SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 12160 PCI SCSI Adapter");
41922e1dc85SMatt Jacob 		break;
42065adb54cSMatt Jacob 	case PCI_QLOGIC_ISP2100:
421960f6939SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 2100 PCI FC-AL Adapter");
42265adb54cSMatt Jacob 		break;
4235542fe4bSMatt Jacob 	case PCI_QLOGIC_ISP2200:
424960f6939SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter");
4255542fe4bSMatt Jacob 		break;
426126ec864SMatt Jacob 	case PCI_QLOGIC_ISP2300:
427126ec864SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter");
428126ec864SMatt Jacob 		break;
429126ec864SMatt Jacob 	case PCI_QLOGIC_ISP2312:
430126ec864SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter");
431126ec864SMatt Jacob 		break;
432e5265237SMatt Jacob 	case PCI_QLOGIC_ISP2322:
433e5265237SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter");
434e5265237SMatt Jacob 		break;
4358872e3d7SMatt Jacob 	case PCI_QLOGIC_ISP2422:
4368872e3d7SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter");
4378872e3d7SMatt Jacob 		break;
43841675df0SMatt Jacob 	case PCI_QLOGIC_ISP2432:
43941675df0SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 2432 PCI FC-AL Adapter");
44041675df0SMatt Jacob 		break;
4412df76c16SMatt Jacob 	case PCI_QLOGIC_ISP2532:
4422df76c16SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 2532 PCI FC-AL Adapter");
4432df76c16SMatt Jacob 		break;
444a959d921SMatt Jacob 	case PCI_QLOGIC_ISP5432:
445a959d921SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 5432 PCI FC-AL Adapter");
446a959d921SMatt Jacob 		break;
447dd1419abSMatt Jacob 	case PCI_QLOGIC_ISP6312:
448dd1419abSMatt Jacob 		device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter");
449dd1419abSMatt Jacob 		break;
4509a5af410SMatt Jacob 	case PCI_QLOGIC_ISP6322:
4519a5af410SMatt Jacob 		device_set_desc(dev, "Qlogic ISP 6322 PCI FC-AL Adapter");
4529a5af410SMatt Jacob 		break;
453*218be0b2SAlexander Motin 	case PCI_QLOGIC_ISP2031:
454*218be0b2SAlexander Motin 		device_set_desc(dev, "Qlogic ISP 2031 PCI FC-AL Adapter");
455*218be0b2SAlexander Motin 		break;
45665adb54cSMatt Jacob 	default:
457960f6939SMatt Jacob 		return (ENXIO);
45865adb54cSMatt Jacob 	}
45973030e03SMatt Jacob 	if (isp_announced == 0 && bootverbose) {
460d02373f1SMatt Jacob 		printf("Qlogic ISP Driver, FreeBSD Version %d.%d, "
461a95ae193SMatt Jacob 		    "Core Version %d.%d\n",
462d720e6d5SJustin T. Gibbs 		    ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
463d720e6d5SJustin T. Gibbs 		    ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
46473030e03SMatt Jacob 		isp_announced++;
46565adb54cSMatt Jacob 	}
46656aef503SMatt Jacob 	/*
46756aef503SMatt Jacob 	 * XXXX: Here is where we might load the f/w module
46856aef503SMatt Jacob 	 * XXXX: (or increase a reference count to it).
46956aef503SMatt Jacob 	 */
470b77e575eSWarner Losh 	return (BUS_PROBE_DEFAULT);
47165adb54cSMatt Jacob }
47265adb54cSMatt Jacob 
4739cd7268eSMatt Jacob static void
4749e7d423dSMatt Jacob isp_get_generic_options(device_t dev, ispsoftc_t *isp)
4759cd7268eSMatt Jacob {
4769cd7268eSMatt Jacob 	int tval;
477f7c631bcSMatt Jacob 
4789cd7268eSMatt Jacob 	tval = 0;
4792df76c16SMatt Jacob 	if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fwload_disable", &tval) == 0 && tval != 0) {
4809cd7268eSMatt Jacob 		isp->isp_confopts |= ISP_CFG_NORELOAD;
4819cd7268eSMatt Jacob 	}
4829cd7268eSMatt Jacob 	tval = 0;
4832df76c16SMatt Jacob 	if (resource_int_value(device_get_name(dev), device_get_unit(dev), "ignore_nvram", &tval) == 0 && tval != 0) {
4849cd7268eSMatt Jacob 		isp->isp_confopts |= ISP_CFG_NONVRAM;
4859cd7268eSMatt Jacob 	}
486336b5612SMatt Jacob 	tval = 0;
4872df76c16SMatt Jacob 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev), "debug", &tval);
488336b5612SMatt Jacob 	if (tval) {
489336b5612SMatt Jacob 		isp->isp_dblev = tval;
490336b5612SMatt Jacob 	} else {
491336b5612SMatt Jacob 		isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR;
492336b5612SMatt Jacob 	}
493336b5612SMatt Jacob 	if (bootverbose) {
494336b5612SMatt Jacob 		isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
495336b5612SMatt Jacob 	}
4969e7d423dSMatt Jacob 	tval = -1;
4972df76c16SMatt Jacob 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev), "vports", &tval);
498ffe6ea05SAlexander Motin 	if (tval > 0 && tval <= 254) {
4999e7d423dSMatt Jacob 		isp_nvports = tval;
5002df76c16SMatt Jacob 	}
5012df76c16SMatt Jacob 	tval = 7;
5022df76c16SMatt Jacob 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev), "quickboot_time", &tval);
5032df76c16SMatt Jacob 	isp_quickboot_time = tval;
504336b5612SMatt Jacob }
505336b5612SMatt Jacob 
506336b5612SMatt Jacob static void
5072df76c16SMatt Jacob isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
508336b5612SMatt Jacob {
509336b5612SMatt Jacob 	const char *sptr;
5109e7d423dSMatt Jacob 	int tval = 0;
51107f56f1cSAlexander Motin 	char prefix[12], name[16];
512336b5612SMatt Jacob 
51307f56f1cSAlexander Motin 	if (chan == 0)
51407f56f1cSAlexander Motin 		prefix[0] = 0;
51507f56f1cSAlexander Motin 	else
51607f56f1cSAlexander Motin 		snprintf(prefix, sizeof(prefix), "chan%d.", chan);
51707f56f1cSAlexander Motin 	snprintf(name, sizeof(name), "%siid", prefix);
51807f56f1cSAlexander Motin 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
51907f56f1cSAlexander Motin 	    name, &tval)) {
5202df76c16SMatt Jacob 		if (IS_FC(isp)) {
5212df76c16SMatt Jacob 			ISP_FC_PC(isp, chan)->default_id = 109 - chan;
5222df76c16SMatt Jacob 		} else {
52317bc427dSMarius Strobl #ifdef __sparc64__
52417bc427dSMarius Strobl 			ISP_SPI_PC(isp, chan)->iid = OF_getscsinitid(dev);
52517bc427dSMarius Strobl #else
5262df76c16SMatt Jacob 			ISP_SPI_PC(isp, chan)->iid = 7;
52717bc427dSMarius Strobl #endif
5282df76c16SMatt Jacob 		}
5292df76c16SMatt Jacob 	} else {
5302df76c16SMatt Jacob 		if (IS_FC(isp)) {
5312df76c16SMatt Jacob 			ISP_FC_PC(isp, chan)->default_id = tval - chan;
5322df76c16SMatt Jacob 		} else {
5332df76c16SMatt Jacob 			ISP_SPI_PC(isp, chan)->iid = tval;
5342df76c16SMatt Jacob 		}
535336b5612SMatt Jacob 		isp->isp_confopts |= ISP_CFG_OWNLOOPID;
536336b5612SMatt Jacob 	}
5372df76c16SMatt Jacob 
5383e6deb33SAlexander Motin 	if (IS_SCSI(isp))
5393e6deb33SAlexander Motin 		return;
5403e6deb33SAlexander Motin 
5412df76c16SMatt Jacob 	tval = -1;
54207f56f1cSAlexander Motin 	snprintf(name, sizeof(name), "%srole", prefix);
54307f56f1cSAlexander Motin 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
54407f56f1cSAlexander Motin 	    name, &tval) == 0) {
5452df76c16SMatt Jacob 		switch (tval) {
5462df76c16SMatt Jacob 		case ISP_ROLE_NONE:
5472df76c16SMatt Jacob 		case ISP_ROLE_INITIATOR:
5482df76c16SMatt Jacob 		case ISP_ROLE_TARGET:
54907f56f1cSAlexander Motin 		case ISP_ROLE_BOTH:
55007f56f1cSAlexander Motin 			device_printf(dev, "Chan %d setting role to 0x%x\n", chan, tval);
5512df76c16SMatt Jacob 			break;
5522df76c16SMatt Jacob 		default:
5532df76c16SMatt Jacob 			tval = -1;
5542df76c16SMatt Jacob 			break;
555336b5612SMatt Jacob 		}
556336b5612SMatt Jacob 	}
5572df76c16SMatt Jacob 	if (tval == -1) {
5582df76c16SMatt Jacob 		tval = ISP_DEFAULT_ROLES;
5592df76c16SMatt Jacob 	}
5604ecb1d4aSMatt Jacob 	ISP_FC_PC(isp, chan)->def_role = tval;
561336b5612SMatt Jacob 
5629cd7268eSMatt Jacob 	tval = 0;
56307f56f1cSAlexander Motin 	snprintf(name, sizeof(name), "%sfullduplex", prefix);
56407f56f1cSAlexander Motin 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
56507f56f1cSAlexander Motin 	    name, &tval) == 0 && tval != 0) {
5669cd7268eSMatt Jacob 		isp->isp_confopts |= ISP_CFG_FULL_DUPLEX;
5679cd7268eSMatt Jacob 	}
5689cd7268eSMatt Jacob 	sptr = 0;
56907f56f1cSAlexander Motin 	snprintf(name, sizeof(name), "%stopology", prefix);
57007f56f1cSAlexander Motin 	if (resource_string_value(device_get_name(dev), device_get_unit(dev),
57107f56f1cSAlexander Motin 	    name, (const char **) &sptr) == 0 && sptr != 0) {
5729cd7268eSMatt Jacob 		if (strcmp(sptr, "lport") == 0) {
5739cd7268eSMatt Jacob 			isp->isp_confopts |= ISP_CFG_LPORT;
5749cd7268eSMatt Jacob 		} else if (strcmp(sptr, "nport") == 0) {
5759cd7268eSMatt Jacob 			isp->isp_confopts |= ISP_CFG_NPORT;
5769cd7268eSMatt Jacob 		} else if (strcmp(sptr, "lport-only") == 0) {
5779cd7268eSMatt Jacob 			isp->isp_confopts |= ISP_CFG_LPORT_ONLY;
5789cd7268eSMatt Jacob 		} else if (strcmp(sptr, "nport-only") == 0) {
5799cd7268eSMatt Jacob 			isp->isp_confopts |= ISP_CFG_NPORT_ONLY;
5809cd7268eSMatt Jacob 		}
581960f6939SMatt Jacob 	}
582960f6939SMatt Jacob 
583387d8239SMatt Jacob 	tval = 0;
58407f56f1cSAlexander Motin 	snprintf(name, sizeof(name), "%snofctape", prefix);
58507f56f1cSAlexander Motin 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
58607f56f1cSAlexander Motin 	    name, &tval);
587387d8239SMatt Jacob 	if (tval) {
588387d8239SMatt Jacob 		isp->isp_confopts |= ISP_CFG_NOFCTAPE;
589387d8239SMatt Jacob 	}
590387d8239SMatt Jacob 
591387d8239SMatt Jacob 	tval = 0;
59207f56f1cSAlexander Motin 	snprintf(name, sizeof(name), "%sfctape", prefix);
59307f56f1cSAlexander Motin 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
59407f56f1cSAlexander Motin 	    name, &tval);
595387d8239SMatt Jacob 	if (tval) {
596387d8239SMatt Jacob 		isp->isp_confopts &= ~ISP_CFG_NOFCTAPE;
597387d8239SMatt Jacob 		isp->isp_confopts |= ISP_CFG_FCTAPE;
598387d8239SMatt Jacob 	}
599387d8239SMatt Jacob 
600387d8239SMatt Jacob 
6019ba86737SMatt Jacob 	/*
6029cd7268eSMatt Jacob 	 * Because the resource_*_value functions can neither return
6039cd7268eSMatt Jacob 	 * 64 bit integer values, nor can they be directly coerced
6049cd7268eSMatt Jacob 	 * to interpret the right hand side of the assignment as
6059cd7268eSMatt Jacob 	 * you want them to interpret it, we have to force WWN
6069cd7268eSMatt Jacob 	 * hint replacement to specify WWN strings with a leading
6079cd7268eSMatt Jacob 	 * 'w' (e..g w50000000aaaa0001). Sigh.
6089cd7268eSMatt Jacob 	 */
6099cd7268eSMatt Jacob 	sptr = 0;
61007f56f1cSAlexander Motin 	snprintf(name, sizeof(name), "%sportwwn", prefix);
61107f56f1cSAlexander Motin 	tval = resource_string_value(device_get_name(dev), device_get_unit(dev),
61207f56f1cSAlexander Motin 	    name, (const char **) &sptr);
6139cd7268eSMatt Jacob 	if (tval == 0 && sptr != 0 && *sptr++ == 'w') {
6149cd7268eSMatt Jacob 		char *eptr = 0;
6152df76c16SMatt Jacob 		ISP_FC_PC(isp, chan)->def_wwpn = strtouq(sptr, &eptr, 16);
6162df76c16SMatt Jacob 		if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwpn == -1) {
6179cd7268eSMatt Jacob 			device_printf(dev, "mangled portwwn hint '%s'\n", sptr);
6182df76c16SMatt Jacob 			ISP_FC_PC(isp, chan)->def_wwpn = 0;
6199cd7268eSMatt Jacob 		}
6209cd7268eSMatt Jacob 	}
6219cd7268eSMatt Jacob 
6229cd7268eSMatt Jacob 	sptr = 0;
62307f56f1cSAlexander Motin 	snprintf(name, sizeof(name), "%snodewwn", prefix);
62407f56f1cSAlexander Motin 	tval = resource_string_value(device_get_name(dev), device_get_unit(dev),
62507f56f1cSAlexander Motin 	    name, (const char **) &sptr);
6269cd7268eSMatt Jacob 	if (tval == 0 && sptr != 0 && *sptr++ == 'w') {
6279cd7268eSMatt Jacob 		char *eptr = 0;
6282df76c16SMatt Jacob 		ISP_FC_PC(isp, chan)->def_wwnn = strtouq(sptr, &eptr, 16);
6292df76c16SMatt Jacob 		if (eptr < sptr + 16 || ISP_FC_PC(isp, chan)->def_wwnn == 0) {
6309cd7268eSMatt Jacob 			device_printf(dev, "mangled nodewwn hint '%s'\n", sptr);
6312df76c16SMatt Jacob 			ISP_FC_PC(isp, chan)->def_wwnn = 0;
6329cd7268eSMatt Jacob 		}
6339cd7268eSMatt Jacob 	}
6349cd7268eSMatt Jacob 
635f7c631bcSMatt Jacob 	tval = -1;
63607f56f1cSAlexander Motin 	snprintf(name, sizeof(name), "%sloop_down_limit", prefix);
63707f56f1cSAlexander Motin 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
63807f56f1cSAlexander Motin 	    name, &tval);
63910365e5aSMatt Jacob 	if (tval >= 0 && tval < 0xffff) {
6402df76c16SMatt Jacob 		ISP_FC_PC(isp, chan)->loop_down_limit = tval;
64110365e5aSMatt Jacob 	} else {
6422df76c16SMatt Jacob 		ISP_FC_PC(isp, chan)->loop_down_limit = isp_loop_down_limit;
64310365e5aSMatt Jacob 	}
64410365e5aSMatt Jacob 
645f7c631bcSMatt Jacob 	tval = -1;
64607f56f1cSAlexander Motin 	snprintf(name, sizeof(name), "%sgone_device_time", prefix);
64707f56f1cSAlexander Motin 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
64807f56f1cSAlexander Motin 	    name, &tval);
649f7c631bcSMatt Jacob 	if (tval >= 0 && tval < 0xffff) {
6502df76c16SMatt Jacob 		ISP_FC_PC(isp, chan)->gone_device_time = tval;
651f7c631bcSMatt Jacob 	} else {
6522df76c16SMatt Jacob 		ISP_FC_PC(isp, chan)->gone_device_time = isp_gone_device_time;
653f7c631bcSMatt Jacob 	}
6549cd7268eSMatt Jacob }
6559cd7268eSMatt Jacob 
6569cd7268eSMatt Jacob static int
6579cd7268eSMatt Jacob isp_pci_attach(device_t dev)
6589cd7268eSMatt Jacob {
659*218be0b2SAlexander Motin 	int i, locksetup = 0;
6602df76c16SMatt Jacob 	uint32_t data, cmd, linesz, did;
6619cd7268eSMatt Jacob 	struct isp_pcisoftc *pcs;
662a035b0afSMatt Jacob 	ispsoftc_t *isp;
6632df76c16SMatt Jacob 	size_t psize, xsize;
6642df76c16SMatt Jacob 	char fwname[32];
6659cd7268eSMatt Jacob 
6669cd7268eSMatt Jacob 	pcs = device_get_softc(dev);
6679cd7268eSMatt Jacob 	if (pcs == NULL) {
6689cd7268eSMatt Jacob 		device_printf(dev, "cannot get softc\n");
6699cd7268eSMatt Jacob 		return (ENOMEM);
6709cd7268eSMatt Jacob 	}
6719cd7268eSMatt Jacob 	memset(pcs, 0, sizeof (*pcs));
6722df76c16SMatt Jacob 
6739cd7268eSMatt Jacob 	pcs->pci_dev = dev;
6749cd7268eSMatt Jacob 	isp = &pcs->pci_isp;
6752df76c16SMatt Jacob 	isp->isp_dev = dev;
6762df76c16SMatt Jacob 	isp->isp_nchan = 1;
677387d8239SMatt Jacob 	if (sizeof (bus_addr_t) > 4)
678387d8239SMatt Jacob 		isp->isp_osinfo.sixtyfourbit = 1;
6799cd7268eSMatt Jacob 
6809cd7268eSMatt Jacob 	/*
681336b5612SMatt Jacob 	 * Get Generic Options
6829cd7268eSMatt Jacob 	 */
6839e7d423dSMatt Jacob 	isp_nvports = 0;
6849e7d423dSMatt Jacob 	isp_get_generic_options(dev, isp);
6859cd7268eSMatt Jacob 
686ab6d0040SMatt Jacob 	linesz = PCI_DFLT_LNSZ;
687e95725cbSMatt Jacob 	pcs->irq = pcs->regs = NULL;
688e95725cbSMatt Jacob 	pcs->rgd = pcs->rtp = pcs->iqd = 0;
689960f6939SMatt Jacob 
6902df76c16SMatt Jacob 	pcs->pci_dev = dev;
691d59bd469SMatt Jacob 	pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
692d59bd469SMatt Jacob 	pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
693d59bd469SMatt Jacob 	pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
694d59bd469SMatt Jacob 	pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF;
695d59bd469SMatt Jacob 	pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
6962df76c16SMatt Jacob 
6972df76c16SMatt Jacob 	switch (pci_get_devid(dev)) {
6982df76c16SMatt Jacob 	case PCI_QLOGIC_ISP1020:
6992df76c16SMatt Jacob 		did = 0x1040;
7002df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec;
7012df76c16SMatt Jacob 		isp->isp_type = ISP_HA_SCSI_UNKNOWN;
7022df76c16SMatt Jacob 		break;
7032df76c16SMatt Jacob 	case PCI_QLOGIC_ISP1080:
7042df76c16SMatt Jacob 		did = 0x1080;
7052df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_1080;
7062df76c16SMatt Jacob 		isp->isp_type = ISP_HA_SCSI_1080;
7072df76c16SMatt Jacob 		pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
7082df76c16SMatt Jacob 		break;
7092df76c16SMatt Jacob 	case PCI_QLOGIC_ISP1240:
7102df76c16SMatt Jacob 		did = 0x1080;
7112df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_1080;
7122df76c16SMatt Jacob 		isp->isp_type = ISP_HA_SCSI_1240;
7132df76c16SMatt Jacob 		isp->isp_nchan = 2;
7142df76c16SMatt Jacob 		pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
7152df76c16SMatt Jacob 		break;
7162df76c16SMatt Jacob 	case PCI_QLOGIC_ISP1280:
7172df76c16SMatt Jacob 		did = 0x1080;
7182df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_1080;
7192df76c16SMatt Jacob 		isp->isp_type = ISP_HA_SCSI_1280;
7202df76c16SMatt Jacob 		pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
7212df76c16SMatt Jacob 		break;
7222df76c16SMatt Jacob 	case PCI_QLOGIC_ISP10160:
7232df76c16SMatt Jacob 		did = 0x12160;
7242df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_12160;
7252df76c16SMatt Jacob 		isp->isp_type = ISP_HA_SCSI_10160;
7262df76c16SMatt Jacob 		pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
7272df76c16SMatt Jacob 		break;
7282df76c16SMatt Jacob 	case PCI_QLOGIC_ISP12160:
7292df76c16SMatt Jacob 		did = 0x12160;
7302df76c16SMatt Jacob 		isp->isp_nchan = 2;
7312df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_12160;
7322df76c16SMatt Jacob 		isp->isp_type = ISP_HA_SCSI_12160;
7332df76c16SMatt Jacob 		pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = ISP1080_DMA_REGS_OFF;
7342df76c16SMatt Jacob 		break;
7352df76c16SMatt Jacob 	case PCI_QLOGIC_ISP2100:
7362df76c16SMatt Jacob 		did = 0x2100;
7372df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_2100;
7382df76c16SMatt Jacob 		isp->isp_type = ISP_HA_FC_2100;
7392df76c16SMatt Jacob 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF;
740960f6939SMatt Jacob 		if (pci_get_revid(dev) < 3) {
741ab6d0040SMatt Jacob 			/*
742ab6d0040SMatt Jacob 			 * XXX: Need to get the actual revision
743ab6d0040SMatt Jacob 			 * XXX: number of the 2100 FB. At any rate,
744ab6d0040SMatt Jacob 			 * XXX: lower cache line size for early revision
745ab6d0040SMatt Jacob 			 * XXX; boards.
746ab6d0040SMatt Jacob 			 */
747ab6d0040SMatt Jacob 			linesz = 1;
748ab6d0040SMatt Jacob 		}
7492df76c16SMatt Jacob 		break;
7502df76c16SMatt Jacob 	case PCI_QLOGIC_ISP2200:
7512df76c16SMatt Jacob 		did = 0x2200;
7522df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_2200;
7532df76c16SMatt Jacob 		isp->isp_type = ISP_HA_FC_2200;
7542df76c16SMatt Jacob 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2100_OFF;
7552df76c16SMatt Jacob 		break;
7562df76c16SMatt Jacob 	case PCI_QLOGIC_ISP2300:
7572df76c16SMatt Jacob 		did = 0x2300;
7582df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_2300;
7592df76c16SMatt Jacob 		isp->isp_type = ISP_HA_FC_2300;
7602df76c16SMatt Jacob 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF;
7612df76c16SMatt Jacob 		break;
7622df76c16SMatt Jacob 	case PCI_QLOGIC_ISP2312:
7632df76c16SMatt Jacob 	case PCI_QLOGIC_ISP6312:
7642df76c16SMatt Jacob 		did = 0x2300;
7652df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_2300;
7662df76c16SMatt Jacob 		isp->isp_type = ISP_HA_FC_2312;
7672df76c16SMatt Jacob 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF;
7682df76c16SMatt Jacob 		break;
7692df76c16SMatt Jacob 	case PCI_QLOGIC_ISP2322:
7702df76c16SMatt Jacob 	case PCI_QLOGIC_ISP6322:
7712df76c16SMatt Jacob 		did = 0x2322;
7722df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_2300;
7732df76c16SMatt Jacob 		isp->isp_type = ISP_HA_FC_2322;
7742df76c16SMatt Jacob 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2300_OFF;
7752df76c16SMatt Jacob 		break;
7762df76c16SMatt Jacob 	case PCI_QLOGIC_ISP2422:
7772df76c16SMatt Jacob 	case PCI_QLOGIC_ISP2432:
7782df76c16SMatt Jacob 		did = 0x2400;
7792df76c16SMatt Jacob 		isp->isp_nchan += isp_nvports;
7802df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_2400;
7812df76c16SMatt Jacob 		isp->isp_type = ISP_HA_FC_2400;
7822df76c16SMatt Jacob 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF;
7832df76c16SMatt Jacob 		break;
7842df76c16SMatt Jacob 	case PCI_QLOGIC_ISP2532:
7852df76c16SMatt Jacob 		did = 0x2500;
7862df76c16SMatt Jacob 		isp->isp_nchan += isp_nvports;
7872df76c16SMatt Jacob 		isp->isp_mdvec = &mdvec_2500;
7882df76c16SMatt Jacob 		isp->isp_type = ISP_HA_FC_2500;
7892df76c16SMatt Jacob 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF;
7902df76c16SMatt Jacob 		break;
791a959d921SMatt Jacob 	case PCI_QLOGIC_ISP5432:
792a959d921SMatt Jacob 		did = 0x2500;
793a959d921SMatt Jacob 		isp->isp_mdvec = &mdvec_2500;
794a959d921SMatt Jacob 		isp->isp_type = ISP_HA_FC_2500;
795a959d921SMatt Jacob 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF;
796a959d921SMatt Jacob 		break;
797*218be0b2SAlexander Motin 	case PCI_QLOGIC_ISP2031:
798*218be0b2SAlexander Motin 		did = 0x2600;
799*218be0b2SAlexander Motin 		isp->isp_nchan += isp_nvports;
800*218be0b2SAlexander Motin 		isp->isp_mdvec = &mdvec_2600;
801*218be0b2SAlexander Motin 		isp->isp_type = ISP_HA_FC_2600;
802*218be0b2SAlexander Motin 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF;
803*218be0b2SAlexander Motin 		break;
8042df76c16SMatt Jacob 	default:
8052df76c16SMatt Jacob 		device_printf(dev, "unknown device type\n");
8062df76c16SMatt Jacob 		goto bad;
8072df76c16SMatt Jacob 		break;
80865adb54cSMatt Jacob 	}
8092df76c16SMatt Jacob 	isp->isp_revision = pci_get_revid(dev);
8102df76c16SMatt Jacob 
811*218be0b2SAlexander Motin 	if (IS_26XX(isp)) {
812*218be0b2SAlexander Motin 		pcs->rtp = SYS_RES_MEMORY;
813*218be0b2SAlexander Motin 		pcs->rgd = PCIR_BAR(0);
814*218be0b2SAlexander Motin 		pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd,
815*218be0b2SAlexander Motin 		    RF_ACTIVE);
816*218be0b2SAlexander Motin 	} else {
817*218be0b2SAlexander Motin 		pcs->rtp = SYS_RES_MEMORY;
818*218be0b2SAlexander Motin 		pcs->rgd = PCIR_BAR(1);
819*218be0b2SAlexander Motin 		pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd,
820*218be0b2SAlexander Motin 		    RF_ACTIVE);
821*218be0b2SAlexander Motin 		if (pcs->regs == NULL) {
822*218be0b2SAlexander Motin 			pcs->rtp = SYS_RES_IOPORT;
823*218be0b2SAlexander Motin 			pcs->rgd = PCIR_BAR(0);
824*218be0b2SAlexander Motin 			pcs->regs = bus_alloc_resource_any(dev, pcs->rtp,
825*218be0b2SAlexander Motin 			    &pcs->rgd, RF_ACTIVE);
826*218be0b2SAlexander Motin 		}
827*218be0b2SAlexander Motin 	}
828*218be0b2SAlexander Motin 	if (pcs->regs == NULL) {
829*218be0b2SAlexander Motin 		device_printf(dev, "Unable to map any ports\n");
830*218be0b2SAlexander Motin 		goto bad;
831*218be0b2SAlexander Motin 	}
832*218be0b2SAlexander Motin 	if (bootverbose) {
833*218be0b2SAlexander Motin 		device_printf(dev, "Using %s space register mapping\n",
834*218be0b2SAlexander Motin 		    (pcs->rtp == SYS_RES_IOPORT)? "I/O" : "Memory");
835*218be0b2SAlexander Motin 	}
836*218be0b2SAlexander Motin 	isp->isp_bus_tag = rman_get_bustag(pcs->regs);
837*218be0b2SAlexander Motin 	isp->isp_bus_handle = rman_get_bushandle(pcs->regs);
838*218be0b2SAlexander Motin 
8392df76c16SMatt Jacob 	if (IS_FC(isp)) {
840222bb542SMatt Jacob 		psize = sizeof (fcparam);
8412df76c16SMatt Jacob 		xsize = sizeof (struct isp_fc);
8422df76c16SMatt Jacob 	} else {
8432df76c16SMatt Jacob 		psize = sizeof (sdparam);
8442df76c16SMatt Jacob 		xsize = sizeof (struct isp_spi);
845222bb542SMatt Jacob 	}
8462df76c16SMatt Jacob 	psize *= isp->isp_nchan;
8472df76c16SMatt Jacob 	xsize *= isp->isp_nchan;
8487cc0979fSDavid Malone 	isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO);
849c6608df3SMatt Jacob 	if (isp->isp_param == NULL) {
850960f6939SMatt Jacob 		device_printf(dev, "cannot allocate parameter data\n");
851960f6939SMatt Jacob 		goto bad;
852c6608df3SMatt Jacob 	}
8532df76c16SMatt Jacob 	isp->isp_osinfo.pc.ptr = malloc(xsize, M_DEVBUF, M_NOWAIT | M_ZERO);
8542df76c16SMatt Jacob 	if (isp->isp_osinfo.pc.ptr == NULL) {
8552df76c16SMatt Jacob 		device_printf(dev, "cannot allocate parameter data\n");
8562df76c16SMatt Jacob 		goto bad;
8572df76c16SMatt Jacob 	}
85865adb54cSMatt Jacob 
859336b5612SMatt Jacob 	/*
860336b5612SMatt Jacob 	 * Now that we know who we are (roughly) get/set specific options
861336b5612SMatt Jacob 	 */
8622df76c16SMatt Jacob 	for (i = 0; i < isp->isp_nchan; i++) {
8632df76c16SMatt Jacob 		isp_get_specific_options(dev, i, isp);
8649a5af410SMatt Jacob 	}
8659a5af410SMatt Jacob 
8669a5af410SMatt Jacob 	isp->isp_osinfo.fw = NULL;
8679a5af410SMatt Jacob 	if (isp->isp_osinfo.fw == NULL) {
8689a5af410SMatt Jacob 		snprintf(fwname, sizeof (fwname), "isp_%04x", did);
8699a5af410SMatt Jacob 		isp->isp_osinfo.fw = firmware_get(fwname);
8709a5af410SMatt Jacob 	}
8719a5af410SMatt Jacob 	if (isp->isp_osinfo.fw != NULL) {
872ad0ab753SMatt Jacob 		isp_prt(isp, ISP_LOGCONFIG, "loaded firmware %s", fwname);
8735f634111SMatt Jacob 		isp->isp_mdvec->dv_ispfw = isp->isp_osinfo.fw->data;
8749a5af410SMatt Jacob 	}
87556aef503SMatt Jacob 
87656aef503SMatt Jacob 	/*
877ad0ab753SMatt Jacob 	 * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set.
878d951bbcaSMatt Jacob 	 */
879c68534f1SScott Long 	cmd = pci_read_config(dev, PCIR_COMMAND, 2);
8809e7d423dSMatt Jacob 	cmd |= PCIM_CMD_SEREN | PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN;
88175c1e828SMatt Jacob 	if (IS_2300(isp)) {	/* per QLogic errata */
88275c1e828SMatt Jacob 		cmd &= ~PCIM_CMD_INVEN;
88375c1e828SMatt Jacob 	}
8848a97c03aSMatt Jacob 	if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) {
8858a97c03aSMatt Jacob 		cmd &= ~PCIM_CMD_INTX_DISABLE;
8868a97c03aSMatt Jacob 	}
88706cacb29SMatt Jacob 	if (IS_24XX(isp)) {
88806cacb29SMatt Jacob 		cmd &= ~PCIM_CMD_INTX_DISABLE;
88906cacb29SMatt Jacob 	}
890b49c4674SMatt Jacob 	pci_write_config(dev, PCIR_COMMAND, cmd, 2);
891ab6d0040SMatt Jacob 
892d951bbcaSMatt Jacob 	/*
893222bb542SMatt Jacob 	 * Make sure the Cache Line Size register is set sensibly.
894d951bbcaSMatt Jacob 	 */
895960f6939SMatt Jacob 	data = pci_read_config(dev, PCIR_CACHELNSZ, 1);
8966a7d12e1SMatt Jacob 	if (data == 0 || (linesz != PCI_DFLT_LNSZ && data != linesz)) {
897ad0ab753SMatt Jacob 		isp_prt(isp, ISP_LOGDEBUG0, "set PCI line size to %d from %d", linesz, data);
8986a7d12e1SMatt Jacob 		data = linesz;
899960f6939SMatt Jacob 		pci_write_config(dev, PCIR_CACHELNSZ, data, 1);
900d951bbcaSMatt Jacob 	}
901ab6d0040SMatt Jacob 
902d951bbcaSMatt Jacob 	/*
903d951bbcaSMatt Jacob 	 * Make sure the Latency Timer is sane.
904d951bbcaSMatt Jacob 	 */
905960f6939SMatt Jacob 	data = pci_read_config(dev, PCIR_LATTIMER, 1);
906d951bbcaSMatt Jacob 	if (data < PCI_DFLT_LTNCY) {
907d951bbcaSMatt Jacob 		data = PCI_DFLT_LTNCY;
908ad0ab753SMatt Jacob 		isp_prt(isp, ISP_LOGDEBUG0, "set PCI latency to %d", data);
909960f6939SMatt Jacob 		pci_write_config(dev, PCIR_LATTIMER, data, 1);
910d951bbcaSMatt Jacob 	}
911ab6d0040SMatt Jacob 
912ab6d0040SMatt Jacob 	/*
913ab6d0040SMatt Jacob 	 * Make sure we've disabled the ROM.
914ab6d0040SMatt Jacob 	 */
915960f6939SMatt Jacob 	data = pci_read_config(dev, PCIR_ROMADDR, 4);
916ab6d0040SMatt Jacob 	data &= ~1;
917960f6939SMatt Jacob 	pci_write_config(dev, PCIR_ROMADDR, data, 4);
9182df76c16SMatt Jacob 
9192df76c16SMatt Jacob 	/*
9202df76c16SMatt Jacob 	 * Do MSI
9212df76c16SMatt Jacob 	 *
9222df76c16SMatt Jacob 	 * NB: MSI-X needs to be disabled for the 2432 (PCI-Express)
9232df76c16SMatt Jacob 	 */
9240a70657fSMatt Jacob 	if (IS_24XX(isp) || IS_2322(isp)) {
9250a70657fSMatt Jacob 		pcs->msicount = pci_msi_count(dev);
9260a70657fSMatt Jacob 		if (pcs->msicount > 1) {
9270a70657fSMatt Jacob 			pcs->msicount = 1;
9280a70657fSMatt Jacob 		}
9290a70657fSMatt Jacob 		if (pci_alloc_msi(dev, &pcs->msicount) == 0) {
930e95725cbSMatt Jacob 			pcs->iqd = 1;
9310a70657fSMatt Jacob 		} else {
932e95725cbSMatt Jacob 			pcs->iqd = 0;
9330a70657fSMatt Jacob 		}
9340a70657fSMatt Jacob 	}
935e95725cbSMatt Jacob 	pcs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &pcs->iqd, RF_ACTIVE | RF_SHAREABLE);
936e95725cbSMatt Jacob 	if (pcs->irq == NULL) {
937960f6939SMatt Jacob 		device_printf(dev, "could not allocate interrupt\n");
938960f6939SMatt Jacob 		goto bad;
939960f6939SMatt Jacob 	}
940960f6939SMatt Jacob 
941f09b1922SMatt Jacob 	/* Make sure the lock is set up. */
9426008862bSJohn Baldwin 	mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
943f09b1922SMatt Jacob 	locksetup++;
944f09b1922SMatt Jacob 
945e95725cbSMatt Jacob 	if (isp_setup_intr(dev, pcs->irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) {
946f09b1922SMatt Jacob 		device_printf(dev, "could not setup interrupt\n");
947f09b1922SMatt Jacob 		goto bad;
948f09b1922SMatt Jacob 	}
949960f6939SMatt Jacob 
95005fbcbb0SMatt Jacob 	/*
95175c1e828SMatt Jacob 	 * Last minute checks...
95275c1e828SMatt Jacob 	 */
95310365e5aSMatt Jacob 	if (IS_23XX(isp) || IS_24XX(isp)) {
95475c1e828SMatt Jacob 		isp->isp_port = pci_get_function(dev);
95575c1e828SMatt Jacob 	}
95675c1e828SMatt Jacob 
95775c1e828SMatt Jacob 	/*
95805fbcbb0SMatt Jacob 	 * Make sure we're in reset state.
95905fbcbb0SMatt Jacob 	 */
9603395b056SMatt Jacob 	ISP_LOCK(isp);
961dfd24649SAlexander Motin 	if (isp_reinit(isp, 1) != 0) {
9623395b056SMatt Jacob 		ISP_UNLOCK(isp);
963960f6939SMatt Jacob 		goto bad;
96465adb54cSMatt Jacob 	}
9652df76c16SMatt Jacob 	ISP_UNLOCK(isp);
9662df76c16SMatt Jacob 	if (isp_attach(isp)) {
9672df76c16SMatt Jacob 		ISP_LOCK(isp);
96865adb54cSMatt Jacob 		isp_uninit(isp);
9693395b056SMatt Jacob 		ISP_UNLOCK(isp);
970960f6939SMatt Jacob 		goto bad;
971d59bd469SMatt Jacob 	}
972960f6939SMatt Jacob 	return (0);
973960f6939SMatt Jacob 
974960f6939SMatt Jacob bad:
975a035b0afSMatt Jacob 	if (pcs->ih) {
976e95725cbSMatt Jacob 		(void) bus_teardown_intr(dev, pcs->irq, pcs->ih);
977960f6939SMatt Jacob 	}
978a035b0afSMatt Jacob 	if (locksetup) {
9793395b056SMatt Jacob 		mtx_destroy(&isp->isp_osinfo.lock);
9803395b056SMatt Jacob 	}
981e95725cbSMatt Jacob 	if (pcs->irq) {
982e95725cbSMatt Jacob 		(void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq);
983960f6939SMatt Jacob 	}
984a035b0afSMatt Jacob 	if (pcs->msicount) {
9850a70657fSMatt Jacob 		pci_release_msi(dev);
9860a70657fSMatt Jacob 	}
987e95725cbSMatt Jacob 	if (pcs->regs) {
988e95725cbSMatt Jacob 		(void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
989960f6939SMatt Jacob 	}
9909cd7268eSMatt Jacob 	if (pcs->pci_isp.isp_param) {
991960f6939SMatt Jacob 		free(pcs->pci_isp.isp_param, M_DEVBUF);
9922df76c16SMatt Jacob 		pcs->pci_isp.isp_param = NULL;
9932df76c16SMatt Jacob 	}
9942df76c16SMatt Jacob 	if (pcs->pci_isp.isp_osinfo.pc.ptr) {
9952df76c16SMatt Jacob 		free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF);
9962df76c16SMatt Jacob 		pcs->pci_isp.isp_osinfo.pc.ptr = NULL;
9979cd7268eSMatt Jacob 	}
998960f6939SMatt Jacob 	return (ENXIO);
99965adb54cSMatt Jacob }
100065adb54cSMatt Jacob 
100110365e5aSMatt Jacob static int
100210365e5aSMatt Jacob isp_pci_detach(device_t dev)
100310365e5aSMatt Jacob {
100410365e5aSMatt Jacob 	struct isp_pcisoftc *pcs;
100510365e5aSMatt Jacob 	ispsoftc_t *isp;
1006e95725cbSMatt Jacob 	int status;
100710365e5aSMatt Jacob 
100810365e5aSMatt Jacob 	pcs = device_get_softc(dev);
100910365e5aSMatt Jacob 	if (pcs == NULL) {
101010365e5aSMatt Jacob 		return (ENXIO);
101110365e5aSMatt Jacob 	}
101210365e5aSMatt Jacob 	isp = (ispsoftc_t *) pcs;
1013e95725cbSMatt Jacob 	status = isp_detach(isp);
1014e95725cbSMatt Jacob 	if (status)
1015e95725cbSMatt Jacob 		return (status);
1016e95725cbSMatt Jacob 	ISP_LOCK(isp);
1017e95725cbSMatt Jacob 	isp_uninit(isp);
1018e95725cbSMatt Jacob 	if (pcs->ih) {
1019e95725cbSMatt Jacob 		(void) bus_teardown_intr(dev, pcs->irq, pcs->ih);
1020e95725cbSMatt Jacob 	}
1021e95725cbSMatt Jacob 	ISP_UNLOCK(isp);
10222df76c16SMatt Jacob 	mtx_destroy(&isp->isp_osinfo.lock);
1023e95725cbSMatt Jacob 	(void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq);
1024e95725cbSMatt Jacob 	if (pcs->msicount) {
1025e95725cbSMatt Jacob 		pci_release_msi(dev);
1026e95725cbSMatt Jacob 	}
1027e95725cbSMatt Jacob 	(void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
1028387d8239SMatt Jacob 	/*
1029387d8239SMatt Jacob 	 * XXX: THERE IS A LOT OF LEAKAGE HERE
1030387d8239SMatt Jacob 	 */
1031e95725cbSMatt Jacob 	if (pcs->pci_isp.isp_param) {
1032e95725cbSMatt Jacob 		free(pcs->pci_isp.isp_param, M_DEVBUF);
1033e95725cbSMatt Jacob 		pcs->pci_isp.isp_param = NULL;
1034e95725cbSMatt Jacob 	}
1035e95725cbSMatt Jacob 	if (pcs->pci_isp.isp_osinfo.pc.ptr) {
1036e95725cbSMatt Jacob 		free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF);
1037e95725cbSMatt Jacob 		pcs->pci_isp.isp_osinfo.pc.ptr = NULL;
1038e95725cbSMatt Jacob 	}
103910365e5aSMatt Jacob 	return (0);
104010365e5aSMatt Jacob }
104110365e5aSMatt Jacob 
1042126ec864SMatt Jacob #define	IspVirt2Off(a, x)	\
1043126ec864SMatt Jacob 	(((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \
10444cc9e3e7SMatt Jacob 	_BLK_REG_SHFT] + ((x) & 0xfff))
1045126ec864SMatt Jacob 
10466a7d12e1SMatt Jacob #define	BXR2(isp, off)		\
10476a7d12e1SMatt Jacob 	bus_space_read_2(isp->isp_bus_tag, isp->isp_bus_handle, off)
10486a7d12e1SMatt Jacob #define	BXW2(isp, off, v)	\
10496a7d12e1SMatt Jacob 	bus_space_write_2(isp->isp_bus_tag, isp->isp_bus_handle, off, v)
10506a7d12e1SMatt Jacob #define	BXR4(isp, off)		\
10516a7d12e1SMatt Jacob 	bus_space_read_4(isp->isp_bus_tag, isp->isp_bus_handle, off)
10526a7d12e1SMatt Jacob #define	BXW4(isp, off, v)	\
10536a7d12e1SMatt Jacob 	bus_space_write_4(isp->isp_bus_tag, isp->isp_bus_handle, off, v)
1054126ec864SMatt Jacob 
1055126ec864SMatt Jacob 
10562df76c16SMatt Jacob static ISP_INLINE int
10579cd7268eSMatt Jacob isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp)
1058126ec864SMatt Jacob {
105910365e5aSMatt Jacob 	uint32_t val0, val1;
1060126ec864SMatt Jacob 	int i = 0;
1061126ec864SMatt Jacob 
1062126ec864SMatt Jacob 	do {
10636a7d12e1SMatt Jacob 		val0 = BXR2(isp, IspVirt2Off(isp, off));
10646a7d12e1SMatt Jacob 		val1 = BXR2(isp, IspVirt2Off(isp, off));
1065126ec864SMatt Jacob 	} while (val0 != val1 && ++i < 1000);
1066126ec864SMatt Jacob 	if (val0 != val1) {
1067126ec864SMatt Jacob 		return (1);
1068126ec864SMatt Jacob 	}
1069126ec864SMatt Jacob 	*rp = val0;
1070126ec864SMatt Jacob 	return (0);
1071126ec864SMatt Jacob }
1072126ec864SMatt Jacob 
1073126ec864SMatt Jacob static int
10746ce548a1SAlexander Motin isp_pci_rd_isr(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info)
1075126ec864SMatt Jacob {
10761dae40ebSMatt Jacob 	uint16_t isr, sema;
1077126ec864SMatt Jacob 
1078126ec864SMatt Jacob 	if (IS_2100(isp)) {
1079126ec864SMatt Jacob 		if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) {
1080126ec864SMatt Jacob 		    return (0);
1081126ec864SMatt Jacob 		}
1082126ec864SMatt Jacob 		if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) {
1083126ec864SMatt Jacob 		    return (0);
1084126ec864SMatt Jacob 		}
1085126ec864SMatt Jacob 	} else {
10866a7d12e1SMatt Jacob 		isr = BXR2(isp, IspVirt2Off(isp, BIU_ISR));
10876a7d12e1SMatt Jacob 		sema = BXR2(isp, IspVirt2Off(isp, BIU_SEMA));
1088126ec864SMatt Jacob 	}
1089126ec864SMatt Jacob 	isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema);
1090126ec864SMatt Jacob 	isr &= INT_PENDING_MASK(isp);
1091126ec864SMatt Jacob 	sema &= BIU_SEMA_LOCK;
1092126ec864SMatt Jacob 	if (isr == 0 && sema == 0) {
1093126ec864SMatt Jacob 		return (0);
1094126ec864SMatt Jacob 	}
1095126ec864SMatt Jacob 	*isrp = isr;
1096126ec864SMatt Jacob 	if ((*semap = sema) != 0) {
1097126ec864SMatt Jacob 		if (IS_2100(isp)) {
10986ce548a1SAlexander Motin 			if (isp_pci_rd_debounced(isp, OUTMAILBOX0, info)) {
1099126ec864SMatt Jacob 				return (0);
1100126ec864SMatt Jacob 			}
1101126ec864SMatt Jacob 		} else {
11026ce548a1SAlexander Motin 			*info = BXR2(isp, IspVirt2Off(isp, OUTMAILBOX0));
1103126ec864SMatt Jacob 		}
1104126ec864SMatt Jacob 	}
1105126ec864SMatt Jacob 	return (1);
1106126ec864SMatt Jacob }
1107126ec864SMatt Jacob 
1108126ec864SMatt Jacob static int
11096ce548a1SAlexander Motin isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info)
1110126ec864SMatt Jacob {
11116ce548a1SAlexander Motin 	uint32_t hccr, r2hisr;
1112126ec864SMatt Jacob 
11136a7d12e1SMatt Jacob 	if (!(BXR2(isp, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) {
11143bd40330SMatt Jacob 		*isrp = 0;
1115db4fa023SMatt Jacob 		return (0);
11163bd40330SMatt Jacob 	}
11176a7d12e1SMatt Jacob 	r2hisr = BXR4(isp, IspVirt2Off(isp, BIU_R2HSTSLO));
1118126ec864SMatt Jacob 	isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr);
1119126ec864SMatt Jacob 	if ((r2hisr & BIU_R2HST_INTR) == 0) {
1120126ec864SMatt Jacob 		*isrp = 0;
1121126ec864SMatt Jacob 		return (0);
1122126ec864SMatt Jacob 	}
11236ce548a1SAlexander Motin 	switch ((*isrp = r2hisr & BIU_R2HST_ISTAT_MASK)) {
1124126ec864SMatt Jacob 	case ISPR2HST_ROM_MBX_OK:
1125126ec864SMatt Jacob 	case ISPR2HST_ROM_MBX_FAIL:
1126126ec864SMatt Jacob 	case ISPR2HST_MBX_OK:
1127126ec864SMatt Jacob 	case ISPR2HST_MBX_FAIL:
1128126ec864SMatt Jacob 	case ISPR2HST_ASYNC_EVENT:
1129126ec864SMatt Jacob 		*semap = 1;
11306ce548a1SAlexander Motin 		break;
1131fc3bbaaaSMatt Jacob 	case ISPR2HST_RIO_16:
11326ce548a1SAlexander Motin 		*info = ASYNC_RIO16_1;
1133fc3bbaaaSMatt Jacob 		*semap = 1;
1134fc3bbaaaSMatt Jacob 		return (1);
1135fc3bbaaaSMatt Jacob 	case ISPR2HST_FPOST:
11366ce548a1SAlexander Motin 		*info = ASYNC_CMD_CMPLT;
1137fc3bbaaaSMatt Jacob 		*semap = 1;
1138fc3bbaaaSMatt Jacob 		return (1);
1139fc3bbaaaSMatt Jacob 	case ISPR2HST_FPOST_CTIO:
11406ce548a1SAlexander Motin 		*info = ASYNC_CTIO_DONE;
1141fc3bbaaaSMatt Jacob 		*semap = 1;
1142fc3bbaaaSMatt Jacob 		return (1);
1143126ec864SMatt Jacob 	case ISPR2HST_RSPQ_UPDATE:
1144126ec864SMatt Jacob 		*semap = 0;
11456ce548a1SAlexander Motin 		break;
1146126ec864SMatt Jacob 	default:
11478a97c03aSMatt Jacob 		hccr = ISP_READ(isp, HCCR);
11488a97c03aSMatt Jacob 		if (hccr & HCCR_PAUSE) {
11498a97c03aSMatt Jacob 			ISP_WRITE(isp, HCCR, HCCR_RESET);
1150443e752dSMatt Jacob 			isp_prt(isp, ISP_LOGERR, "RISC paused at interrupt (%x->%x)", hccr, ISP_READ(isp, HCCR));
11515ccae6a5SMatt Jacob 			ISP_WRITE(isp, BIU_ICR, 0);
11528a97c03aSMatt Jacob 		} else {
1153443e752dSMatt Jacob 			isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr);
11548a97c03aSMatt Jacob 		}
1155126ec864SMatt Jacob 		return (0);
1156126ec864SMatt Jacob 	}
11576ce548a1SAlexander Motin 	*info = (r2hisr >> 16);
11586ce548a1SAlexander Motin 	return (1);
1159126ec864SMatt Jacob }
1160126ec864SMatt Jacob 
116110365e5aSMatt Jacob static int
11626ce548a1SAlexander Motin isp_pci_rd_isr_2400(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info)
116310365e5aSMatt Jacob {
116410365e5aSMatt Jacob 	uint32_t r2hisr;
116510365e5aSMatt Jacob 
11666a7d12e1SMatt Jacob 	r2hisr = BXR4(isp, IspVirt2Off(isp, BIU2400_R2HSTSLO));
116710365e5aSMatt Jacob 	isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr);
11686ce548a1SAlexander Motin 	if ((r2hisr & BIU_R2HST_INTR) == 0) {
116910365e5aSMatt Jacob 		*isrp = 0;
117010365e5aSMatt Jacob 		return (0);
117110365e5aSMatt Jacob 	}
11726ce548a1SAlexander Motin 	switch ((*isrp = r2hisr & BIU_R2HST_ISTAT_MASK)) {
11736ce548a1SAlexander Motin 	case ISPR2HST_ROM_MBX_OK:
11746ce548a1SAlexander Motin 	case ISPR2HST_ROM_MBX_FAIL:
11756ce548a1SAlexander Motin 	case ISPR2HST_MBX_OK:
11766ce548a1SAlexander Motin 	case ISPR2HST_MBX_FAIL:
11776ce548a1SAlexander Motin 	case ISPR2HST_ASYNC_EVENT:
117810365e5aSMatt Jacob 		*semap = 1;
11796ce548a1SAlexander Motin 		break;
11806ce548a1SAlexander Motin 	case ISPR2HST_RSPQ_UPDATE:
11816ce548a1SAlexander Motin 	case ISPR2HST_RSPQ_UPDATE2:
11826ce548a1SAlexander Motin 	case ISPR2HST_ATIO_UPDATE:
11836ce548a1SAlexander Motin 	case ISPR2HST_ATIO_RSPQ_UPDATE:
11846ce548a1SAlexander Motin 	case ISPR2HST_ATIO_UPDATE2:
118510365e5aSMatt Jacob 		*semap = 0;
11866ce548a1SAlexander Motin 		break;
118710365e5aSMatt Jacob 	default:
118810365e5aSMatt Jacob 		ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
118910365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr);
119010365e5aSMatt Jacob 		return (0);
119110365e5aSMatt Jacob 	}
11926ce548a1SAlexander Motin 	*info = (r2hisr >> 16);
11936ce548a1SAlexander Motin 	return (1);
119410365e5aSMatt Jacob }
119510365e5aSMatt Jacob 
119610365e5aSMatt Jacob static uint32_t
11979cd7268eSMatt Jacob isp_pci_rd_reg(ispsoftc_t *isp, int regoff)
119865adb54cSMatt Jacob {
11996a7d12e1SMatt Jacob 	uint16_t rv;
1200126ec864SMatt Jacob 	int oldconf = 0;
120165adb54cSMatt Jacob 
1202d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
120365adb54cSMatt Jacob 		/*
120465adb54cSMatt Jacob 		 * We will assume that someone has paused the RISC processor.
120565adb54cSMatt Jacob 		 */
12066a7d12e1SMatt Jacob 		oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1));
1207443e752dSMatt Jacob 		BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf | BIU_PCI_CONF1_SXP);
120837bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1);
120965adb54cSMatt Jacob 	}
12106a7d12e1SMatt Jacob 	rv = BXR2(isp, IspVirt2Off(isp, regoff));
1211d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
12126a7d12e1SMatt Jacob 		BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf);
121337bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1);
121465adb54cSMatt Jacob 	}
121565adb54cSMatt Jacob 	return (rv);
121665adb54cSMatt Jacob }
121765adb54cSMatt Jacob 
121865adb54cSMatt Jacob static void
121910365e5aSMatt Jacob isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val)
122065adb54cSMatt Jacob {
1221126ec864SMatt Jacob 	int oldconf = 0;
1222d59bd469SMatt Jacob 
1223d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
122465adb54cSMatt Jacob 		/*
122565adb54cSMatt Jacob 		 * We will assume that someone has paused the RISC processor.
122665adb54cSMatt Jacob 		 */
12276a7d12e1SMatt Jacob 		oldconf = BXR2(isp, IspVirt2Off(isp, BIU_CONF1));
12286a7d12e1SMatt Jacob 		BXW2(isp, IspVirt2Off(isp, BIU_CONF1),
1229126ec864SMatt Jacob 		    oldconf | BIU_PCI_CONF1_SXP);
123037bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1);
123165adb54cSMatt Jacob 	}
12326a7d12e1SMatt Jacob 	BXW2(isp, IspVirt2Off(isp, regoff), val);
123337bb79f1SMarius Strobl 	MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1);
1234d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
12356a7d12e1SMatt Jacob 		BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oldconf);
123637bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1);
123765adb54cSMatt Jacob 	}
12386a7d12e1SMatt Jacob 
1239f9734398SMatt Jacob }
124065adb54cSMatt Jacob 
124110365e5aSMatt Jacob static uint32_t
12429cd7268eSMatt Jacob isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff)
1243d59bd469SMatt Jacob {
124410365e5aSMatt Jacob 	uint32_t rv, oc = 0;
1245d59bd469SMatt Jacob 
124610bf42c2SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
124710365e5aSMatt Jacob 		uint32_t tc;
1248d59bd469SMatt Jacob 		/*
1249d59bd469SMatt Jacob 		 * We will assume that someone has paused the RISC processor.
1250d59bd469SMatt Jacob 		 */
12516a7d12e1SMatt Jacob 		oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1));
125222e1dc85SMatt Jacob 		tc = oc & ~BIU_PCI1080_CONF1_DMA;
125322e1dc85SMatt Jacob 		if (regoff & SXP_BANK1_SELECT)
125422e1dc85SMatt Jacob 			tc |= BIU_PCI1080_CONF1_SXP1;
125522e1dc85SMatt Jacob 		else
125622e1dc85SMatt Jacob 			tc |= BIU_PCI1080_CONF1_SXP0;
12576a7d12e1SMatt Jacob 		BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc);
125837bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1);
1259d59bd469SMatt Jacob 	} else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
12606a7d12e1SMatt Jacob 		oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1));
12616a7d12e1SMatt Jacob 		BXW2(isp, IspVirt2Off(isp, BIU_CONF1),
1262126ec864SMatt Jacob 		    oc | BIU_PCI1080_CONF1_DMA);
126337bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1);
1264d59bd469SMatt Jacob 	}
12656a7d12e1SMatt Jacob 	rv = BXR2(isp, IspVirt2Off(isp, regoff));
126622e1dc85SMatt Jacob 	if (oc) {
12676a7d12e1SMatt Jacob 		BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc);
126837bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1);
1269d59bd469SMatt Jacob 	}
1270d59bd469SMatt Jacob 	return (rv);
1271d59bd469SMatt Jacob }
1272d59bd469SMatt Jacob 
1273d59bd469SMatt Jacob static void
127410365e5aSMatt Jacob isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val)
1275d59bd469SMatt Jacob {
1276126ec864SMatt Jacob 	int oc = 0;
1277d59bd469SMatt Jacob 
127810bf42c2SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
127910365e5aSMatt Jacob 		uint32_t tc;
1280d59bd469SMatt Jacob 		/*
1281d59bd469SMatt Jacob 		 * We will assume that someone has paused the RISC processor.
1282d59bd469SMatt Jacob 		 */
12836a7d12e1SMatt Jacob 		oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1));
128422e1dc85SMatt Jacob 		tc = oc & ~BIU_PCI1080_CONF1_DMA;
128522e1dc85SMatt Jacob 		if (regoff & SXP_BANK1_SELECT)
128622e1dc85SMatt Jacob 			tc |= BIU_PCI1080_CONF1_SXP1;
128722e1dc85SMatt Jacob 		else
128822e1dc85SMatt Jacob 			tc |= BIU_PCI1080_CONF1_SXP0;
12896a7d12e1SMatt Jacob 		BXW2(isp, IspVirt2Off(isp, BIU_CONF1), tc);
129037bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1);
1291d59bd469SMatt Jacob 	} else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
12926a7d12e1SMatt Jacob 		oc = BXR2(isp, IspVirt2Off(isp, BIU_CONF1));
12936a7d12e1SMatt Jacob 		BXW2(isp, IspVirt2Off(isp, BIU_CONF1),
1294126ec864SMatt Jacob 		    oc | BIU_PCI1080_CONF1_DMA);
129537bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1);
1296d59bd469SMatt Jacob 	}
12976a7d12e1SMatt Jacob 	BXW2(isp, IspVirt2Off(isp, regoff), val);
129837bb79f1SMarius Strobl 	MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1);
129922e1dc85SMatt Jacob 	if (oc) {
13006a7d12e1SMatt Jacob 		BXW2(isp, IspVirt2Off(isp, BIU_CONF1), oc);
130137bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, BIU_CONF1), 2, -1);
130210365e5aSMatt Jacob 	}
130310365e5aSMatt Jacob }
130410365e5aSMatt Jacob 
130510365e5aSMatt Jacob static uint32_t
130610365e5aSMatt Jacob isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff)
130710365e5aSMatt Jacob {
130810365e5aSMatt Jacob 	uint32_t rv;
130910365e5aSMatt Jacob 	int block = regoff & _BLK_REG_MASK;
131010365e5aSMatt Jacob 
131110365e5aSMatt Jacob 	switch (block) {
131210365e5aSMatt Jacob 	case BIU_BLOCK:
131310365e5aSMatt Jacob 		break;
131410365e5aSMatt Jacob 	case MBOX_BLOCK:
13156a7d12e1SMatt Jacob 		return (BXR2(isp, IspVirt2Off(isp, regoff)));
131610365e5aSMatt Jacob 	case SXP_BLOCK:
131710365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK read at 0x%x", regoff);
131810365e5aSMatt Jacob 		return (0xffffffff);
131910365e5aSMatt Jacob 	case RISC_BLOCK:
132010365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK read at 0x%x", regoff);
132110365e5aSMatt Jacob 		return (0xffffffff);
132210365e5aSMatt Jacob 	case DMA_BLOCK:
132310365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK read at 0x%x", regoff);
132410365e5aSMatt Jacob 		return (0xffffffff);
132510365e5aSMatt Jacob 	default:
132610365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGWARN, "unknown block read at 0x%x", regoff);
132710365e5aSMatt Jacob 		return (0xffffffff);
132810365e5aSMatt Jacob 	}
132910365e5aSMatt Jacob 
133010365e5aSMatt Jacob 
133110365e5aSMatt Jacob 	switch (regoff) {
133210365e5aSMatt Jacob 	case BIU2400_FLASH_ADDR:
133310365e5aSMatt Jacob 	case BIU2400_FLASH_DATA:
133410365e5aSMatt Jacob 	case BIU2400_ICR:
133510365e5aSMatt Jacob 	case BIU2400_ISR:
133610365e5aSMatt Jacob 	case BIU2400_CSR:
133710365e5aSMatt Jacob 	case BIU2400_REQINP:
133810365e5aSMatt Jacob 	case BIU2400_REQOUTP:
133910365e5aSMatt Jacob 	case BIU2400_RSPINP:
134010365e5aSMatt Jacob 	case BIU2400_RSPOUTP:
13412df76c16SMatt Jacob 	case BIU2400_PRI_REQINP:
13422df76c16SMatt Jacob 	case BIU2400_PRI_REQOUTP:
134310365e5aSMatt Jacob 	case BIU2400_ATIO_RSPINP:
13442df76c16SMatt Jacob 	case BIU2400_ATIO_RSPOUTP:
134510365e5aSMatt Jacob 	case BIU2400_HCCR:
134610365e5aSMatt Jacob 	case BIU2400_GPIOD:
134710365e5aSMatt Jacob 	case BIU2400_GPIOE:
134810365e5aSMatt Jacob 	case BIU2400_HSEMA:
13496a7d12e1SMatt Jacob 		rv = BXR4(isp, IspVirt2Off(isp, regoff));
135010365e5aSMatt Jacob 		break;
135110365e5aSMatt Jacob 	case BIU2400_R2HSTSLO:
13526a7d12e1SMatt Jacob 		rv = BXR4(isp, IspVirt2Off(isp, regoff));
135310365e5aSMatt Jacob 		break;
135410365e5aSMatt Jacob 	case BIU2400_R2HSTSHI:
13556a7d12e1SMatt Jacob 		rv = BXR4(isp, IspVirt2Off(isp, regoff)) >> 16;
135610365e5aSMatt Jacob 		break;
135710365e5aSMatt Jacob 	default:
135810365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGERR,
135910365e5aSMatt Jacob 		    "isp_pci_rd_reg_2400: unknown offset %x", regoff);
136010365e5aSMatt Jacob 		rv = 0xffffffff;
136110365e5aSMatt Jacob 		break;
136210365e5aSMatt Jacob 	}
136310365e5aSMatt Jacob 	return (rv);
136410365e5aSMatt Jacob }
136510365e5aSMatt Jacob 
136610365e5aSMatt Jacob static void
136710365e5aSMatt Jacob isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val)
136810365e5aSMatt Jacob {
136910365e5aSMatt Jacob 	int block = regoff & _BLK_REG_MASK;
137010365e5aSMatt Jacob 
137110365e5aSMatt Jacob 	switch (block) {
137210365e5aSMatt Jacob 	case BIU_BLOCK:
137310365e5aSMatt Jacob 		break;
137410365e5aSMatt Jacob 	case MBOX_BLOCK:
13756a7d12e1SMatt Jacob 		BXW2(isp, IspVirt2Off(isp, regoff), val);
137637bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1);
137710365e5aSMatt Jacob 		return;
137810365e5aSMatt Jacob 	case SXP_BLOCK:
137910365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK write at 0x%x", regoff);
138010365e5aSMatt Jacob 		return;
138110365e5aSMatt Jacob 	case RISC_BLOCK:
138210365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK write at 0x%x", regoff);
138310365e5aSMatt Jacob 		return;
138410365e5aSMatt Jacob 	case DMA_BLOCK:
138510365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK write at 0x%x", regoff);
138610365e5aSMatt Jacob 		return;
138710365e5aSMatt Jacob 	default:
138810365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGWARN, "unknown block write at 0x%x",
138910365e5aSMatt Jacob 		    regoff);
139010365e5aSMatt Jacob 		break;
139110365e5aSMatt Jacob 	}
139210365e5aSMatt Jacob 
139310365e5aSMatt Jacob 	switch (regoff) {
139410365e5aSMatt Jacob 	case BIU2400_FLASH_ADDR:
139510365e5aSMatt Jacob 	case BIU2400_FLASH_DATA:
139610365e5aSMatt Jacob 	case BIU2400_ICR:
139710365e5aSMatt Jacob 	case BIU2400_ISR:
139810365e5aSMatt Jacob 	case BIU2400_CSR:
139910365e5aSMatt Jacob 	case BIU2400_REQINP:
140010365e5aSMatt Jacob 	case BIU2400_REQOUTP:
140110365e5aSMatt Jacob 	case BIU2400_RSPINP:
140210365e5aSMatt Jacob 	case BIU2400_RSPOUTP:
14032df76c16SMatt Jacob 	case BIU2400_PRI_REQINP:
14042df76c16SMatt Jacob 	case BIU2400_PRI_REQOUTP:
140510365e5aSMatt Jacob 	case BIU2400_ATIO_RSPINP:
14062df76c16SMatt Jacob 	case BIU2400_ATIO_RSPOUTP:
140710365e5aSMatt Jacob 	case BIU2400_HCCR:
140810365e5aSMatt Jacob 	case BIU2400_GPIOD:
140910365e5aSMatt Jacob 	case BIU2400_GPIOE:
141010365e5aSMatt Jacob 	case BIU2400_HSEMA:
14116a7d12e1SMatt Jacob 		BXW4(isp, IspVirt2Off(isp, regoff), val);
141207d925faSAlexander Motin #ifdef MEMORYBARRIERW
141307d925faSAlexander Motin 		if (regoff == BIU2400_REQINP ||
141407d925faSAlexander Motin 		    regoff == BIU2400_RSPOUTP ||
141507d925faSAlexander Motin 		    regoff == BIU2400_PRI_REQINP ||
141607d925faSAlexander Motin 		    regoff == BIU2400_ATIO_RSPOUTP)
141707d925faSAlexander Motin 			MEMORYBARRIERW(isp, SYNC_REG,
141807d925faSAlexander Motin 			    IspVirt2Off(isp, regoff), 4, -1)
141907d925faSAlexander Motin 		else
142007d925faSAlexander Motin #endif
142137bb79f1SMarius Strobl 		MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 4, -1);
142210365e5aSMatt Jacob 		break;
142310365e5aSMatt Jacob 	default:
142410365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGERR,
142510365e5aSMatt Jacob 		    "isp_pci_wr_reg_2400: bad offset 0x%x", regoff);
142610365e5aSMatt Jacob 		break;
1427d59bd469SMatt Jacob 	}
1428d59bd469SMatt Jacob }
1429d59bd469SMatt Jacob 
1430d720e6d5SJustin T. Gibbs 
1431222bb542SMatt Jacob struct imush {
14329cd7268eSMatt Jacob 	ispsoftc_t *isp;
14332df76c16SMatt Jacob 	caddr_t vbase;
14342df76c16SMatt Jacob 	int chan;
1435222bb542SMatt Jacob 	int error;
1436222bb542SMatt Jacob };
1437222bb542SMatt Jacob 
14381923f739SMatt Jacob static void imc(void *, bus_dma_segment_t *, int, int);
14392df76c16SMatt Jacob static void imc1(void *, bus_dma_segment_t *, int, int);
14401923f739SMatt Jacob 
1441d720e6d5SJustin T. Gibbs static void
14421923f739SMatt Jacob imc(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1443d720e6d5SJustin T. Gibbs {
1444222bb542SMatt Jacob 	struct imush *imushp = (struct imush *) arg;
1445387d8239SMatt Jacob 	isp_ecmd_t *ecmd;
14462df76c16SMatt Jacob 
1447222bb542SMatt Jacob 	if (error) {
1448222bb542SMatt Jacob 		imushp->error = error;
14492df76c16SMatt Jacob 		return;
14502df76c16SMatt Jacob 	}
14512df76c16SMatt Jacob 	if (nseg != 1) {
14522df76c16SMatt Jacob 		imushp->error = EINVAL;
14532df76c16SMatt Jacob 		return;
14542df76c16SMatt Jacob 	}
14557d3cea31SMatt Jacob 	isp_prt(imushp->isp, ISP_LOGDEBUG0, "request/result area @ 0x%jx/0x%jx", (uintmax_t) segs->ds_addr, (uintmax_t) segs->ds_len);
1456387d8239SMatt Jacob 
14572df76c16SMatt Jacob 	imushp->isp->isp_rquest = imushp->vbase;
14582df76c16SMatt Jacob 	imushp->isp->isp_rquest_dma = segs->ds_addr;
14592df76c16SMatt Jacob 	segs->ds_addr += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp));
14602df76c16SMatt Jacob 	imushp->vbase += ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(imushp->isp));
1461387d8239SMatt Jacob 
14622df76c16SMatt Jacob 	imushp->isp->isp_result_dma = segs->ds_addr;
14632df76c16SMatt Jacob 	imushp->isp->isp_result = imushp->vbase;
14642df76c16SMatt Jacob 	segs->ds_addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp));
14652df76c16SMatt Jacob 	imushp->vbase += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp));
1466387d8239SMatt Jacob 
1467a4ccb5d6SAlexander Motin 	if (imushp->isp->isp_type >= ISP_HA_FC_2200) {
1468387d8239SMatt Jacob         imushp->isp->isp_osinfo.ecmd_dma = segs->ds_addr;
1469387d8239SMatt Jacob         imushp->isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)imushp->vbase;
1470387d8239SMatt Jacob         imushp->isp->isp_osinfo.ecmd_base = imushp->isp->isp_osinfo.ecmd_free;
1471387d8239SMatt Jacob         for (ecmd = imushp->isp->isp_osinfo.ecmd_free; ecmd < &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) {
1472387d8239SMatt Jacob             if (ecmd == &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS - 1]) {
1473387d8239SMatt Jacob                 ecmd->next = NULL;
1474387d8239SMatt Jacob             } else {
1475387d8239SMatt Jacob                 ecmd->next = ecmd + 1;
1476387d8239SMatt Jacob             }
1477387d8239SMatt Jacob         }
1478de0627d0SMatt Jacob     }
1479387d8239SMatt Jacob #ifdef	ISP_TARGET_MODE
1480387d8239SMatt Jacob 	segs->ds_addr += (N_XCMDS * XCMD_SIZE);
1481387d8239SMatt Jacob 	imushp->vbase += (N_XCMDS * XCMD_SIZE);
1482387d8239SMatt Jacob 	if (IS_24XX(imushp->isp)) {
14832df76c16SMatt Jacob 		imushp->isp->isp_atioq_dma = segs->ds_addr;
14842df76c16SMatt Jacob 		imushp->isp->isp_atioq = imushp->vbase;
14851923f739SMatt Jacob 	}
14862df76c16SMatt Jacob #endif
1487222bb542SMatt Jacob }
14882df76c16SMatt Jacob 
14892df76c16SMatt Jacob static void
14902df76c16SMatt Jacob imc1(void *arg, bus_dma_segment_t *segs, int nseg, int error)
14912df76c16SMatt Jacob {
14922df76c16SMatt Jacob 	struct imush *imushp = (struct imush *) arg;
14932df76c16SMatt Jacob 	if (error) {
14942df76c16SMatt Jacob 		imushp->error = error;
14952df76c16SMatt Jacob 		return;
14962df76c16SMatt Jacob 	}
14972df76c16SMatt Jacob 	if (nseg != 1) {
14982df76c16SMatt Jacob 		imushp->error = EINVAL;
14992df76c16SMatt Jacob 		return;
15002df76c16SMatt Jacob 	}
15017d3cea31SMatt Jacob 	isp_prt(imushp->isp, ISP_LOGDEBUG0, "scdma @ 0x%jx/0x%jx", (uintmax_t) segs->ds_addr, (uintmax_t) segs->ds_len);
15022df76c16SMatt Jacob 	FCPARAM(imushp->isp, imushp->chan)->isp_scdma = segs->ds_addr;
15032df76c16SMatt Jacob 	FCPARAM(imushp->isp, imushp->chan)->isp_scratch = imushp->vbase;
1504d720e6d5SJustin T. Gibbs }
1505d720e6d5SJustin T. Gibbs 
1506d720e6d5SJustin T. Gibbs static int
15079cd7268eSMatt Jacob isp_pci_mbxdma(ispsoftc_t *isp)
1508d720e6d5SJustin T. Gibbs {
1509d720e6d5SJustin T. Gibbs 	caddr_t base;
1510662daaddSMatt Jacob 	uint32_t len, nsegs;
15118e1b6e7aSMatt Jacob 	int i, error, cmap = 0;
151253af7d22SMatt Jacob 	bus_size_t slim;	/* segment size */
15134b2dc3c4SScott Long 	bus_addr_t llim;	/* low limit of unavailable dma */
151451effc8cSMatt Jacob 	bus_addr_t hlim;	/* high limit of unavailable dma */
1515222bb542SMatt Jacob 	struct imush im;
1516222bb542SMatt Jacob 
1517a95ae193SMatt Jacob 	/*
1518a95ae193SMatt Jacob 	 * Already been here? If so, leave...
1519a95ae193SMatt Jacob 	 */
1520a95ae193SMatt Jacob 	if (isp->isp_rquest) {
1521a95ae193SMatt Jacob 		return (0);
1522a95ae193SMatt Jacob 	}
15230a70657fSMatt Jacob 	ISP_UNLOCK(isp);
1524a95ae193SMatt Jacob 
152510365e5aSMatt Jacob 	if (isp->isp_maxcmds == 0) {
152610365e5aSMatt Jacob 		isp_prt(isp, ISP_LOGERR, "maxcmds not set");
15270a70657fSMatt Jacob 		ISP_LOCK(isp);
152810365e5aSMatt Jacob 		return (1);
152910365e5aSMatt Jacob 	}
153010365e5aSMatt Jacob 
153153af7d22SMatt Jacob 	hlim = BUS_SPACE_MAXADDR;
15321923f739SMatt Jacob 	if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) {
15339b434edeSMatt Jacob 		if (sizeof (bus_size_t) > 4) {
153453af7d22SMatt Jacob 			slim = (bus_size_t) (1ULL << 32);
15359b434edeSMatt Jacob 		} else {
15369b434edeSMatt Jacob 			slim = (bus_size_t) (1UL << 31);
15379b434edeSMatt Jacob 		}
15381dae40ebSMatt Jacob 		llim = BUS_SPACE_MAXADDR;
15391923f739SMatt Jacob 	} else {
15401dae40ebSMatt Jacob 		llim = BUS_SPACE_MAXADDR_32BIT;
15419b434edeSMatt Jacob 		slim = (1UL << 24);
15421923f739SMatt Jacob 	}
15431923f739SMatt Jacob 
15440a70657fSMatt Jacob 	len = isp->isp_maxcmds * sizeof (struct isp_pcmd);
15452df76c16SMatt Jacob 	isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
15460a70657fSMatt Jacob 	if (isp->isp_osinfo.pcmd_pool == NULL) {
15470a70657fSMatt Jacob 		isp_prt(isp, ISP_LOGERR, "cannot allocate pcmds");
15480a70657fSMatt Jacob 		ISP_LOCK(isp);
15490a70657fSMatt Jacob 		return (1);
15500a70657fSMatt Jacob 	}
15510a70657fSMatt Jacob 
1552662daaddSMatt Jacob 	if (isp->isp_osinfo.sixtyfourbit) {
1553662daaddSMatt Jacob 		nsegs = ISP_NSEG64_MAX;
1554662daaddSMatt Jacob 	} else {
1555662daaddSMatt Jacob 		nsegs = ISP_NSEG_MAX;
1556662daaddSMatt Jacob 	}
155709934867SMatt Jacob 
1558662daaddSMatt Jacob 	if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_PCD(isp)), 1, slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, nsegs, slim, 0, &isp->isp_osinfo.dmat)) {
15590a70657fSMatt Jacob 		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
156072429e49SMatt Jacob 		ISP_LOCK(isp);
15610a70657fSMatt Jacob 		isp_prt(isp, ISP_LOGERR, "could not create master dma tag");
15621923f739SMatt Jacob 		return (1);
15631923f739SMatt Jacob 	}
15641923f739SMatt Jacob 
1565c8b8a2c4SMatt Jacob 	len = sizeof (isp_hdl_t) * isp->isp_maxcmds;
1566c8b8a2c4SMatt Jacob 	isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
1567a95ae193SMatt Jacob 	if (isp->isp_xflist == NULL) {
15680a70657fSMatt Jacob 		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
156972429e49SMatt Jacob 		ISP_LOCK(isp);
15700a70657fSMatt Jacob 		isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array");
1571a95ae193SMatt Jacob 		return (1);
1572a95ae193SMatt Jacob 	}
1573c8b8a2c4SMatt Jacob 	for (len = 0; len < isp->isp_maxcmds - 1; len++) {
1574c8b8a2c4SMatt Jacob 		isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1];
1575c8b8a2c4SMatt Jacob 	}
1576c8b8a2c4SMatt Jacob 	isp->isp_xffree = isp->isp_xflist;
157751e23558SNate Lawson #ifdef	ISP_TARGET_MODE
157832b3ec7dSMatt Jacob 	len = sizeof (isp_hdl_t) * isp->isp_maxcmds;
1579c8b8a2c4SMatt Jacob 	isp->isp_tgtlist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
158051e23558SNate Lawson 	if (isp->isp_tgtlist == NULL) {
15810a70657fSMatt Jacob 		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
1582a95ae193SMatt Jacob 		free(isp->isp_xflist, M_DEVBUF);
158372429e49SMatt Jacob 		ISP_LOCK(isp);
15840a70657fSMatt Jacob 		isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array");
1585a95ae193SMatt Jacob 		return (1);
1586a95ae193SMatt Jacob 	}
1587c8b8a2c4SMatt Jacob 	for (len = 0; len < isp->isp_maxcmds - 1; len++) {
1588c8b8a2c4SMatt Jacob 		isp->isp_tgtlist[len].cmd = &isp->isp_tgtlist[len+1];
1589c8b8a2c4SMatt Jacob 	}
1590c8b8a2c4SMatt Jacob 	isp->isp_tgtfree = isp->isp_tgtlist;
15910a70657fSMatt Jacob #endif
1592a95ae193SMatt Jacob 
1593d720e6d5SJustin T. Gibbs 	/*
15942df76c16SMatt Jacob 	 * Allocate and map the request and result queues (and ATIO queue
1595387d8239SMatt Jacob 	 * if we're a 2400 supporting target mode), and a region for
1596387d8239SMatt Jacob 	 * external dma addressable command/status structures (23XX and
1597387d8239SMatt Jacob 	 * later).
1598d720e6d5SJustin T. Gibbs 	 */
1599d02373f1SMatt Jacob 	len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
1600d02373f1SMatt Jacob 	len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
16012df76c16SMatt Jacob #ifdef	ISP_TARGET_MODE
16022df76c16SMatt Jacob 	if (IS_24XX(isp)) {
16032df76c16SMatt Jacob 		len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
1604d720e6d5SJustin T. Gibbs 	}
16052df76c16SMatt Jacob #endif
1606a4ccb5d6SAlexander Motin 	if (isp->isp_type >= ISP_HA_FC_2200) {
1607387d8239SMatt Jacob 		len += (N_XCMDS * XCMD_SIZE);
1608387d8239SMatt Jacob 	}
16092df76c16SMatt Jacob 
161053af7d22SMatt Jacob 	/*
16112df76c16SMatt Jacob 	 * Create a tag for the control spaces. We don't always need this
16122df76c16SMatt Jacob 	 * to be 32 bits, but we do this for simplicity and speed's sake.
161353af7d22SMatt Jacob 	 */
16148e1b6e7aSMatt Jacob 	if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, slim, 0, &isp->isp_osinfo.cdmat)) {
16152df76c16SMatt Jacob 		isp_prt(isp, ISP_LOGERR, "cannot create a dma tag for control spaces");
16160a70657fSMatt Jacob 		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
1617a95ae193SMatt Jacob 		free(isp->isp_xflist, M_DEVBUF);
161851e23558SNate Lawson #ifdef	ISP_TARGET_MODE
161951e23558SNate Lawson 		free(isp->isp_tgtlist, M_DEVBUF);
162051e23558SNate Lawson #endif
162172429e49SMatt Jacob 		ISP_LOCK(isp);
1622d720e6d5SJustin T. Gibbs 		return (1);
1623d720e6d5SJustin T. Gibbs 	}
1624d720e6d5SJustin T. Gibbs 
162537bb79f1SMarius Strobl 	if (bus_dmamem_alloc(isp->isp_osinfo.cdmat, (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &isp->isp_osinfo.cdmap) != 0) {
16262df76c16SMatt Jacob 		isp_prt(isp, ISP_LOGERR, "cannot allocate %d bytes of CCB memory", len);
16272df76c16SMatt Jacob 		bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
16280a70657fSMatt Jacob 		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
1629a95ae193SMatt Jacob 		free(isp->isp_xflist, M_DEVBUF);
163051e23558SNate Lawson #ifdef	ISP_TARGET_MODE
163151e23558SNate Lawson 		free(isp->isp_tgtlist, M_DEVBUF);
163251e23558SNate Lawson #endif
163372429e49SMatt Jacob 		ISP_LOCK(isp);
1634222bb542SMatt Jacob 		return (1);
1635222bb542SMatt Jacob 	}
1636d720e6d5SJustin T. Gibbs 
16372df76c16SMatt Jacob 	im.isp = isp;
16382df76c16SMatt Jacob 	im.chan = 0;
16392df76c16SMatt Jacob 	im.vbase = base;
16402df76c16SMatt Jacob 	im.error = 0;
16412df76c16SMatt Jacob 
16422df76c16SMatt Jacob 	bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0);
16432df76c16SMatt Jacob 	if (im.error) {
16442df76c16SMatt Jacob 		isp_prt(isp, ISP_LOGERR, "error %d loading dma map for control areas", im.error);
16452df76c16SMatt Jacob 		goto bad;
16462df76c16SMatt Jacob 	}
16472df76c16SMatt Jacob 
16482df76c16SMatt Jacob 	if (IS_FC(isp)) {
16492df76c16SMatt Jacob 		for (cmap = 0; cmap < isp->isp_nchan; cmap++) {
16502df76c16SMatt Jacob 			struct isp_fc *fc = ISP_FC_PC(isp, cmap);
16512df76c16SMatt Jacob 			if (isp_dma_tag_create(isp->isp_osinfo.dmat, 64, slim, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, ISP_FC_SCRLEN, 1, slim, 0, &fc->tdmat)) {
16522df76c16SMatt Jacob 				goto bad;
16532df76c16SMatt Jacob 			}
165437bb79f1SMarius Strobl 			if (bus_dmamem_alloc(fc->tdmat, (void **)&base, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &fc->tdmap) != 0) {
16552df76c16SMatt Jacob 				bus_dma_tag_destroy(fc->tdmat);
16562df76c16SMatt Jacob 				goto bad;
16572df76c16SMatt Jacob 			}
16582df76c16SMatt Jacob 			im.isp = isp;
16592df76c16SMatt Jacob 			im.chan = cmap;
16602df76c16SMatt Jacob 			im.vbase = base;
16612df76c16SMatt Jacob 			im.error = 0;
16622df76c16SMatt Jacob 			bus_dmamap_load(fc->tdmat, fc->tdmap, base, ISP_FC_SCRLEN, imc1, &im, 0);
16632df76c16SMatt Jacob 			if (im.error) {
16642df76c16SMatt Jacob 				bus_dmamem_free(fc->tdmat, base, fc->tdmap);
16652df76c16SMatt Jacob 				bus_dma_tag_destroy(fc->tdmat);
16662df76c16SMatt Jacob 				goto bad;
16672df76c16SMatt Jacob 			}
1668a4ccb5d6SAlexander Motin 			if (!IS_2100(isp)) {
1669387d8239SMatt Jacob 				for (i = 0; i < INITIAL_NEXUS_COUNT; i++) {
1670387d8239SMatt Jacob 					struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO);
1671387d8239SMatt Jacob 					if (n == NULL) {
1672387d8239SMatt Jacob 						while (fc->nexus_free_list) {
1673387d8239SMatt Jacob 							n = fc->nexus_free_list;
1674387d8239SMatt Jacob 							fc->nexus_free_list = n->next;
1675387d8239SMatt Jacob 							free(n, M_DEVBUF);
1676387d8239SMatt Jacob 						}
1677387d8239SMatt Jacob 						goto bad;
1678387d8239SMatt Jacob 					}
1679387d8239SMatt Jacob 					n->next = fc->nexus_free_list;
1680387d8239SMatt Jacob 					fc->nexus_free_list = n;
1681387d8239SMatt Jacob 				}
16822df76c16SMatt Jacob 			}
16832df76c16SMatt Jacob 		}
1684405b7a29SMatt Jacob 	}
16852df76c16SMatt Jacob 
1686a95ae193SMatt Jacob 	for (i = 0; i < isp->isp_maxcmds; i++) {
16870a70657fSMatt Jacob 		struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i];
16880a70657fSMatt Jacob 		error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap);
1689d720e6d5SJustin T. Gibbs 		if (error) {
16902df76c16SMatt Jacob 			isp_prt(isp, ISP_LOGERR, "error %d creating per-cmd DMA maps", error);
16911923f739SMatt Jacob 			while (--i >= 0) {
16922df76c16SMatt Jacob 				bus_dmamap_destroy(isp->isp_osinfo.dmat, isp->isp_osinfo.pcmd_pool[i].dmap);
16931923f739SMatt Jacob 			}
16941923f739SMatt Jacob 			goto bad;
1695d720e6d5SJustin T. Gibbs 		}
16962df76c16SMatt Jacob 		callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0);
16970a70657fSMatt Jacob 		if (i == isp->isp_maxcmds-1) {
16980a70657fSMatt Jacob 			pcmd->next = NULL;
16990a70657fSMatt Jacob 		} else {
17000a70657fSMatt Jacob 			pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1];
1701d720e6d5SJustin T. Gibbs 		}
17020a70657fSMatt Jacob 	}
17030a70657fSMatt Jacob 	isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0];
170472429e49SMatt Jacob 	ISP_LOCK(isp);
1705d720e6d5SJustin T. Gibbs 	return (0);
17061923f739SMatt Jacob 
17071923f739SMatt Jacob bad:
17082df76c16SMatt Jacob 	while (--cmap >= 0) {
17092df76c16SMatt Jacob 		struct isp_fc *fc = ISP_FC_PC(isp, cmap);
1710aced5239SJohn Baldwin 		bus_dmamap_unload(fc->tdmat, fc->tdmap);
17112df76c16SMatt Jacob 		bus_dmamem_free(fc->tdmat, base, fc->tdmap);
17122df76c16SMatt Jacob 		bus_dma_tag_destroy(fc->tdmat);
1713387d8239SMatt Jacob 		while (fc->nexus_free_list) {
1714387d8239SMatt Jacob 			struct isp_nexus *n = fc->nexus_free_list;
1715387d8239SMatt Jacob 			fc->nexus_free_list = n->next;
1716387d8239SMatt Jacob 			free(n, M_DEVBUF);
1717387d8239SMatt Jacob 		}
17182df76c16SMatt Jacob 	}
1719aced5239SJohn Baldwin 	if (isp->isp_rquest_dma != 0)
1720aced5239SJohn Baldwin 		bus_dmamap_unload(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap);
17212df76c16SMatt Jacob 	bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap);
17222df76c16SMatt Jacob 	bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
17231923f739SMatt Jacob 	free(isp->isp_xflist, M_DEVBUF);
172451e23558SNate Lawson #ifdef	ISP_TARGET_MODE
172551e23558SNate Lawson 	free(isp->isp_tgtlist, M_DEVBUF);
172651e23558SNate Lawson #endif
17270a70657fSMatt Jacob 	free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
17281923f739SMatt Jacob 	isp->isp_rquest = NULL;
17290a70657fSMatt Jacob 	ISP_LOCK(isp);
17301923f739SMatt Jacob 	return (1);
1731d720e6d5SJustin T. Gibbs }
1732d720e6d5SJustin T. Gibbs 
1733d720e6d5SJustin T. Gibbs typedef struct {
17349cd7268eSMatt Jacob 	ispsoftc_t *isp;
17359e11e5beSMatt Jacob 	void *cmd_token;
17362df76c16SMatt Jacob 	void *rq;	/* original request */
17371dae40ebSMatt Jacob 	int error;
17382df76c16SMatt Jacob 	bus_size_t mapsize;
1739d720e6d5SJustin T. Gibbs } mush_t;
1740d720e6d5SJustin T. Gibbs 
17414873663cSMatt Jacob #define	MUSHERR_NOQENTRIES	-2
17424873663cSMatt Jacob 
17439e11e5beSMatt Jacob #ifdef	ISP_TARGET_MODE
17442df76c16SMatt Jacob static void tdma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int);
17452df76c16SMatt Jacob static void tdma2(void *, bus_dma_segment_t *, int, int);
17469e11e5beSMatt Jacob 
1747d720e6d5SJustin T. Gibbs static void
17482df76c16SMatt Jacob tdma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error)
1749d720e6d5SJustin T. Gibbs {
1750d720e6d5SJustin T. Gibbs 	mush_t *mp;
17512df76c16SMatt Jacob 	mp = (mush_t *)arg;
17522df76c16SMatt Jacob 	mp->mapsize = mapsize;
17532df76c16SMatt Jacob 	tdma2(arg, dm_segs, nseg, error);
17542df76c16SMatt Jacob }
17552df76c16SMatt Jacob 
17562df76c16SMatt Jacob static void
17572df76c16SMatt Jacob tdma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
17582df76c16SMatt Jacob {
17592df76c16SMatt Jacob 	mush_t *mp;
17609cd7268eSMatt Jacob 	ispsoftc_t *isp;
17612df76c16SMatt Jacob 	struct ccb_scsiio *csio;
17622df76c16SMatt Jacob 	isp_ddir_t ddir;
17632df76c16SMatt Jacob 	ispreq_t *rq;
1764d720e6d5SJustin T. Gibbs 
1765d720e6d5SJustin T. Gibbs 	mp = (mush_t *) arg;
1766d720e6d5SJustin T. Gibbs 	if (error) {
1767d720e6d5SJustin T. Gibbs 		mp->error = error;
1768d720e6d5SJustin T. Gibbs 		return;
1769d720e6d5SJustin T. Gibbs 	}
17709e11e5beSMatt Jacob 	csio = mp->cmd_token;
17714fd13c1bSMatt Jacob 	isp = mp->isp;
17722df76c16SMatt Jacob 	rq = mp->rq;
17732df76c16SMatt Jacob 	if (nseg) {
1774387d8239SMatt Jacob 		if (isp->isp_osinfo.sixtyfourbit) {
17752df76c16SMatt Jacob 			if (nseg >= ISP_NSEG64_MAX) {
17762df76c16SMatt Jacob 				isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX);
17772df76c16SMatt Jacob 				mp->error = EFAULT;
17789e11e5beSMatt Jacob 				return;
17799e11e5beSMatt Jacob 			}
17802df76c16SMatt Jacob 			if (rq->req_header.rqs_entry_type == RQSTYPE_CTIO2) {
17812df76c16SMatt Jacob 				rq->req_header.rqs_entry_type = RQSTYPE_CTIO3;
17822df76c16SMatt Jacob 			}
178309934867SMatt Jacob 		} else {
17842df76c16SMatt Jacob 			if (nseg >= ISP_NSEG_MAX) {
17852df76c16SMatt Jacob 				isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX);
17862df76c16SMatt Jacob 				mp->error = EFAULT;
17872df76c16SMatt Jacob 				return;
178809934867SMatt Jacob 			}
17892df76c16SMatt Jacob 		}
17902df76c16SMatt Jacob 		if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
17912df76c16SMatt Jacob 			bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
17922df76c16SMatt Jacob 			ddir = ISP_TO_DEVICE;
17932df76c16SMatt Jacob 		} else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
17942df76c16SMatt Jacob 			bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
17952df76c16SMatt Jacob 			ddir = ISP_FROM_DEVICE;
179609934867SMatt Jacob 		} else {
1797a035b0afSMatt Jacob 			dm_segs = NULL;
1798a035b0afSMatt Jacob 			nseg = 0;
17992df76c16SMatt Jacob 			ddir = ISP_NOXFR;
180009934867SMatt Jacob 		}
18012df76c16SMatt Jacob 	} else {
18022df76c16SMatt Jacob 		dm_segs = NULL;
18032df76c16SMatt Jacob 		nseg = 0;
18042df76c16SMatt Jacob 		ddir = ISP_NOXFR;
1805fc087171SMatt Jacob 	}
180665b024e1SMatt Jacob 
1807387d8239SMatt Jacob 	error = isp_send_tgt_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, &csio->sense_data, csio->sense_len);
1808387d8239SMatt Jacob 	switch (error) {
1809387d8239SMatt Jacob 	case CMD_EAGAIN:
18102df76c16SMatt Jacob 		mp->error = MUSHERR_NOQENTRIES;
1811387d8239SMatt Jacob 	case CMD_QUEUED:
1812387d8239SMatt Jacob 		break;
1813387d8239SMatt Jacob 	default:
1814387d8239SMatt Jacob 		mp->error = EIO;
181510365e5aSMatt Jacob 	}
18169e11e5beSMatt Jacob }
18179e11e5beSMatt Jacob #endif
18189e11e5beSMatt Jacob 
18192df76c16SMatt Jacob static void dma2_2(void *, bus_dma_segment_t *, int, bus_size_t, int);
1820126ec864SMatt Jacob static void dma2(void *, bus_dma_segment_t *, int, int);
18219e11e5beSMatt Jacob 
18226de9bf77SMatt Jacob static void
18232df76c16SMatt Jacob dma2_2(void *arg, bus_dma_segment_t *dm_segs, int nseg, bus_size_t mapsize, int error)
182410365e5aSMatt Jacob {
182510365e5aSMatt Jacob 	mush_t *mp;
182610365e5aSMatt Jacob 	mp = (mush_t *)arg;
18272df76c16SMatt Jacob 	mp->mapsize = mapsize;
18282df76c16SMatt Jacob 	dma2(arg, dm_segs, nseg, error);
18296de9bf77SMatt Jacob }
18301dae40ebSMatt Jacob 
18319e11e5beSMatt Jacob static void
18329e11e5beSMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
18339e11e5beSMatt Jacob {
18349e11e5beSMatt Jacob 	mush_t *mp;
18359cd7268eSMatt Jacob 	ispsoftc_t *isp;
18369e11e5beSMatt Jacob 	struct ccb_scsiio *csio;
18372df76c16SMatt Jacob 	isp_ddir_t ddir;
18389e11e5beSMatt Jacob 	ispreq_t *rq;
18399e11e5beSMatt Jacob 
18409e11e5beSMatt Jacob 	mp = (mush_t *) arg;
18419e11e5beSMatt Jacob 	if (error) {
18429e11e5beSMatt Jacob 		mp->error = error;
18439e11e5beSMatt Jacob 		return;
18449e11e5beSMatt Jacob 	}
18459e11e5beSMatt Jacob 	csio = mp->cmd_token;
18464fd13c1bSMatt Jacob 	isp = mp->isp;
18479e11e5beSMatt Jacob 	rq = mp->rq;
18482df76c16SMatt Jacob 	if (nseg) {
1849387d8239SMatt Jacob 		if (isp->isp_osinfo.sixtyfourbit) {
18502df76c16SMatt Jacob 			if (nseg >= ISP_NSEG64_MAX) {
18512df76c16SMatt Jacob 				isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG64_MAX);
18522df76c16SMatt Jacob 				mp->error = EFAULT;
1853d720e6d5SJustin T. Gibbs 				return;
1854d720e6d5SJustin T. Gibbs 			}
18552df76c16SMatt Jacob 			if (rq->req_header.rqs_entry_type == RQSTYPE_T2RQS) {
18562df76c16SMatt Jacob 				rq->req_header.rqs_entry_type = RQSTYPE_T3RQS;
18572df76c16SMatt Jacob 			} else if (rq->req_header.rqs_entry_type == RQSTYPE_REQUEST) {
18582df76c16SMatt Jacob 				rq->req_header.rqs_entry_type = RQSTYPE_A64;
1859d720e6d5SJustin T. Gibbs 			}
18602df76c16SMatt Jacob 		} else {
18612df76c16SMatt Jacob 			if (nseg >= ISP_NSEG_MAX) {
18622df76c16SMatt Jacob 				isp_prt(isp, ISP_LOGERR, "number of segments (%d) exceed maximum we can support (%d)", nseg, ISP_NSEG_MAX);
18632df76c16SMatt Jacob 				mp->error = EFAULT;
18642df76c16SMatt Jacob 				return;
186510365e5aSMatt Jacob 			}
1866d720e6d5SJustin T. Gibbs 		}
18672df76c16SMatt Jacob 		if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
18682df76c16SMatt Jacob 			bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
18692df76c16SMatt Jacob 			ddir = ISP_FROM_DEVICE;
18702df76c16SMatt Jacob 		} else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
18712df76c16SMatt Jacob 			bus_dmamap_sync(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
18722df76c16SMatt Jacob 			ddir = ISP_TO_DEVICE;
18732df76c16SMatt Jacob 		} else {
18742df76c16SMatt Jacob 			ddir = ISP_NOXFR;
18752df76c16SMatt Jacob 		}
18762df76c16SMatt Jacob 	} else {
18772df76c16SMatt Jacob 		dm_segs = NULL;
18782df76c16SMatt Jacob 		nseg = 0;
18792df76c16SMatt Jacob 		ddir = ISP_NOXFR;
1880d720e6d5SJustin T. Gibbs 	}
1881d720e6d5SJustin T. Gibbs 
1882387d8239SMatt Jacob 	error = isp_send_cmd(isp, rq, dm_segs, nseg, XS_XFRLEN(csio), ddir, (ispds64_t *)csio->req_map);
1883387d8239SMatt Jacob 	switch (error) {
1884387d8239SMatt Jacob 	case CMD_EAGAIN:
18852df76c16SMatt Jacob 		mp->error = MUSHERR_NOQENTRIES;
1886387d8239SMatt Jacob 		break;
1887387d8239SMatt Jacob 	case CMD_QUEUED:
1888387d8239SMatt Jacob 		break;
1889387d8239SMatt Jacob 	default:
1890387d8239SMatt Jacob 		mp->error = EIO;
1891387d8239SMatt Jacob 		break;
18922df76c16SMatt Jacob 	}
18932df76c16SMatt Jacob }
18942df76c16SMatt Jacob 
1895d720e6d5SJustin T. Gibbs static int
18962df76c16SMatt Jacob isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff)
1897d720e6d5SJustin T. Gibbs {
1898d720e6d5SJustin T. Gibbs 	mush_t mush, *mp;
1899126ec864SMatt Jacob 	void (*eptr)(void *, bus_dma_segment_t *, int, int);
19002df76c16SMatt Jacob 	void (*eptr2)(void *, bus_dma_segment_t *, int, bus_size_t, int);
1901dd0b4fb6SKonstantin Belousov 	int error;
1902d720e6d5SJustin T. Gibbs 
19032df76c16SMatt Jacob 	mp = &mush;
19042df76c16SMatt Jacob 	mp->isp = isp;
19052df76c16SMatt Jacob 	mp->cmd_token = csio;
19062df76c16SMatt Jacob 	mp->rq = ff;
19072df76c16SMatt Jacob 	mp->error = 0;
19082df76c16SMatt Jacob 	mp->mapsize = 0;
19092df76c16SMatt Jacob 
191065b024e1SMatt Jacob #ifdef	ISP_TARGET_MODE
191165b024e1SMatt Jacob 	if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) {
19122df76c16SMatt Jacob 		eptr = tdma2;
19132df76c16SMatt Jacob 		eptr2 = tdma2_2;
191465b024e1SMatt Jacob 	} else
191565b024e1SMatt Jacob #endif
19162df76c16SMatt Jacob 	{
191765b024e1SMatt Jacob 		eptr = dma2;
19182df76c16SMatt Jacob 		eptr2 = dma2_2;
19191dae40ebSMatt Jacob 	}
192065b024e1SMatt Jacob 
19214fd13c1bSMatt Jacob 
1922dd0b4fb6SKonstantin Belousov 	error = bus_dmamap_load_ccb(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap,
1923dd0b4fb6SKonstantin Belousov 	    (union ccb *)csio, eptr, mp, 0);
1924d720e6d5SJustin T. Gibbs 	if (error == EINPROGRESS) {
19252df76c16SMatt Jacob 		bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap);
1926d720e6d5SJustin T. Gibbs 		mp->error = EINVAL;
19272df76c16SMatt Jacob 		isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported");
1928d720e6d5SJustin T. Gibbs 	} else if (error && mp->error == 0) {
19290a5f7e8bSMatt Jacob #ifdef	DIAGNOSTIC
19302df76c16SMatt Jacob 		isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error);
19310a5f7e8bSMatt Jacob #endif
1932d720e6d5SJustin T. Gibbs 		mp->error = error;
1933d720e6d5SJustin T. Gibbs 	}
1934d720e6d5SJustin T. Gibbs 	if (mp->error) {
19354873663cSMatt Jacob 		int retval = CMD_COMPLETE;
19364873663cSMatt Jacob 		if (mp->error == MUSHERR_NOQENTRIES) {
19374873663cSMatt Jacob 			retval = CMD_EAGAIN;
19384873663cSMatt Jacob 		} else if (mp->error == EFBIG) {
1939387d8239SMatt Jacob 			csio->ccb_h.status = CAM_REQ_TOO_BIG;
1940d720e6d5SJustin T. Gibbs 		} else if (mp->error == EINVAL) {
1941387d8239SMatt Jacob 			csio->ccb_h.status = CAM_REQ_INVALID;
1942d720e6d5SJustin T. Gibbs 		} else {
1943387d8239SMatt Jacob 			csio->ccb_h.status = CAM_UNREC_HBA_ERROR;
1944d720e6d5SJustin T. Gibbs 		}
19454873663cSMatt Jacob 		return (retval);
19460a5f7e8bSMatt Jacob 	}
19474873663cSMatt Jacob 	return (CMD_QUEUED);
1948d720e6d5SJustin T. Gibbs }
1949d720e6d5SJustin T. Gibbs 
1950d720e6d5SJustin T. Gibbs static void
19513bda7a83SMatt Jacob isp_pci_reset0(ispsoftc_t *isp)
19523bda7a83SMatt Jacob {
19533bda7a83SMatt Jacob 	ISP_DISABLE_INTS(isp);
19543bda7a83SMatt Jacob }
19553bda7a83SMatt Jacob 
19563bda7a83SMatt Jacob static void
19579cd7268eSMatt Jacob isp_pci_reset1(ispsoftc_t *isp)
195865adb54cSMatt Jacob {
195910365e5aSMatt Jacob 	if (!IS_24XX(isp)) {
196065adb54cSMatt Jacob 		/* Make sure the BIOS is disabled */
196165adb54cSMatt Jacob 		isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
196210365e5aSMatt Jacob 	}
1963469b6b9eSMatt Jacob 	/* and enable interrupts */
196410365e5aSMatt Jacob 	ISP_ENABLE_INTS(isp);
196565adb54cSMatt Jacob }
196665adb54cSMatt Jacob 
196765adb54cSMatt Jacob static void
19689cd7268eSMatt Jacob isp_pci_dumpregs(ispsoftc_t *isp, const char *msg)
196965adb54cSMatt Jacob {
19701923f739SMatt Jacob 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
1971d02373f1SMatt Jacob 	if (msg)
19726e5c5328SMatt Jacob 		printf("%s: %s\n", device_get_nameunit(isp->isp_dev), msg);
19736e5c5328SMatt Jacob 	else
19746e5c5328SMatt Jacob 		printf("%s:\n", device_get_nameunit(isp->isp_dev));
1975d02373f1SMatt Jacob 	if (IS_SCSI(isp))
1976d02373f1SMatt Jacob 		printf("    biu_conf1=%x", ISP_READ(isp, BIU_CONF1));
1977d02373f1SMatt Jacob 	else
1978d02373f1SMatt Jacob 		printf("    biu_csr=%x", ISP_READ(isp, BIU2100_CSR));
1979d02373f1SMatt Jacob 	printf(" biu_icr=%x biu_isr=%x biu_sema=%x ", ISP_READ(isp, BIU_ICR),
1980d02373f1SMatt Jacob 	    ISP_READ(isp, BIU_ISR), ISP_READ(isp, BIU_SEMA));
1981d02373f1SMatt Jacob 	printf("risc_hccr=%x\n", ISP_READ(isp, HCCR));
1982d02373f1SMatt Jacob 
1983d02373f1SMatt Jacob 
1984d02373f1SMatt Jacob 	if (IS_SCSI(isp)) {
1985d02373f1SMatt Jacob 		ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
1986d02373f1SMatt Jacob 		printf("    cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n",
1987d02373f1SMatt Jacob 			ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS),
1988d02373f1SMatt Jacob 			ISP_READ(isp, CDMA_FIFO_STS));
1989d02373f1SMatt Jacob 		printf("    ddma_conf=%x ddma_sts=%x ddma_fifostat=%x\n",
1990d02373f1SMatt Jacob 			ISP_READ(isp, DDMA_CONF), ISP_READ(isp, DDMA_STATUS),
1991d02373f1SMatt Jacob 			ISP_READ(isp, DDMA_FIFO_STS));
1992d02373f1SMatt Jacob 		printf("    sxp_int=%x sxp_gross=%x sxp(scsi_ctrl)=%x\n",
1993d02373f1SMatt Jacob 			ISP_READ(isp, SXP_INTERRUPT),
1994d02373f1SMatt Jacob 			ISP_READ(isp, SXP_GROSS_ERR),
1995d02373f1SMatt Jacob 			ISP_READ(isp, SXP_PINS_CTRL));
1996d02373f1SMatt Jacob 		ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);
1997d02373f1SMatt Jacob 	}
1998d02373f1SMatt Jacob 	printf("    mbox regs: %x %x %x %x %x\n",
1999d02373f1SMatt Jacob 	    ISP_READ(isp, OUTMAILBOX0), ISP_READ(isp, OUTMAILBOX1),
2000d02373f1SMatt Jacob 	    ISP_READ(isp, OUTMAILBOX2), ISP_READ(isp, OUTMAILBOX3),
2001d02373f1SMatt Jacob 	    ISP_READ(isp, OUTMAILBOX4));
2002d02373f1SMatt Jacob 	printf("    PCI Status Command/Status=%x\n",
20031923f739SMatt Jacob 	    pci_read_config(pcs->pci_dev, PCIR_COMMAND, 1));
200465adb54cSMatt Jacob }
2005