xref: /freebsd/sys/dev/isp/isp_pci.c (revision 086646f7c6630b28dc44a42d9d7ba67fec2b9da1)
1086646f7SJustin T. Gibbs /* $Id: isp_pci.c,v 1.28 1999/07/06 01:24:20 mjacob Exp $ */
25542fe4bSMatt Jacob /* release_6_5_99 */
365adb54cSMatt Jacob /*
465adb54cSMatt Jacob  * PCI specific probe and attach routines for Qlogic ISP SCSI adapters.
565adb54cSMatt Jacob  * FreeBSD Version.
665adb54cSMatt Jacob  *
765adb54cSMatt Jacob  *---------------------------------------
8222bb542SMatt Jacob  * Copyright (c) 1997, 1998, 1999 by Matthew Jacob
965adb54cSMatt Jacob  * NASA/Ames Research Center
1065adb54cSMatt Jacob  * All rights reserved.
1165adb54cSMatt Jacob  *---------------------------------------
1265adb54cSMatt Jacob  *
1365adb54cSMatt Jacob  * Redistribution and use in source and binary forms, with or without
1465adb54cSMatt Jacob  * modification, are permitted provided that the following conditions
1565adb54cSMatt Jacob  * are met:
1665adb54cSMatt Jacob  * 1. Redistributions of source code must retain the above copyright
1765adb54cSMatt Jacob  *    notice immediately at the beginning of the file, without modification,
1865adb54cSMatt Jacob  *    this list of conditions, and the following disclaimer.
1965adb54cSMatt Jacob  * 2. Redistributions in binary form must reproduce the above copyright
2065adb54cSMatt Jacob  *    notice, this list of conditions and the following disclaimer in the
2165adb54cSMatt Jacob  *    documentation and/or other materials provided with the distribution.
2265adb54cSMatt Jacob  * 3. The name of the author may not be used to endorse or promote products
2365adb54cSMatt Jacob  *    derived from this software without specific prior written permission.
2465adb54cSMatt Jacob  *
2565adb54cSMatt Jacob  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2665adb54cSMatt Jacob  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2765adb54cSMatt Jacob  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2865adb54cSMatt Jacob  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
2965adb54cSMatt Jacob  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3065adb54cSMatt Jacob  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3165adb54cSMatt Jacob  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3265adb54cSMatt Jacob  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3365adb54cSMatt Jacob  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3465adb54cSMatt Jacob  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3565adb54cSMatt Jacob  * SUCH DAMAGE.
3665adb54cSMatt Jacob  */
3765adb54cSMatt Jacob #include <dev/isp/isp_freebsd.h>
3865adb54cSMatt Jacob #include <dev/isp/asm_pci.h>
39d720e6d5SJustin T. Gibbs #include <sys/malloc.h>
40d720e6d5SJustin T. Gibbs #include <vm/vm.h>
41d720e6d5SJustin T. Gibbs #include <vm/pmap.h>
42d720e6d5SJustin T. Gibbs #include <vm/vm_extern.h>
43d720e6d5SJustin T. Gibbs 
4465adb54cSMatt Jacob 
4565adb54cSMatt Jacob #include <pci/pcireg.h>
4665adb54cSMatt Jacob #include <pci/pcivar.h>
4765adb54cSMatt Jacob 
48d720e6d5SJustin T. Gibbs #include <machine/bus_memio.h>
49d720e6d5SJustin T. Gibbs #include <machine/bus_pio.h>
50d720e6d5SJustin T. Gibbs #include <machine/bus.h>
51222bb542SMatt Jacob #include <machine/md_var.h>
52d720e6d5SJustin T. Gibbs 
53d59bd469SMatt Jacob 
5465adb54cSMatt Jacob static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int));
5565adb54cSMatt Jacob static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t));
56d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT
57d59bd469SMatt Jacob static u_int16_t isp_pci_rd_reg_1080 __P((struct ispsoftc *, int));
58d59bd469SMatt Jacob static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t));
59d59bd469SMatt Jacob #endif
6065adb54cSMatt Jacob static int isp_pci_mbxdma __P((struct ispsoftc *));
6165adb54cSMatt Jacob static int isp_pci_dmasetup __P((struct ispsoftc *, ISP_SCSI_XFER_T *,
6265adb54cSMatt Jacob 	ispreq_t *, u_int8_t *, u_int8_t));
63d720e6d5SJustin T. Gibbs static void
64d720e6d5SJustin T. Gibbs isp_pci_dmateardown __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t));
6565adb54cSMatt Jacob 
6665adb54cSMatt Jacob static void isp_pci_reset1 __P((struct ispsoftc *));
6765adb54cSMatt Jacob static void isp_pci_dumpregs __P((struct ispsoftc *));
6865adb54cSMatt Jacob 
69d59bd469SMatt Jacob #ifndef ISP_DISABLE_1020_SUPPORT
7065adb54cSMatt Jacob static struct ispmdvec mdvec = {
7165adb54cSMatt Jacob 	isp_pci_rd_reg,
7265adb54cSMatt Jacob 	isp_pci_wr_reg,
7365adb54cSMatt Jacob 	isp_pci_mbxdma,
7465adb54cSMatt Jacob 	isp_pci_dmasetup,
75d720e6d5SJustin T. Gibbs 	isp_pci_dmateardown,
7665adb54cSMatt Jacob 	NULL,
7765adb54cSMatt Jacob 	isp_pci_reset1,
7865adb54cSMatt Jacob 	isp_pci_dumpregs,
7965adb54cSMatt Jacob 	ISP_RISC_CODE,
8065adb54cSMatt Jacob 	ISP_CODE_LENGTH,
8165adb54cSMatt Jacob 	ISP_CODE_ORG,
8265adb54cSMatt Jacob 	ISP_CODE_VERSION,
83285e230dSMatt Jacob 	BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64,
84d720e6d5SJustin T. Gibbs 	0
8565adb54cSMatt Jacob };
86d59bd469SMatt Jacob #endif
8765adb54cSMatt Jacob 
88d59bd469SMatt Jacob #ifndef ISP_DISABLE_1080_SUPPORT
89d59bd469SMatt Jacob static struct ispmdvec mdvec_1080 = {
90d59bd469SMatt Jacob 	isp_pci_rd_reg_1080,
91d59bd469SMatt Jacob 	isp_pci_wr_reg_1080,
92d59bd469SMatt Jacob 	isp_pci_mbxdma,
93d59bd469SMatt Jacob 	isp_pci_dmasetup,
94d59bd469SMatt Jacob 	isp_pci_dmateardown,
95d59bd469SMatt Jacob 	NULL,
96d59bd469SMatt Jacob 	isp_pci_reset1,
97d59bd469SMatt Jacob 	isp_pci_dumpregs,
9892c49d78SMatt Jacob 	ISP1080_RISC_CODE,
9992c49d78SMatt Jacob 	ISP1080_CODE_LENGTH,
10092c49d78SMatt Jacob 	ISP1080_CODE_ORG,
10192c49d78SMatt Jacob 	ISP1080_CODE_VERSION,
102d59bd469SMatt Jacob 	BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64,
103d59bd469SMatt Jacob 	0
104d59bd469SMatt Jacob };
105d59bd469SMatt Jacob #endif
106d59bd469SMatt Jacob 
107d59bd469SMatt Jacob #ifndef ISP_DISABLE_2100_SUPPORT
10865adb54cSMatt Jacob static struct ispmdvec mdvec_2100 = {
10965adb54cSMatt Jacob 	isp_pci_rd_reg,
11065adb54cSMatt Jacob 	isp_pci_wr_reg,
11165adb54cSMatt Jacob 	isp_pci_mbxdma,
11265adb54cSMatt Jacob 	isp_pci_dmasetup,
113d720e6d5SJustin T. Gibbs 	isp_pci_dmateardown,
11465adb54cSMatt Jacob 	NULL,
11565adb54cSMatt Jacob 	isp_pci_reset1,
11665adb54cSMatt Jacob 	isp_pci_dumpregs,
11765adb54cSMatt Jacob 	ISP2100_RISC_CODE,
11865adb54cSMatt Jacob 	ISP2100_CODE_LENGTH,
11965adb54cSMatt Jacob 	ISP2100_CODE_ORG,
12065adb54cSMatt Jacob 	ISP2100_CODE_VERSION,
121285e230dSMatt Jacob 	0,			/* Irrelevant to the 2100 */
122d720e6d5SJustin T. Gibbs 	0
12365adb54cSMatt Jacob };
1245542fe4bSMatt Jacob #endif
125222bb542SMatt Jacob 
12686cb5d6bSMatt Jacob #ifndef	ISP_DISABLE_2200_SUPPORT
127222bb542SMatt Jacob static struct ispmdvec mdvec_2200 = {
128222bb542SMatt Jacob 	isp_pci_rd_reg,
129222bb542SMatt Jacob 	isp_pci_wr_reg,
130222bb542SMatt Jacob 	isp_pci_mbxdma,
131222bb542SMatt Jacob 	isp_pci_dmasetup,
132222bb542SMatt Jacob 	isp_pci_dmateardown,
133222bb542SMatt Jacob 	NULL,
134222bb542SMatt Jacob 	isp_pci_reset1,
135222bb542SMatt Jacob 	isp_pci_dumpregs,
1365542fe4bSMatt Jacob 	ISP2200_RISC_CODE,
1375542fe4bSMatt Jacob 	ISP2200_CODE_LENGTH,
138222bb542SMatt Jacob 	ISP2100_CODE_ORG,
139100f099bSMatt Jacob 	ISP2200_CODE_VERSION,
140222bb542SMatt Jacob 	0,
141222bb542SMatt Jacob 	0
142222bb542SMatt Jacob };
143d59bd469SMatt Jacob #endif
14465adb54cSMatt Jacob 
145d951bbcaSMatt Jacob #ifndef	SCSI_ISP_PREFER_MEM_MAP
146d951bbcaSMatt Jacob #ifdef	__alpha__
147d951bbcaSMatt Jacob #define	SCSI_ISP_PREFER_MEM_MAP	0
148d951bbcaSMatt Jacob #else
149d951bbcaSMatt Jacob #define	SCSI_ISP_PREFER_MEM_MAP	1
150d951bbcaSMatt Jacob #endif
151d951bbcaSMatt Jacob #endif
152d951bbcaSMatt Jacob 
15365adb54cSMatt Jacob #ifndef	PCIM_CMD_INVEN
15465adb54cSMatt Jacob #define	PCIM_CMD_INVEN			0x10
15565adb54cSMatt Jacob #endif
15665adb54cSMatt Jacob #ifndef	PCIM_CMD_BUSMASTEREN
15765adb54cSMatt Jacob #define	PCIM_CMD_BUSMASTEREN		0x0004
15865adb54cSMatt Jacob #endif
159d951bbcaSMatt Jacob #ifndef	PCIM_CMD_PERRESPEN
160d951bbcaSMatt Jacob #define	PCIM_CMD_PERRESPEN		0x0040
161d951bbcaSMatt Jacob #endif
162d951bbcaSMatt Jacob #ifndef	PCIM_CMD_SEREN
163d951bbcaSMatt Jacob #define	PCIM_CMD_SEREN			0x0100
164d951bbcaSMatt Jacob #endif
165d951bbcaSMatt Jacob 
166d951bbcaSMatt Jacob #ifndef	PCIR_COMMAND
167d951bbcaSMatt Jacob #define	PCIR_COMMAND			0x04
168d951bbcaSMatt Jacob #endif
169d951bbcaSMatt Jacob 
170d951bbcaSMatt Jacob #ifndef	PCIR_CACHELNSZ
171d951bbcaSMatt Jacob #define	PCIR_CACHELNSZ			0x0c
172d951bbcaSMatt Jacob #endif
173d951bbcaSMatt Jacob 
174d951bbcaSMatt Jacob #ifndef	PCIR_LATTIMER
175d951bbcaSMatt Jacob #define	PCIR_LATTIMER			0x0d
176d951bbcaSMatt Jacob #endif
177d951bbcaSMatt Jacob 
178ab6d0040SMatt Jacob #ifndef	PCIR_ROMADDR
179ab6d0040SMatt Jacob #define	PCIR_ROMADDR			0x30
180ab6d0040SMatt Jacob #endif
181ab6d0040SMatt Jacob 
18265adb54cSMatt Jacob #ifndef	PCI_VENDOR_QLOGIC
18365adb54cSMatt Jacob #define	PCI_VENDOR_QLOGIC	0x1077
18465adb54cSMatt Jacob #endif
18565adb54cSMatt Jacob 
18665adb54cSMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP1020
18765adb54cSMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP1020	0x1020
18865adb54cSMatt Jacob #endif
18965adb54cSMatt Jacob 
190d59bd469SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP1080
191d59bd469SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP1080	0x1080
192d59bd469SMatt Jacob #endif
193d59bd469SMatt Jacob 
194d59bd469SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP1240
195d59bd469SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP1240	0x1240
196d59bd469SMatt Jacob #endif
19765adb54cSMatt Jacob 
19865adb54cSMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP2100
19965adb54cSMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP2100	0x2100
20065adb54cSMatt Jacob #endif
20165adb54cSMatt Jacob 
202222bb542SMatt Jacob #ifndef	PCI_PRODUCT_QLOGIC_ISP2200
203222bb542SMatt Jacob #define	PCI_PRODUCT_QLOGIC_ISP2200	0x2200
204222bb542SMatt Jacob #endif
205222bb542SMatt Jacob 
206d59bd469SMatt Jacob #define	PCI_QLOGIC_ISP	((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC)
207d59bd469SMatt Jacob 
208d59bd469SMatt Jacob #define	PCI_QLOGIC_ISP1080	\
209d59bd469SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC)
210d59bd469SMatt Jacob 
211d59bd469SMatt Jacob #define	PCI_QLOGIC_ISP1240	\
212d59bd469SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC)
213d59bd469SMatt Jacob 
21465adb54cSMatt Jacob #define	PCI_QLOGIC_ISP2100	\
21565adb54cSMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC)
21665adb54cSMatt Jacob 
217222bb542SMatt Jacob #define	PCI_QLOGIC_ISP2200	\
218222bb542SMatt Jacob 	((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC)
219222bb542SMatt Jacob 
22065adb54cSMatt Jacob #define	IO_MAP_REG	0x10
22165adb54cSMatt Jacob #define	MEM_MAP_REG	0x14
22265adb54cSMatt Jacob 
223d951bbcaSMatt Jacob #define	PCI_DFLT_LTNCY	0x40
224d951bbcaSMatt Jacob #define	PCI_DFLT_LNSZ	0x10
22565adb54cSMatt Jacob 
226222bb542SMatt Jacob static const char *isp_pci_probe __P((pcici_t tag, pcidi_t type));
22765adb54cSMatt Jacob static void isp_pci_attach __P((pcici_t config_d, int unit));
22865adb54cSMatt Jacob 
229d720e6d5SJustin T. Gibbs /* This distinguishing define is not right, but it does work */
230a185f9b1SMatt Jacob #ifdef __alpha__
231a185f9b1SMatt Jacob #define IO_SPACE_MAPPING	ALPHA_BUS_SPACE_IO
232a185f9b1SMatt Jacob #define MEM_SPACE_MAPPING	ALPHA_BUS_SPACE_MEM
233a185f9b1SMatt Jacob #else
234a185f9b1SMatt Jacob #define IO_SPACE_MAPPING	I386_BUS_SPACE_IO
235a185f9b1SMatt Jacob #define MEM_SPACE_MAPPING	I386_BUS_SPACE_MEM
236a185f9b1SMatt Jacob #endif
23765adb54cSMatt Jacob 
23865adb54cSMatt Jacob struct isp_pcisoftc {
23965adb54cSMatt Jacob 	struct ispsoftc			pci_isp;
24065adb54cSMatt Jacob         pcici_t				pci_id;
24165adb54cSMatt Jacob 	bus_space_tag_t			pci_st;
24265adb54cSMatt Jacob 	bus_space_handle_t		pci_sh;
243d59bd469SMatt Jacob 	int16_t				pci_poff[_NREG_BLKS];
244d720e6d5SJustin T. Gibbs 	bus_dma_tag_t			parent_dmat;
245d720e6d5SJustin T. Gibbs 	bus_dma_tag_t			cntrol_dmat;
246d720e6d5SJustin T. Gibbs 	bus_dmamap_t			cntrol_dmap;
247d720e6d5SJustin T. Gibbs 	bus_dmamap_t			dmaps[MAXISPREQUEST];
24865adb54cSMatt Jacob };
24965adb54cSMatt Jacob 
250d720e6d5SJustin T. Gibbs static u_long ispunit;
25165adb54cSMatt Jacob 
25266235db5SEivind Eklund static struct pci_device isp_pci_driver = {
25365adb54cSMatt Jacob 	"isp",
25465adb54cSMatt Jacob 	isp_pci_probe,
25565adb54cSMatt Jacob 	isp_pci_attach,
256d720e6d5SJustin T. Gibbs 	&ispunit,
25765adb54cSMatt Jacob 	NULL
25865adb54cSMatt Jacob };
25996b3554eSPeter Wemm COMPAT_PCI_DRIVER (isp_pci, isp_pci_driver);
26065adb54cSMatt Jacob 
26165adb54cSMatt Jacob 
262222bb542SMatt Jacob static const char *
26317e318c6SMatt Jacob isp_pci_probe(pcici_t tag, pcidi_t type)
26465adb54cSMatt Jacob {
26565adb54cSMatt Jacob 	static int oneshot = 1;
26665adb54cSMatt Jacob 	char *x;
26765adb54cSMatt Jacob 
26865adb54cSMatt Jacob         switch (type) {
269d59bd469SMatt Jacob #ifndef	ISP_DISABLE_1020_SUPPORT
27065adb54cSMatt Jacob 	case PCI_QLOGIC_ISP:
271d59bd469SMatt Jacob 		x = "Qlogic ISP 1020/1040 PCI SCSI Adapter";
27265adb54cSMatt Jacob 		break;
273d59bd469SMatt Jacob #endif
274d59bd469SMatt Jacob #ifndef	ISP_DISABLE_1080_SUPPORT
275d59bd469SMatt Jacob 	case PCI_QLOGIC_ISP1080:
276c6608df3SMatt Jacob 		x = "Qlogic ISP 1080 PCI SCSI Adapter";
277c6608df3SMatt Jacob 		break;
278c6608df3SMatt Jacob 	case PCI_QLOGIC_ISP1240:
279c6608df3SMatt Jacob 		x = "Qlogic ISP 1240 PCI SCSI Adapter";
280d59bd469SMatt Jacob 		break;
281d59bd469SMatt Jacob #endif
282d59bd469SMatt Jacob #ifndef	ISP_DISABLE_2100_SUPPORT
28365adb54cSMatt Jacob 	case PCI_QLOGIC_ISP2100:
28465adb54cSMatt Jacob 		x = "Qlogic ISP 2100 PCI FC-AL Adapter";
28565adb54cSMatt Jacob 		break;
286d59bd469SMatt Jacob #endif
2875542fe4bSMatt Jacob #ifndef	ISP_DISABLE_2200_SUPPORT
2885542fe4bSMatt Jacob 	case PCI_QLOGIC_ISP2200:
2895542fe4bSMatt Jacob 		x = "Qlogic ISP 2200 PCI FC-AL Adapter";
2905542fe4bSMatt Jacob 		break;
2915542fe4bSMatt Jacob #endif
29265adb54cSMatt Jacob 	default:
29365adb54cSMatt Jacob 		return (NULL);
29465adb54cSMatt Jacob 	}
29565adb54cSMatt Jacob 	if (oneshot) {
29665adb54cSMatt Jacob 		oneshot = 0;
297d720e6d5SJustin T. Gibbs 		printf("%s Version %d.%d, Core Version %d.%d\n", PVS,
298d720e6d5SJustin T. Gibbs 		    ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
299d720e6d5SJustin T. Gibbs 		    ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
30065adb54cSMatt Jacob 	}
30165adb54cSMatt Jacob 	return (x);
30265adb54cSMatt Jacob }
30365adb54cSMatt Jacob 
30465adb54cSMatt Jacob 
30565adb54cSMatt Jacob static void
306222bb542SMatt Jacob isp_pci_attach(pcici_t cfid, int unit)
30765adb54cSMatt Jacob {
308222bb542SMatt Jacob 	int mapped, prefer_mem_map, bitmap;
309a185f9b1SMatt Jacob 	pci_port_t io_port;
310c6608df3SMatt Jacob 	u_int32_t data, linesz, psize, basetype;
31165adb54cSMatt Jacob 	struct isp_pcisoftc *pcs;
31265adb54cSMatt Jacob 	struct ispsoftc *isp;
31365adb54cSMatt Jacob 	vm_offset_t vaddr, paddr;
314c6608df3SMatt Jacob 	struct ispmdvec *mdvp;
315222bb542SMatt Jacob 	bus_size_t lim;
31665adb54cSMatt Jacob 	ISP_LOCKVAL_DECL;
31765adb54cSMatt Jacob 
31865adb54cSMatt Jacob 	pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT);
31965adb54cSMatt Jacob 	if (pcs == NULL) {
3209bffbcd4SBruce Evans 		printf("isp%d: cannot allocate softc\n", unit);
32165adb54cSMatt Jacob 		return;
32265adb54cSMatt Jacob 	}
32365adb54cSMatt Jacob 	bzero(pcs, sizeof (struct isp_pcisoftc));
32465adb54cSMatt Jacob 
325222bb542SMatt Jacob 	/*
3269ba86737SMatt Jacob 	 * Figure out if we're supposed to skip this one.
3279ba86737SMatt Jacob 	 */
3289ba86737SMatt Jacob 	if (getenv_int("isp_disable", &bitmap)) {
3299ba86737SMatt Jacob 		if (bitmap & (1 << unit)) {
3309ba86737SMatt Jacob 			printf("isp%d: not configuring\n", unit);
3319ba86737SMatt Jacob 			return;
3329ba86737SMatt Jacob 		}
3339ba86737SMatt Jacob 	}
3349ba86737SMatt Jacob 
3359ba86737SMatt Jacob 	/*
336222bb542SMatt Jacob 	 * Figure out which we should try first - memory mapping or i/o mapping?
337222bb542SMatt Jacob 	 */
338222bb542SMatt Jacob #if	SCSI_ISP_PREFER_MEM_MAP == 1
339222bb542SMatt Jacob 	prefer_mem_map = 1;
340222bb542SMatt Jacob #else
341222bb542SMatt Jacob 	prefer_mem_map = 0;
342222bb542SMatt Jacob #endif
343222bb542SMatt Jacob 	bitmap = 0;
344222bb542SMatt Jacob 	if (getenv_int("isp_mem_map", &bitmap)) {
345222bb542SMatt Jacob 		if (bitmap & (1 << unit))
346222bb542SMatt Jacob 			prefer_mem_map = 1;
347222bb542SMatt Jacob 	}
348222bb542SMatt Jacob 	bitmap = 0;
349222bb542SMatt Jacob 	if (getenv_int("isp_io_map", &bitmap)) {
350222bb542SMatt Jacob 		if (bitmap & (1 << unit))
351222bb542SMatt Jacob 			prefer_mem_map = 0;
352222bb542SMatt Jacob 	}
353222bb542SMatt Jacob 
35465adb54cSMatt Jacob 	vaddr = paddr = NULL;
35565adb54cSMatt Jacob 	mapped = 0;
356ab6d0040SMatt Jacob 	linesz = PCI_DFLT_LNSZ;
357d951bbcaSMatt Jacob 	/*
358d951bbcaSMatt Jacob 	 * Note that pci_conf_read is a 32 bit word aligned function.
359d951bbcaSMatt Jacob 	 */
360222bb542SMatt Jacob 	data = pci_conf_read(cfid, PCIR_COMMAND);
361222bb542SMatt Jacob 	if (prefer_mem_map) {
362222bb542SMatt Jacob 		if (data & PCI_COMMAND_MEM_ENABLE) {
363222bb542SMatt Jacob 			if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) {
364a185f9b1SMatt Jacob 				pcs->pci_st = MEM_SPACE_MAPPING;
365a185f9b1SMatt Jacob 				pcs->pci_sh = vaddr;
36665adb54cSMatt Jacob 				mapped++;
36765adb54cSMatt Jacob 			}
36865adb54cSMatt Jacob 		}
369a185f9b1SMatt Jacob 		if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) {
370222bb542SMatt Jacob 			if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) {
371a185f9b1SMatt Jacob 				pcs->pci_st = IO_SPACE_MAPPING;
372a185f9b1SMatt Jacob 				pcs->pci_sh = io_port;
37365adb54cSMatt Jacob 				mapped++;
37465adb54cSMatt Jacob 			}
37565adb54cSMatt Jacob 		}
376222bb542SMatt Jacob 	} else {
377222bb542SMatt Jacob 		if (data & PCI_COMMAND_IO_ENABLE) {
378222bb542SMatt Jacob 			if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) {
379d951bbcaSMatt Jacob 				pcs->pci_st = IO_SPACE_MAPPING;
380d951bbcaSMatt Jacob 				pcs->pci_sh = io_port;
381d951bbcaSMatt Jacob 				mapped++;
382d951bbcaSMatt Jacob 			}
383d951bbcaSMatt Jacob 		}
384d951bbcaSMatt Jacob 		if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) {
385222bb542SMatt Jacob 			if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) {
386d951bbcaSMatt Jacob 				pcs->pci_st = MEM_SPACE_MAPPING;
387d951bbcaSMatt Jacob 				pcs->pci_sh = vaddr;
388d951bbcaSMatt Jacob 				mapped++;
389d951bbcaSMatt Jacob 			}
390d951bbcaSMatt Jacob 		}
391222bb542SMatt Jacob 	}
39265adb54cSMatt Jacob 	if (mapped == 0) {
3939bffbcd4SBruce Evans 		printf("isp%d: unable to map any ports!\n", unit);
39465adb54cSMatt Jacob 		free(pcs, M_DEVBUF);
39565adb54cSMatt Jacob 		return;
39665adb54cSMatt Jacob 	}
397222bb542SMatt Jacob 	if (bootverbose)
39865adb54cSMatt Jacob 		printf("isp%d: using %s space register mapping\n", unit,
399a185f9b1SMatt Jacob 		    pcs->pci_st == IO_SPACE_MAPPING? "I/O" : "Memory");
40065adb54cSMatt Jacob 
401222bb542SMatt Jacob 	data = pci_conf_read(cfid, PCI_ID_REG);
402d59bd469SMatt Jacob 	pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
403d59bd469SMatt Jacob 	pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
404d59bd469SMatt Jacob 	pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
405d59bd469SMatt Jacob 	pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF;
406d59bd469SMatt Jacob 	pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
407c6608df3SMatt Jacob 	/*
408c6608df3SMatt Jacob  	 * GCC!
409c6608df3SMatt Jacob 	 */
410c6608df3SMatt Jacob 	mdvp = &mdvec;
411c6608df3SMatt Jacob 	basetype = ISP_HA_SCSI_UNKNOWN;
412c6608df3SMatt Jacob 	psize = sizeof (sdparam);
413222bb542SMatt Jacob 	lim = BUS_SPACE_MAXSIZE_32BIT;
414d59bd469SMatt Jacob #ifndef	ISP_DISABLE_1020_SUPPORT
41565adb54cSMatt Jacob 	if (data == PCI_QLOGIC_ISP) {
416c6608df3SMatt Jacob 		mdvp = &mdvec;
417c6608df3SMatt Jacob 		basetype = ISP_HA_SCSI_UNKNOWN;
418c6608df3SMatt Jacob 		psize = sizeof (sdparam);
419222bb542SMatt Jacob 		lim = BUS_SPACE_MAXSIZE_24BIT;
420d59bd469SMatt Jacob 	}
421d59bd469SMatt Jacob #endif
422d59bd469SMatt Jacob #ifndef	ISP_DISABLE_1080_SUPPORT
423c6608df3SMatt Jacob 	if (data == PCI_QLOGIC_ISP1080) {
424c6608df3SMatt Jacob 		mdvp = &mdvec_1080;
425c6608df3SMatt Jacob 		basetype = ISP_HA_SCSI_1080;
426c6608df3SMatt Jacob 		psize = sizeof (sdparam);
427c6608df3SMatt Jacob 		pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
428c6608df3SMatt Jacob 		    ISP1080_DMA_REGS_OFF;
429c6608df3SMatt Jacob 	}
430c6608df3SMatt Jacob 	if (data == PCI_QLOGIC_ISP1240) {
431c6608df3SMatt Jacob 		mdvp = &mdvec_1080;
432c6608df3SMatt Jacob 		basetype = ISP_HA_SCSI_12X0;
433c6608df3SMatt Jacob 		psize = 2 * sizeof (sdparam);
434d59bd469SMatt Jacob 		pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
435d59bd469SMatt Jacob 		    ISP1080_DMA_REGS_OFF;
436d59bd469SMatt Jacob 	}
437d59bd469SMatt Jacob #endif
438d59bd469SMatt Jacob #ifndef	ISP_DISABLE_2100_SUPPORT
439d59bd469SMatt Jacob 	if (data == PCI_QLOGIC_ISP2100) {
440c6608df3SMatt Jacob 		mdvp = &mdvec_2100;
441c6608df3SMatt Jacob 		basetype = ISP_HA_FC_2100;
442c6608df3SMatt Jacob 		psize = sizeof (fcparam);
443d59bd469SMatt Jacob 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
444d59bd469SMatt Jacob 		    PCI_MBOX_REGS2100_OFF;
445222bb542SMatt Jacob 		data = pci_conf_read(cfid, PCI_CLASS_REG);
446ab6d0040SMatt Jacob 		if ((data & 0xff) < 3) {
447ab6d0040SMatt Jacob 			/*
448ab6d0040SMatt Jacob 			 * XXX: Need to get the actual revision
449ab6d0040SMatt Jacob 			 * XXX: number of the 2100 FB. At any rate,
450ab6d0040SMatt Jacob 			 * XXX: lower cache line size for early revision
451ab6d0040SMatt Jacob 			 * XXX; boards.
452ab6d0040SMatt Jacob 			 */
453ab6d0040SMatt Jacob 			linesz = 1;
454ab6d0040SMatt Jacob 		}
45565adb54cSMatt Jacob 	}
4565542fe4bSMatt Jacob #endif
4575542fe4bSMatt Jacob #ifndef	ISP_DISABLE_2200_SUPPORT
458222bb542SMatt Jacob 	if (data == PCI_QLOGIC_ISP2200) {
459222bb542SMatt Jacob 		mdvp = &mdvec_2200;
460222bb542SMatt Jacob 		basetype = ISP_HA_FC_2200;
461222bb542SMatt Jacob 		psize = sizeof (fcparam);
462222bb542SMatt Jacob 		pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
463222bb542SMatt Jacob 		    PCI_MBOX_REGS2100_OFF;
464222bb542SMatt Jacob 	}
465d59bd469SMatt Jacob #endif
466c6608df3SMatt Jacob 	isp = &pcs->pci_isp;
467c6608df3SMatt Jacob 	isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT);
468c6608df3SMatt Jacob 	if (isp->isp_param == NULL) {
469c6608df3SMatt Jacob 		printf("isp%d: cannot allocate parameter data\n", unit);
470c6608df3SMatt Jacob 		return;
471c6608df3SMatt Jacob 	}
472c6608df3SMatt Jacob 	bzero(isp->isp_param, psize);
473c6608df3SMatt Jacob 	isp->isp_mdvec = mdvp;
474c6608df3SMatt Jacob 	isp->isp_type = basetype;
475c6608df3SMatt Jacob 	(void) snprintf(isp->isp_name, sizeof (isp->isp_name), "isp%d", unit);
476c6608df3SMatt Jacob 	isp->isp_osinfo.unit = unit;
47765adb54cSMatt Jacob 
478d951bbcaSMatt Jacob 	ISP_LOCK(isp);
479ab6d0040SMatt Jacob 
480d951bbcaSMatt Jacob 	/*
481d951bbcaSMatt Jacob 	 * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER
482d951bbcaSMatt Jacob 	 * are set.
483d951bbcaSMatt Jacob 	 */
484222bb542SMatt Jacob 	data = pci_cfgread(cfid, PCIR_COMMAND, 2);
485d951bbcaSMatt Jacob 	data |=	PCIM_CMD_SEREN		|
486d951bbcaSMatt Jacob 		PCIM_CMD_PERRESPEN	|
487d951bbcaSMatt Jacob 		PCIM_CMD_BUSMASTEREN	|
488d951bbcaSMatt Jacob 		PCIM_CMD_INVEN;
489222bb542SMatt Jacob 	pci_cfgwrite(cfid, PCIR_COMMAND, 2, data);
490ab6d0040SMatt Jacob 
491d951bbcaSMatt Jacob 	/*
492222bb542SMatt Jacob 	 * Make sure the Cache Line Size register is set sensibly.
493d951bbcaSMatt Jacob 	 */
494222bb542SMatt Jacob 	data = pci_cfgread(cfid, PCIR_CACHELNSZ, 1);
495ab6d0040SMatt Jacob 	if (data != linesz) {
496d951bbcaSMatt Jacob 		data = PCI_DFLT_LNSZ;
497d951bbcaSMatt Jacob 		printf("%s: set PCI line size to %d\n", isp->isp_name, data);
498222bb542SMatt Jacob 		pci_cfgwrite(cfid, PCIR_CACHELNSZ, data, 1);
499d951bbcaSMatt Jacob 	}
500ab6d0040SMatt Jacob 
501d951bbcaSMatt Jacob 	/*
502d951bbcaSMatt Jacob 	 * Make sure the Latency Timer is sane.
503d951bbcaSMatt Jacob 	 */
504222bb542SMatt Jacob 	data = pci_cfgread(cfid, PCIR_LATTIMER, 1);
505d951bbcaSMatt Jacob 	if (data < PCI_DFLT_LTNCY) {
506d951bbcaSMatt Jacob 		data = PCI_DFLT_LTNCY;
507d951bbcaSMatt Jacob 		printf("%s: set PCI latency to %d\n", isp->isp_name, data);
508222bb542SMatt Jacob 		pci_cfgwrite(cfid, PCIR_LATTIMER, data, 1);
509d951bbcaSMatt Jacob 	}
510ab6d0040SMatt Jacob 
511ab6d0040SMatt Jacob 	/*
512ab6d0040SMatt Jacob 	 * Make sure we've disabled the ROM.
513ab6d0040SMatt Jacob 	 */
514222bb542SMatt Jacob 	data = pci_cfgread(cfid, PCIR_ROMADDR, 4);
515ab6d0040SMatt Jacob 	data &= ~1;
516222bb542SMatt Jacob 	pci_cfgwrite(cfid, PCIR_ROMADDR, data, 4);
517d951bbcaSMatt Jacob 	ISP_UNLOCK(isp);
518d951bbcaSMatt Jacob 
519086646f7SJustin T. Gibbs 	if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
520222bb542SMatt Jacob 	    BUS_SPACE_MAXADDR, NULL, NULL, lim + 1,
521222bb542SMatt Jacob 	    255, lim, 0, &pcs->parent_dmat) != 0) {
522d720e6d5SJustin T. Gibbs 		printf("%s: could not create master dma tag\n", isp->isp_name);
523d720e6d5SJustin T. Gibbs 		free(pcs, M_DEVBUF);
524d720e6d5SJustin T. Gibbs 		return;
525d720e6d5SJustin T. Gibbs 	}
526222bb542SMatt Jacob 	if (pci_map_int(cfid, (void (*)(void *))isp_intr,
52765adb54cSMatt Jacob 	    (void *)isp, &IMASK) == 0) {
5289bffbcd4SBruce Evans 		printf("%s: could not map interrupt\n", isp->isp_name);
52965adb54cSMatt Jacob 		free(pcs, M_DEVBUF);
53065adb54cSMatt Jacob 		return;
53165adb54cSMatt Jacob 	}
53265adb54cSMatt Jacob 
533222bb542SMatt Jacob 	pcs->pci_id = cfid;
534d951bbcaSMatt Jacob #ifdef	SCSI_ISP_NO_FWLOAD_MASK
535d951bbcaSMatt Jacob 	if (SCSI_ISP_NO_FWLOAD_MASK && (SCSI_ISP_NO_FWLOAD_MASK & (1 << unit)))
536d951bbcaSMatt Jacob 		isp->isp_confopts |= ISP_CFG_NORELOAD;
537d951bbcaSMatt Jacob #endif
538222bb542SMatt Jacob 	if (getenv_int("isp_no_fwload", &bitmap)) {
539222bb542SMatt Jacob 		if (bitmap & (1 << unit))
540222bb542SMatt Jacob 			isp->isp_confopts |= ISP_CFG_NORELOAD;
541222bb542SMatt Jacob 	}
542222bb542SMatt Jacob 	if (getenv_int("isp_fwload", &bitmap)) {
543222bb542SMatt Jacob 		if (bitmap & (1 << unit))
544222bb542SMatt Jacob 			isp->isp_confopts &= ~ISP_CFG_NORELOAD;
545222bb542SMatt Jacob 	}
546222bb542SMatt Jacob 
547d951bbcaSMatt Jacob #ifdef	SCSI_ISP_NO_NVRAM_MASK
548ab6d0040SMatt Jacob 	if (SCSI_ISP_NO_NVRAM_MASK && (SCSI_ISP_NO_NVRAM_MASK & (1 << unit))) {
549ab6d0040SMatt Jacob 		printf("%s: ignoring NVRAM\n", isp->isp_name);
550d951bbcaSMatt Jacob 		isp->isp_confopts |= ISP_CFG_NONVRAM;
551ab6d0040SMatt Jacob 	}
552d951bbcaSMatt Jacob #endif
553222bb542SMatt Jacob 	if (getenv_int("isp_no_nvram", &bitmap)) {
554222bb542SMatt Jacob 		if (bitmap & (1 << unit))
555222bb542SMatt Jacob 			isp->isp_confopts |= ISP_CFG_NONVRAM;
556222bb542SMatt Jacob 	}
557222bb542SMatt Jacob 	if (getenv_int("isp_nvram", &bitmap)) {
558222bb542SMatt Jacob 		if (bitmap & (1 << unit))
559222bb542SMatt Jacob 			isp->isp_confopts &= ~ISP_CFG_NONVRAM;
560222bb542SMatt Jacob 	}
561222bb542SMatt Jacob 
562222bb542SMatt Jacob #ifdef	SCSI_ISP_FCDUPLEX
563222bb542SMatt Jacob 	if (IS_FC(isp)) {
564222bb542SMatt Jacob 		if (SCSI_ISP_FCDUPLEX && (SCSI_ISP_FCDUPLEX & (1 << unit))) {
565222bb542SMatt Jacob 			isp->isp_confopts |= ISP_CFG_FULL_DUPLEX;
566222bb542SMatt Jacob 		}
567222bb542SMatt Jacob 	}
568222bb542SMatt Jacob #endif
569222bb542SMatt Jacob 	if (getenv_int("isp_fcduplex", &bitmap)) {
570222bb542SMatt Jacob 		if (bitmap & (1 << unit))
571222bb542SMatt Jacob 			isp->isp_confopts |= ISP_CFG_FULL_DUPLEX;
572222bb542SMatt Jacob 	}
573222bb542SMatt Jacob 	if (getenv_int("isp_no_fcduplex", &bitmap)) {
574222bb542SMatt Jacob 		if (bitmap & (1 << unit))
575222bb542SMatt Jacob 			isp->isp_confopts &= ~ISP_CFG_FULL_DUPLEX;
576222bb542SMatt Jacob 	}
577222bb542SMatt Jacob 
578222bb542SMatt Jacob 	if (getenv_int("isp_seed", &isp->isp_osinfo.seed)) {
579222bb542SMatt Jacob 		isp->isp_osinfo.seed <<= 8;
580222bb542SMatt Jacob 		isp->isp_osinfo.seed += (unit + 1);
581222bb542SMatt Jacob 	} else {
582222bb542SMatt Jacob 		/*
583222bb542SMatt Jacob 		 * poor man's attempt at pseudo randomness.
584222bb542SMatt Jacob 		 */
585222bb542SMatt Jacob 		long i = (long) isp;
586222bb542SMatt Jacob 
587222bb542SMatt Jacob 		i >>= 5;
588222bb542SMatt Jacob 		i &= 0x7;
589222bb542SMatt Jacob 
590222bb542SMatt Jacob 		/*
591222bb542SMatt Jacob 		 * This isn't very random, but it's the best we can do for
592222bb542SMatt Jacob 		 * the real edge case of cards that don't have WWNs.
593222bb542SMatt Jacob 		 */
594222bb542SMatt Jacob 		isp->isp_osinfo.seed += ((int) cfid->bus) << 16;
595222bb542SMatt Jacob 		isp->isp_osinfo.seed += ((int) cfid->slot) << 8;
596222bb542SMatt Jacob 		isp->isp_osinfo.seed += ((int) cfid->func);
597222bb542SMatt Jacob 		while (version[i])
598222bb542SMatt Jacob 			isp->isp_osinfo.seed += (int) version[i++];
599222bb542SMatt Jacob 		isp->isp_osinfo.seed <<= 8;
600222bb542SMatt Jacob 		isp->isp_osinfo.seed += (unit + 1);
601222bb542SMatt Jacob 	}
602222bb542SMatt Jacob 
603d720e6d5SJustin T. Gibbs 	ISP_LOCK(isp);
60465adb54cSMatt Jacob 	isp_reset(isp);
60565adb54cSMatt Jacob 	if (isp->isp_state != ISP_RESETSTATE) {
606222bb542SMatt Jacob 		(void) pci_unmap_int(cfid);
607d720e6d5SJustin T. Gibbs 		ISP_UNLOCK(isp);
60865adb54cSMatt Jacob 		free(pcs, M_DEVBUF);
60965adb54cSMatt Jacob 		return;
61065adb54cSMatt Jacob 	}
61165adb54cSMatt Jacob 	isp_init(isp);
61265adb54cSMatt Jacob 	if (isp->isp_state != ISP_INITSTATE) {
613d59bd469SMatt Jacob 		/* If we're a Fibre Channel Card, we allow deferred attach */
614222bb542SMatt Jacob 		if (IS_SCSI(isp)) {
61565adb54cSMatt Jacob 			isp_uninit(isp);
616222bb542SMatt Jacob 			(void) pci_unmap_int(cfid); /* Does nothing */
617c6608df3SMatt Jacob 			ISP_UNLOCK(isp);
61865adb54cSMatt Jacob 			free(pcs, M_DEVBUF);
619c6608df3SMatt Jacob 			return;
620d59bd469SMatt Jacob 		}
62165adb54cSMatt Jacob 	}
62265adb54cSMatt Jacob 	isp_attach(isp);
62365adb54cSMatt Jacob 	if (isp->isp_state != ISP_RUNSTATE) {
624d59bd469SMatt Jacob 		/* If we're a Fibre Channel Card, we allow deferred attach */
62592c49d78SMatt Jacob 		if (IS_SCSI(isp)) {
62665adb54cSMatt Jacob 			isp_uninit(isp);
627222bb542SMatt Jacob 			(void) pci_unmap_int(cfid); /* Does nothing */
628c6608df3SMatt Jacob 			ISP_UNLOCK(isp);
62965adb54cSMatt Jacob 			free(pcs, M_DEVBUF);
630c6608df3SMatt Jacob 			return;
63165adb54cSMatt Jacob 		}
632d59bd469SMatt Jacob 	}
633d720e6d5SJustin T. Gibbs 	ISP_UNLOCK(isp);
634e37c0455SDoug Rabson #ifdef __alpha__
635d951bbcaSMatt Jacob 	/*
636d951bbcaSMatt Jacob 	 * THIS SHOULD NOT HAVE TO BE HERE
637d951bbcaSMatt Jacob 	 */
638222bb542SMatt Jacob 	alpha_register_pci_scsi(cfid->bus, cfid->slot, isp->isp_sim);
639e37c0455SDoug Rabson #endif
64065adb54cSMatt Jacob }
64165adb54cSMatt Jacob 
64265adb54cSMatt Jacob static u_int16_t
643d59bd469SMatt Jacob isp_pci_rd_reg(isp, regoff)
644d59bd469SMatt Jacob 	struct ispsoftc *isp;
645d59bd469SMatt Jacob 	int regoff;
64665adb54cSMatt Jacob {
64765adb54cSMatt Jacob 	u_int16_t rv;
64865adb54cSMatt Jacob 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
649d59bd469SMatt Jacob 	int offset, oldconf = 0;
65065adb54cSMatt Jacob 
651d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
65265adb54cSMatt Jacob 		/*
65365adb54cSMatt Jacob 		 * We will assume that someone has paused the RISC processor.
65465adb54cSMatt Jacob 		 */
655d59bd469SMatt Jacob 		oldconf = isp_pci_rd_reg(isp, BIU_CONF1);
656d59bd469SMatt Jacob 		isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP);
65765adb54cSMatt Jacob 	}
658d59bd469SMatt Jacob 	offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
659d59bd469SMatt Jacob 	offset += (regoff & 0xff);
66065adb54cSMatt Jacob 	rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset);
661d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
662d59bd469SMatt Jacob 		isp_pci_wr_reg(isp, BIU_CONF1, oldconf);
66365adb54cSMatt Jacob 	}
66465adb54cSMatt Jacob 	return (rv);
66565adb54cSMatt Jacob }
66665adb54cSMatt Jacob 
66765adb54cSMatt Jacob static void
668d59bd469SMatt Jacob isp_pci_wr_reg(isp, regoff, val)
669d59bd469SMatt Jacob 	struct ispsoftc *isp;
670d59bd469SMatt Jacob 	int regoff;
671d59bd469SMatt Jacob 	u_int16_t val;
67265adb54cSMatt Jacob {
67365adb54cSMatt Jacob 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
674d59bd469SMatt Jacob 	int offset, oldconf = 0;
675d59bd469SMatt Jacob 
676d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
67765adb54cSMatt Jacob 		/*
67865adb54cSMatt Jacob 		 * We will assume that someone has paused the RISC processor.
67965adb54cSMatt Jacob 		 */
680d59bd469SMatt Jacob 		oldconf = isp_pci_rd_reg(isp, BIU_CONF1);
681d59bd469SMatt Jacob 		isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP);
68265adb54cSMatt Jacob 	}
683d59bd469SMatt Jacob 	offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
684d59bd469SMatt Jacob 	offset += (regoff & 0xff);
68565adb54cSMatt Jacob 	bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val);
686d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
687d59bd469SMatt Jacob 		isp_pci_wr_reg(isp, BIU_CONF1, oldconf);
68865adb54cSMatt Jacob 	}
68965adb54cSMatt Jacob }
69065adb54cSMatt Jacob 
691d59bd469SMatt Jacob #ifndef	ISP_DISABLE_1080_SUPPORT
692d59bd469SMatt Jacob static u_int16_t
693d59bd469SMatt Jacob isp_pci_rd_reg_1080(isp, regoff)
694d59bd469SMatt Jacob 	struct ispsoftc *isp;
695d59bd469SMatt Jacob 	int regoff;
696d59bd469SMatt Jacob {
697d59bd469SMatt Jacob 	u_int16_t rv;
698d59bd469SMatt Jacob 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
699d59bd469SMatt Jacob 	int offset, oc = 0;
700d59bd469SMatt Jacob 
701d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
702d59bd469SMatt Jacob 		/*
703d59bd469SMatt Jacob 		 * We will assume that someone has paused the RISC processor.
704d59bd469SMatt Jacob 		 */
705d59bd469SMatt Jacob 		oc = isp_pci_rd_reg(isp, BIU_CONF1);
706d59bd469SMatt Jacob 		isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP);
707d59bd469SMatt Jacob 	} else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
708d59bd469SMatt Jacob 		oc = isp_pci_rd_reg(isp, BIU_CONF1);
709d59bd469SMatt Jacob 		isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA);
710d59bd469SMatt Jacob 	}
711d59bd469SMatt Jacob 	offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
712d59bd469SMatt Jacob 	offset += (regoff & 0xff);
713d59bd469SMatt Jacob 	rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset);
714d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
715d59bd469SMatt Jacob 	    ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) {
716d59bd469SMatt Jacob 		isp_pci_wr_reg(isp, BIU_CONF1, oc);
717d59bd469SMatt Jacob 	}
718d59bd469SMatt Jacob 	return (rv);
719d59bd469SMatt Jacob }
720d59bd469SMatt Jacob 
721d59bd469SMatt Jacob static void
722d59bd469SMatt Jacob isp_pci_wr_reg_1080(isp, regoff, val)
723d59bd469SMatt Jacob 	struct ispsoftc *isp;
724d59bd469SMatt Jacob 	int regoff;
725d59bd469SMatt Jacob 	u_int16_t val;
726d59bd469SMatt Jacob {
727d59bd469SMatt Jacob 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
728d59bd469SMatt Jacob 	int offset, oc = 0;
729d59bd469SMatt Jacob 
730d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
731d59bd469SMatt Jacob 		/*
732d59bd469SMatt Jacob 		 * We will assume that someone has paused the RISC processor.
733d59bd469SMatt Jacob 		 */
734d59bd469SMatt Jacob 		oc = isp_pci_rd_reg(isp, BIU_CONF1);
735d59bd469SMatt Jacob 		isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP);
736d59bd469SMatt Jacob 	} else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
737d59bd469SMatt Jacob 		oc = isp_pci_rd_reg(isp, BIU_CONF1);
738d59bd469SMatt Jacob 		isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA);
739d59bd469SMatt Jacob 	}
740d59bd469SMatt Jacob 	offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
741d59bd469SMatt Jacob 	offset += (regoff & 0xff);
742d59bd469SMatt Jacob 	bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val);
743d59bd469SMatt Jacob 	if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
744d59bd469SMatt Jacob 	    ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) {
745d59bd469SMatt Jacob 		isp_pci_wr_reg(isp, BIU_CONF1, oc);
746d59bd469SMatt Jacob 	}
747d59bd469SMatt Jacob }
748d59bd469SMatt Jacob #endif
749d59bd469SMatt Jacob 
750d59bd469SMatt Jacob 
751d720e6d5SJustin T. Gibbs static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int));
752d720e6d5SJustin T. Gibbs static void isp_map_result __P((void *, bus_dma_segment_t *, int, int));
753d720e6d5SJustin T. Gibbs static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int));
754d720e6d5SJustin T. Gibbs 
755222bb542SMatt Jacob struct imush {
756222bb542SMatt Jacob 	struct ispsoftc *isp;
757222bb542SMatt Jacob 	int error;
758222bb542SMatt Jacob };
759222bb542SMatt Jacob 
760d720e6d5SJustin T. Gibbs static void
76117e318c6SMatt Jacob isp_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error)
762d720e6d5SJustin T. Gibbs {
763222bb542SMatt Jacob 	struct imush *imushp = (struct imush *) arg;
764222bb542SMatt Jacob 	if (error) {
765222bb542SMatt Jacob 		imushp->error = error;
766222bb542SMatt Jacob 	} else {
767222bb542SMatt Jacob 		imushp->isp->isp_rquest_dma = segs->ds_addr;
768222bb542SMatt Jacob 	}
769d720e6d5SJustin T. Gibbs }
770d720e6d5SJustin T. Gibbs 
771d720e6d5SJustin T. Gibbs static void
77217e318c6SMatt Jacob isp_map_result(void *arg, bus_dma_segment_t *segs, int nseg, int error)
773d720e6d5SJustin T. Gibbs {
774222bb542SMatt Jacob 	struct imush *imushp = (struct imush *) arg;
775222bb542SMatt Jacob 	if (error) {
776222bb542SMatt Jacob 		imushp->error = error;
777222bb542SMatt Jacob 	} else {
778222bb542SMatt Jacob 		imushp->isp->isp_result_dma = segs->ds_addr;
779222bb542SMatt Jacob 	}
780d720e6d5SJustin T. Gibbs }
781d720e6d5SJustin T. Gibbs 
782d720e6d5SJustin T. Gibbs static void
78317e318c6SMatt Jacob isp_map_fcscrt(void *arg, bus_dma_segment_t *segs, int nseg, int error)
784d720e6d5SJustin T. Gibbs {
785222bb542SMatt Jacob 	struct imush *imushp = (struct imush *) arg;
786222bb542SMatt Jacob 	if (error) {
787222bb542SMatt Jacob 		imushp->error = error;
788222bb542SMatt Jacob 	} else {
789222bb542SMatt Jacob 		fcparam *fcp = imushp->isp->isp_param;
790d720e6d5SJustin T. Gibbs 		fcp->isp_scdma = segs->ds_addr;
791d720e6d5SJustin T. Gibbs 	}
792222bb542SMatt Jacob }
793d720e6d5SJustin T. Gibbs 
794d720e6d5SJustin T. Gibbs static int
79517e318c6SMatt Jacob isp_pci_mbxdma(struct ispsoftc *isp)
796d720e6d5SJustin T. Gibbs {
797d720e6d5SJustin T. Gibbs 	struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
798d720e6d5SJustin T. Gibbs 	caddr_t base;
799d720e6d5SJustin T. Gibbs 	u_int32_t len;
800d720e6d5SJustin T. Gibbs 	int i, error;
801222bb542SMatt Jacob 	bus_size_t lim;
802222bb542SMatt Jacob 	struct imush im;
803222bb542SMatt Jacob 
804222bb542SMatt Jacob 
805222bb542SMatt Jacob 	if (IS_FC(isp) || IS_1080(isp) || IS_12X0(isp))
806222bb542SMatt Jacob 		lim = BUS_SPACE_MAXADDR + 1;
807222bb542SMatt Jacob 	else
808222bb542SMatt Jacob 		lim = BUS_SPACE_MAXADDR_24BIT + 1;
809d720e6d5SJustin T. Gibbs 
810d720e6d5SJustin T. Gibbs 	/*
811d720e6d5SJustin T. Gibbs 	 * Allocate and map the request, result queues, plus FC scratch area.
812d720e6d5SJustin T. Gibbs 	 */
813d720e6d5SJustin T. Gibbs 	len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN);
814d720e6d5SJustin T. Gibbs 	len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN);
815222bb542SMatt Jacob 	if (IS_FC(isp)) {
816d720e6d5SJustin T. Gibbs 		len += ISP2100_SCRLEN;
817d720e6d5SJustin T. Gibbs 	}
818222bb542SMatt Jacob 	if (bus_dma_tag_create(pci->parent_dmat, PAGE_SIZE, lim,
819222bb542SMatt Jacob 	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, len, 1,
820222bb542SMatt Jacob 	    BUS_SPACE_MAXSIZE_32BIT, 0, &pci->cntrol_dmat) != 0) {
821d720e6d5SJustin T. Gibbs 		printf("%s: cannot create a dma tag for control spaces\n",
822d720e6d5SJustin T. Gibbs 		    isp->isp_name);
823d720e6d5SJustin T. Gibbs 		return (1);
824d720e6d5SJustin T. Gibbs 	}
825d720e6d5SJustin T. Gibbs 	if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base,
826d720e6d5SJustin T. Gibbs 	    BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) {
8274873663cSMatt Jacob 		printf("%s: cannot allocate %d bytes of CCB memory\n",
8284873663cSMatt Jacob 		    isp->isp_name, len);
829d720e6d5SJustin T. Gibbs 		return (1);
830d720e6d5SJustin T. Gibbs 	}
831d720e6d5SJustin T. Gibbs 
832d720e6d5SJustin T. Gibbs 	isp->isp_rquest = base;
833222bb542SMatt Jacob 	im.isp = isp;
834222bb542SMatt Jacob 	im.error = 0;
835d720e6d5SJustin T. Gibbs 	bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest,
836222bb542SMatt Jacob 	    ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN), isp_map_rquest, &im, 0);
837222bb542SMatt Jacob 	if (im.error) {
838222bb542SMatt Jacob 		printf("%s: error %d loading dma map for DMA request queue\n",
839222bb542SMatt Jacob 		    isp->isp_name, im.error);
840222bb542SMatt Jacob 		return (1);
841222bb542SMatt Jacob 	}
842d720e6d5SJustin T. Gibbs 	isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN);
843222bb542SMatt Jacob 	im.error = 0;
844d720e6d5SJustin T. Gibbs 	bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result,
845222bb542SMatt Jacob 	    ISP_QUEUE_SIZE(RESULT_QUEUE_LEN), isp_map_result, &im, 0);
846222bb542SMatt Jacob 	if (im.error) {
847222bb542SMatt Jacob 		printf("%s: error %d loading dma map for DMA result queue\n",
848222bb542SMatt Jacob 		    isp->isp_name, im.error);
849222bb542SMatt Jacob 		return (1);
850222bb542SMatt Jacob 	}
851d720e6d5SJustin T. Gibbs 
852d720e6d5SJustin T. Gibbs 	/*
853d720e6d5SJustin T. Gibbs 	 * Use this opportunity to initialize/create data DMA maps.
854d720e6d5SJustin T. Gibbs 	 */
855d720e6d5SJustin T. Gibbs 	for (i = 0; i < MAXISPREQUEST; i++) {
856d720e6d5SJustin T. Gibbs 		error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]);
857d720e6d5SJustin T. Gibbs 		if (error) {
8584873663cSMatt Jacob 			printf("%s: error %d creating mailbox DMA maps\n",
859d720e6d5SJustin T. Gibbs 			    isp->isp_name, error);
860d720e6d5SJustin T. Gibbs 			return (1);
861d720e6d5SJustin T. Gibbs 		}
862d720e6d5SJustin T. Gibbs 	}
863222bb542SMatt Jacob 	if (IS_FC(isp)) {
86492c49d78SMatt Jacob 		fcparam *fcp = (fcparam *) isp->isp_param;
86592c49d78SMatt Jacob 		fcp->isp_scratch = base +
86692c49d78SMatt Jacob 			ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN) +
86792c49d78SMatt Jacob 			ISP_QUEUE_SIZE(RESULT_QUEUE_LEN);
868222bb542SMatt Jacob 		im.error = 0;
86992c49d78SMatt Jacob 		bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap,
870222bb542SMatt Jacob 		    fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, &im, 0);
871222bb542SMatt Jacob 		if (im.error) {
872222bb542SMatt Jacob 			printf("%s: error %d loading FC scratch area\n",
873222bb542SMatt Jacob 			    isp->isp_name, im.error);
874222bb542SMatt Jacob 			return (1);
875222bb542SMatt Jacob 		}
87692c49d78SMatt Jacob 	}
877d720e6d5SJustin T. Gibbs 	return (0);
878d720e6d5SJustin T. Gibbs }
879d720e6d5SJustin T. Gibbs 
880d720e6d5SJustin T. Gibbs static void dma2 __P((void *, bus_dma_segment_t *, int, int));
881d720e6d5SJustin T. Gibbs typedef struct {
882d720e6d5SJustin T. Gibbs 	struct ispsoftc *isp;
883d720e6d5SJustin T. Gibbs 	ISP_SCSI_XFER_T *ccb;
884d720e6d5SJustin T. Gibbs 	ispreq_t *rq;
885d720e6d5SJustin T. Gibbs 	u_int8_t *iptrp;
886d720e6d5SJustin T. Gibbs 	u_int8_t optr;
887d720e6d5SJustin T. Gibbs 	u_int error;
888d720e6d5SJustin T. Gibbs } mush_t;
889d720e6d5SJustin T. Gibbs 
8904873663cSMatt Jacob #define	MUSHERR_NOQENTRIES	-2
8914873663cSMatt Jacob 
892d720e6d5SJustin T. Gibbs static void
89317e318c6SMatt Jacob dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
894d720e6d5SJustin T. Gibbs {
895d720e6d5SJustin T. Gibbs 	mush_t *mp;
896d720e6d5SJustin T. Gibbs 	ISP_SCSI_XFER_T *ccb;
897d720e6d5SJustin T. Gibbs 	struct ispsoftc *isp;
898d720e6d5SJustin T. Gibbs 	struct isp_pcisoftc *pci;
899d720e6d5SJustin T. Gibbs 	bus_dmamap_t *dp;
900d720e6d5SJustin T. Gibbs 	bus_dma_segment_t *eseg;
901d720e6d5SJustin T. Gibbs 	ispreq_t *rq;
902d720e6d5SJustin T. Gibbs 	u_int8_t *iptrp;
903d720e6d5SJustin T. Gibbs 	u_int8_t optr;
904d720e6d5SJustin T. Gibbs 	ispcontreq_t *crq;
905d720e6d5SJustin T. Gibbs 	int drq, seglim, datalen;
906d720e6d5SJustin T. Gibbs 
907d720e6d5SJustin T. Gibbs 	mp = (mush_t *) arg;
908d720e6d5SJustin T. Gibbs 	if (error) {
909d720e6d5SJustin T. Gibbs 		mp->error = error;
910d720e6d5SJustin T. Gibbs 		return;
911d720e6d5SJustin T. Gibbs 	}
912d720e6d5SJustin T. Gibbs 
913d720e6d5SJustin T. Gibbs 	isp = mp->isp;
914d720e6d5SJustin T. Gibbs 	if (nseg < 1) {
915d720e6d5SJustin T. Gibbs 		printf("%s: zero or negative segment count\n", isp->isp_name);
916d720e6d5SJustin T. Gibbs 		mp->error = EFAULT;
917d720e6d5SJustin T. Gibbs 		return;
918d720e6d5SJustin T. Gibbs 	}
919d720e6d5SJustin T. Gibbs 	ccb = mp->ccb;
920d720e6d5SJustin T. Gibbs 	rq = mp->rq;
921d720e6d5SJustin T. Gibbs 	iptrp = mp->iptrp;
922d720e6d5SJustin T. Gibbs 	optr = mp->optr;
923d720e6d5SJustin T. Gibbs 
924d720e6d5SJustin T. Gibbs 	pci = (struct isp_pcisoftc *)isp;
925d720e6d5SJustin T. Gibbs 	dp = &pci->dmaps[rq->req_handle - 1];
926d720e6d5SJustin T. Gibbs 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
927d720e6d5SJustin T. Gibbs 		bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD);
928d720e6d5SJustin T. Gibbs 		drq = REQFLAG_DATA_IN;
929d720e6d5SJustin T. Gibbs 	} else {
930d720e6d5SJustin T. Gibbs 		bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE);
931d720e6d5SJustin T. Gibbs 		drq = REQFLAG_DATA_OUT;
932d720e6d5SJustin T. Gibbs 	}
933d720e6d5SJustin T. Gibbs 
934d720e6d5SJustin T. Gibbs 	datalen = XS_XFRLEN(ccb);
935222bb542SMatt Jacob 	if (IS_FC(isp)) {
936d720e6d5SJustin T. Gibbs 		seglim = ISP_RQDSEG_T2;
937d720e6d5SJustin T. Gibbs 		((ispreqt2_t *)rq)->req_totalcnt = datalen;
938d720e6d5SJustin T. Gibbs 		((ispreqt2_t *)rq)->req_flags |= drq;
939d720e6d5SJustin T. Gibbs 	} else {
940d720e6d5SJustin T. Gibbs 		seglim = ISP_RQDSEG;
941d720e6d5SJustin T. Gibbs 		rq->req_flags |= drq;
942d720e6d5SJustin T. Gibbs 	}
943d720e6d5SJustin T. Gibbs 
944d720e6d5SJustin T. Gibbs 	eseg = dm_segs + nseg;
945d720e6d5SJustin T. Gibbs 
946d720e6d5SJustin T. Gibbs 	while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) {
947222bb542SMatt Jacob 		if (IS_FC(isp)) {
948d720e6d5SJustin T. Gibbs 			ispreqt2_t *rq2 = (ispreqt2_t *)rq;
949d720e6d5SJustin T. Gibbs 			rq2->req_dataseg[rq2->req_seg_count].ds_base =
950d720e6d5SJustin T. Gibbs 			    dm_segs->ds_addr;
951d720e6d5SJustin T. Gibbs 			rq2->req_dataseg[rq2->req_seg_count].ds_count =
952d720e6d5SJustin T. Gibbs 			    dm_segs->ds_len;
953d720e6d5SJustin T. Gibbs 		} else {
954d720e6d5SJustin T. Gibbs 			rq->req_dataseg[rq->req_seg_count].ds_base =
955d720e6d5SJustin T. Gibbs 				dm_segs->ds_addr;
956d720e6d5SJustin T. Gibbs 			rq->req_dataseg[rq->req_seg_count].ds_count =
957d720e6d5SJustin T. Gibbs 				dm_segs->ds_len;
958d720e6d5SJustin T. Gibbs 		}
959d720e6d5SJustin T. Gibbs 		datalen -= dm_segs->ds_len;
960d720e6d5SJustin T. Gibbs #if	0
961222bb542SMatt Jacob 		if (IS_FC(isp)) {
962d720e6d5SJustin T. Gibbs 			ispreqt2_t *rq2 = (ispreqt2_t *)rq;
963d720e6d5SJustin T. Gibbs 			printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n",
964d720e6d5SJustin T. Gibbs 			    isp->isp_name, rq->req_seg_count,
965d720e6d5SJustin T. Gibbs 			    rq2->req_dataseg[rq2->req_seg_count].ds_count,
966d720e6d5SJustin T. Gibbs 			    rq2->req_dataseg[rq2->req_seg_count].ds_base);
967d720e6d5SJustin T. Gibbs 		} else {
968d720e6d5SJustin T. Gibbs 			printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n",
969d720e6d5SJustin T. Gibbs 			    isp->isp_name, rq->req_seg_count,
970d720e6d5SJustin T. Gibbs 			    rq->req_dataseg[rq->req_seg_count].ds_count,
971d720e6d5SJustin T. Gibbs 			    rq->req_dataseg[rq->req_seg_count].ds_base);
972d720e6d5SJustin T. Gibbs 		}
973d720e6d5SJustin T. Gibbs #endif
974d720e6d5SJustin T. Gibbs 		rq->req_seg_count++;
975d720e6d5SJustin T. Gibbs 		dm_segs++;
976d720e6d5SJustin T. Gibbs 	}
977d720e6d5SJustin T. Gibbs 
978d720e6d5SJustin T. Gibbs 	while (datalen > 0 && dm_segs != eseg) {
979d720e6d5SJustin T. Gibbs 		crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp);
9804873663cSMatt Jacob 		*iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN);
981d720e6d5SJustin T. Gibbs 		if (*iptrp == optr) {
9824873663cSMatt Jacob #if	0
9834873663cSMatt Jacob 			printf("%s: Request Queue Overflow++\n", isp->isp_name);
9844873663cSMatt Jacob #endif
9854873663cSMatt Jacob 			mp->error = MUSHERR_NOQENTRIES;
986d720e6d5SJustin T. Gibbs 			return;
987d720e6d5SJustin T. Gibbs 		}
988d720e6d5SJustin T. Gibbs 		rq->req_header.rqs_entry_count++;
989d720e6d5SJustin T. Gibbs 		bzero((void *)crq, sizeof (*crq));
990d720e6d5SJustin T. Gibbs 		crq->req_header.rqs_entry_count = 1;
991d720e6d5SJustin T. Gibbs 		crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
992d720e6d5SJustin T. Gibbs 
993d720e6d5SJustin T. Gibbs 		seglim = 0;
994d720e6d5SJustin T. Gibbs 		while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) {
995d720e6d5SJustin T. Gibbs 			crq->req_dataseg[seglim].ds_base =
996d720e6d5SJustin T. Gibbs 			    dm_segs->ds_addr;
997d720e6d5SJustin T. Gibbs 			crq->req_dataseg[seglim].ds_count =
998d720e6d5SJustin T. Gibbs 			    dm_segs->ds_len;
999d720e6d5SJustin T. Gibbs #if	0
1000d720e6d5SJustin T. Gibbs 			printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n",
1001d720e6d5SJustin T. Gibbs 			    isp->isp_name, rq->req_header.rqs_entry_count-1,
1002d720e6d5SJustin T. Gibbs 			    seglim, crq->req_dataseg[seglim].ds_count,
1003d720e6d5SJustin T. Gibbs 			    crq->req_dataseg[seglim].ds_base);
1004d720e6d5SJustin T. Gibbs #endif
1005d720e6d5SJustin T. Gibbs 			rq->req_seg_count++;
1006d720e6d5SJustin T. Gibbs 			dm_segs++;
1007d720e6d5SJustin T. Gibbs 			seglim++;
1008d720e6d5SJustin T. Gibbs 			datalen -= dm_segs->ds_len;
1009d720e6d5SJustin T. Gibbs 		}
1010d720e6d5SJustin T. Gibbs 	}
1011d720e6d5SJustin T. Gibbs }
1012d720e6d5SJustin T. Gibbs 
1013d720e6d5SJustin T. Gibbs static int
101417e318c6SMatt Jacob isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb, ispreq_t *rq,
101517e318c6SMatt Jacob 	u_int8_t *iptrp, u_int8_t optr)
1016d720e6d5SJustin T. Gibbs {
1017d720e6d5SJustin T. Gibbs 	struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
1018d720e6d5SJustin T. Gibbs 	struct ccb_hdr *ccb_h;
1019d720e6d5SJustin T. Gibbs 	struct ccb_scsiio *csio;
1020d720e6d5SJustin T. Gibbs 	bus_dmamap_t *dp;
1021d720e6d5SJustin T. Gibbs 	mush_t mush, *mp;
1022d720e6d5SJustin T. Gibbs 
1023d720e6d5SJustin T. Gibbs 	csio = (struct ccb_scsiio *) ccb;
1024d720e6d5SJustin T. Gibbs 	ccb_h = &csio->ccb_h;
1025d720e6d5SJustin T. Gibbs 
1026d720e6d5SJustin T. Gibbs 	if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) {
1027d720e6d5SJustin T. Gibbs 		rq->req_seg_count = 1;
10284873663cSMatt Jacob 		return (CMD_QUEUED);
1029d720e6d5SJustin T. Gibbs 	}
1030d720e6d5SJustin T. Gibbs 	dp = &pci->dmaps[rq->req_handle - 1];
1031d720e6d5SJustin T. Gibbs 
1032d720e6d5SJustin T. Gibbs 	/*
1033d720e6d5SJustin T. Gibbs 	 * Do a virtual grapevine step to collect info for
10344873663cSMatt Jacob 	 * the callback dma allocation that we have to use...
1035d720e6d5SJustin T. Gibbs 	 */
1036d720e6d5SJustin T. Gibbs 	mp = &mush;
1037d720e6d5SJustin T. Gibbs 	mp->isp = isp;
1038d720e6d5SJustin T. Gibbs 	mp->ccb = ccb;
1039d720e6d5SJustin T. Gibbs 	mp->rq = rq;
1040d720e6d5SJustin T. Gibbs 	mp->iptrp = iptrp;
1041d720e6d5SJustin T. Gibbs 	mp->optr = optr;
1042d720e6d5SJustin T. Gibbs 	mp->error = 0;
1043d720e6d5SJustin T. Gibbs 
1044d720e6d5SJustin T. Gibbs 	if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) {
1045d720e6d5SJustin T. Gibbs 		if ((ccb_h->flags & CAM_DATA_PHYS) == 0) {
10464873663cSMatt Jacob 			int error, s;
10474873663cSMatt Jacob 
1048d720e6d5SJustin T. Gibbs 			s = splsoftvm();
1049d720e6d5SJustin T. Gibbs 			error = bus_dmamap_load(pci->parent_dmat, *dp,
1050d720e6d5SJustin T. Gibbs 			    csio->data_ptr, csio->dxfer_len, dma2, mp, 0);
1051d720e6d5SJustin T. Gibbs 			if (error == EINPROGRESS) {
1052d720e6d5SJustin T. Gibbs 				bus_dmamap_unload(pci->parent_dmat, *dp);
1053d720e6d5SJustin T. Gibbs 				mp->error = EINVAL;
10544873663cSMatt Jacob 				printf("%s: deferred dma allocation not "
10554873663cSMatt Jacob 				    "supported\n", isp->isp_name);
1056d720e6d5SJustin T. Gibbs 			} else if (error && mp->error == 0) {
1057d720e6d5SJustin T. Gibbs 				mp->error = error;
1058d720e6d5SJustin T. Gibbs 			}
10594873663cSMatt Jacob 			splx(s);
1060d720e6d5SJustin T. Gibbs 		} else {
1061d720e6d5SJustin T. Gibbs 			/* Pointer to physical buffer */
1062d720e6d5SJustin T. Gibbs 			struct bus_dma_segment seg;
1063d720e6d5SJustin T. Gibbs 			seg.ds_addr = (bus_addr_t)csio->data_ptr;
1064d720e6d5SJustin T. Gibbs 			seg.ds_len = csio->dxfer_len;
1065d720e6d5SJustin T. Gibbs 			dma2(mp, &seg, 1, 0);
1066d720e6d5SJustin T. Gibbs 		}
1067d720e6d5SJustin T. Gibbs 	} else {
1068d720e6d5SJustin T. Gibbs 		struct bus_dma_segment *segs;
1069d720e6d5SJustin T. Gibbs 
1070d720e6d5SJustin T. Gibbs 		if ((ccb_h->flags & CAM_DATA_PHYS) != 0) {
1071d720e6d5SJustin T. Gibbs 			printf("%s: Physical segment pointers unsupported",
1072d720e6d5SJustin T. Gibbs 				isp->isp_name);
1073d720e6d5SJustin T. Gibbs 			mp->error = EINVAL;
1074d720e6d5SJustin T. Gibbs 		} else if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) {
1075d720e6d5SJustin T. Gibbs 			printf("%s: Virtual segment addresses unsupported",
1076d720e6d5SJustin T. Gibbs 				isp->isp_name);
1077d720e6d5SJustin T. Gibbs 			mp->error = EINVAL;
1078d720e6d5SJustin T. Gibbs 		} else {
1079d720e6d5SJustin T. Gibbs 			/* Just use the segments provided */
1080d720e6d5SJustin T. Gibbs 			segs = (struct bus_dma_segment *) csio->data_ptr;
1081d720e6d5SJustin T. Gibbs 			dma2(mp, segs, csio->sglist_cnt, 0);
1082d720e6d5SJustin T. Gibbs 		}
1083d720e6d5SJustin T. Gibbs 	}
1084d720e6d5SJustin T. Gibbs 	if (mp->error) {
10854873663cSMatt Jacob 		int retval = CMD_COMPLETE;
10864873663cSMatt Jacob 		if (mp->error == MUSHERR_NOQENTRIES) {
10874873663cSMatt Jacob 			retval = CMD_EAGAIN;
10884873663cSMatt Jacob 			ccb_h->status = CAM_UNREC_HBA_ERROR;
10894873663cSMatt Jacob 		} else if (mp->error == EFBIG) {
1090d720e6d5SJustin T. Gibbs 			ccb_h->status = CAM_REQ_TOO_BIG;
1091d720e6d5SJustin T. Gibbs 		} else if (mp->error == EINVAL) {
1092d720e6d5SJustin T. Gibbs 			ccb_h->status = CAM_REQ_INVALID;
1093d720e6d5SJustin T. Gibbs 		} else {
1094d720e6d5SJustin T. Gibbs 			ccb_h->status = CAM_UNREC_HBA_ERROR;
1095d720e6d5SJustin T. Gibbs 		}
10964873663cSMatt Jacob 		return (retval);
10974873663cSMatt Jacob 	} else {
10984873663cSMatt Jacob 		return (CMD_QUEUED);
1099d720e6d5SJustin T. Gibbs 	}
1100d720e6d5SJustin T. Gibbs }
1101d720e6d5SJustin T. Gibbs 
1102d720e6d5SJustin T. Gibbs static void
110317e318c6SMatt Jacob isp_pci_dmateardown(struct ispsoftc *isp, ISP_SCSI_XFER_T *ccb,
110417e318c6SMatt Jacob 	u_int32_t handle)
1105d720e6d5SJustin T. Gibbs {
1106d720e6d5SJustin T. Gibbs 	struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
1107d720e6d5SJustin T. Gibbs 	bus_dmamap_t *dp = &pci->dmaps[handle];
1108d720e6d5SJustin T. Gibbs 
1109d720e6d5SJustin T. Gibbs 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1110d720e6d5SJustin T. Gibbs 		bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD);
1111d720e6d5SJustin T. Gibbs 	} else {
1112d720e6d5SJustin T. Gibbs 		bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE);
1113d720e6d5SJustin T. Gibbs 	}
1114d720e6d5SJustin T. Gibbs 	bus_dmamap_unload(pci->parent_dmat, *dp);
1115d720e6d5SJustin T. Gibbs }
1116d720e6d5SJustin T. Gibbs 
111765adb54cSMatt Jacob 
111865adb54cSMatt Jacob static void
111917e318c6SMatt Jacob isp_pci_reset1(struct ispsoftc *isp)
112065adb54cSMatt Jacob {
112165adb54cSMatt Jacob 	/* Make sure the BIOS is disabled */
112265adb54cSMatt Jacob 	isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
112365adb54cSMatt Jacob }
112465adb54cSMatt Jacob 
112565adb54cSMatt Jacob static void
112617e318c6SMatt Jacob isp_pci_dumpregs(struct ispsoftc *isp)
112765adb54cSMatt Jacob {
112865adb54cSMatt Jacob 	struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
11299bffbcd4SBruce Evans 	printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name,
1130d951bbcaSMatt Jacob 	    pci_conf_read(pci->pci_id, PCIR_COMMAND));
113165adb54cSMatt Jacob }
1132