xref: /freebsd/sys/dev/isp/isp_pci.c (revision 2aebedc3ad9e722b272254e6dd3a12e399595e57)
1 /* $FreeBSD$ */
2 /* isp_pci.c 1.18 */
3 /*
4  * PCI specific probe and attach routines for Qlogic ISP SCSI adapters.
5  * FreeBSD Version.
6  *
7  *---------------------------------------
8  * Copyright (c) 1997, 1998 by Matthew Jacob
9  * NASA/Ames Research Center
10  * All rights reserved.
11  *---------------------------------------
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice immediately at the beginning of the file, without modification,
18  *    this list of conditions, and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. The name of the author may not be used to endorse or promote products
23  *    derived from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
29  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 #include <dev/isp/isp_freebsd.h>
38 #include <dev/isp/asm_pci.h>
39 #include <sys/malloc.h>
40 #include <vm/vm.h>
41 #include <vm/pmap.h>
42 #include <vm/vm_extern.h>
43 
44 
45 #include <pci/pcireg.h>
46 #include <pci/pcivar.h>
47 
48 #if	__FreeBSD_version >= 300004
49 #include <machine/bus_memio.h>
50 #include <machine/bus_pio.h>
51 #include <machine/bus.h>
52 #endif
53 
54 static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int));
55 static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t));
56 static int isp_pci_mbxdma __P((struct ispsoftc *));
57 static int isp_pci_dmasetup __P((struct ispsoftc *, ISP_SCSI_XFER_T *,
58 	ispreq_t *, u_int8_t *, u_int8_t));
59 #if	__FreeBSD_version >= 300004
60 static void
61 isp_pci_dmateardown __P((struct ispsoftc *, ISP_SCSI_XFER_T *, u_int32_t));
62 #else
63 #define	isp_pci_dmateardown	NULL
64 #endif
65 
66 static void isp_pci_reset1 __P((struct ispsoftc *));
67 static void isp_pci_dumpregs __P((struct ispsoftc *));
68 
69 static struct ispmdvec mdvec = {
70 	isp_pci_rd_reg,
71 	isp_pci_wr_reg,
72 	isp_pci_mbxdma,
73 	isp_pci_dmasetup,
74 	isp_pci_dmateardown,
75 	NULL,
76 	isp_pci_reset1,
77 	isp_pci_dumpregs,
78 	ISP_RISC_CODE,
79 	ISP_CODE_LENGTH,
80 	ISP_CODE_ORG,
81 	ISP_CODE_VERSION,
82 	BIU_BURST_ENABLE,
83 	0
84 };
85 
86 static struct ispmdvec mdvec_2100 = {
87 	isp_pci_rd_reg,
88 	isp_pci_wr_reg,
89 	isp_pci_mbxdma,
90 	isp_pci_dmasetup,
91 	isp_pci_dmateardown,
92 	NULL,
93 	isp_pci_reset1,
94 	isp_pci_dumpregs,
95 	ISP2100_RISC_CODE,
96 	ISP2100_CODE_LENGTH,
97 	ISP2100_CODE_ORG,
98 	ISP2100_CODE_VERSION,
99 	BIU_BURST_ENABLE,
100 	0
101 };
102 
103 #ifndef	PCIM_CMD_INVEN
104 #define	PCIM_CMD_INVEN			0x10
105 #endif
106 #ifndef	PCIM_CMD_BUSMASTEREN
107 #define	PCIM_CMD_BUSMASTEREN		0x0004
108 #endif
109 
110 #ifndef	PCI_VENDOR_QLOGIC
111 #define	PCI_VENDOR_QLOGIC		0x1077
112 #endif
113 
114 #ifndef	PCI_PRODUCT_QLOGIC_ISP1020
115 #define	PCI_PRODUCT_QLOGIC_ISP1020	0x1020
116 #endif
117 
118 #define	PCI_QLOGIC_ISP	\
119 	((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC)
120 
121 #ifndef	PCI_PRODUCT_QLOGIC_ISP2100
122 #define	PCI_PRODUCT_QLOGIC_ISP2100	0x2100
123 #endif
124 
125 #define	PCI_QLOGIC_ISP2100	\
126 	((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC)
127 
128 #define IO_MAP_REG	0x10
129 #define MEM_MAP_REG	0x14
130 
131 
132 static const char *isp_pci_probe __P((pcici_t tag, pcidi_t type));
133 static void isp_pci_attach __P((pcici_t config_d, int unit));
134 
135 /* This distinguishing define is not right, but it does work */
136 
137 #if	__FreeBSD_version < 300004
138 #define	IO_SPACE_MAPPING	0
139 #define	MEM_SPACE_MAPPING	1
140 typedef int bus_space_tag_t;
141 typedef u_long bus_space_handle_t;
142 #ifdef __alpha__
143 #define	bus_space_read_2(st, sh, offset)	\
144 	(st == IO_SPACE_MAPPING)? \
145 		inw((pci_port_t)sh + offset) : readw((pci_port_t)sh + offset)
146 #define	bus_space_write_2(st, sh, offset, val)	\
147 	if (st == IO_SPACE_MAPPING) outw((pci_port_t)sh + offset, val); else \
148                 writew((pci_port_t)sh + offset, val)
149 #else
150 #define	bus_space_read_2(st, sh, offset)	\
151 	(st == IO_SPACE_MAPPING)? \
152 		inw((pci_port_t)sh + offset) : *((u_int16_t *)(uintptr_t)sh)
153 #define	bus_space_write_2(st, sh, offset, val)	\
154 	if (st == IO_SPACE_MAPPING) outw((pci_port_t)sh + offset, val); else \
155 		*((u_int16_t *)(uintptr_t)sh) = val
156 #endif
157 #else
158 #ifdef __alpha__
159 #define IO_SPACE_MAPPING	ALPHA_BUS_SPACE_IO
160 #define MEM_SPACE_MAPPING	ALPHA_BUS_SPACE_MEM
161 #else
162 #define IO_SPACE_MAPPING	I386_BUS_SPACE_IO
163 #define MEM_SPACE_MAPPING	I386_BUS_SPACE_MEM
164 #endif
165 #endif
166 
167 struct isp_pcisoftc {
168 	struct ispsoftc			pci_isp;
169         pcici_t				pci_id;
170 	bus_space_tag_t			pci_st;
171 	bus_space_handle_t		pci_sh;
172 #if	__FreeBSD_version >= 300004
173 	bus_dma_tag_t			parent_dmat;
174 	bus_dma_tag_t			cntrol_dmat;
175 	bus_dmamap_t			cntrol_dmap;
176 	bus_dmamap_t			dmaps[MAXISPREQUEST];
177 #endif
178 	union {
179 		sdparam	_x;
180 		struct {
181 			fcparam _a;
182 			char _b[ISP2100_SCRLEN];
183 		} _y;
184 	} _z;
185 };
186 
187 static u_long ispunit;
188 
189 struct pci_device isp_pci_driver = {
190 	"isp",
191 	isp_pci_probe,
192 	isp_pci_attach,
193 	&ispunit,
194 	NULL
195 };
196 DATA_SET (pcidevice_set, isp_pci_driver);
197 
198 
199 static const char *
200 isp_pci_probe(tag, type)
201 	pcici_t tag;
202 	pcidi_t type;
203 {
204 	static int oneshot = 1;
205 	char *x;
206 
207         switch (type) {
208 	case PCI_QLOGIC_ISP:
209 		x = "Qlogic ISP 10X0 PCI SCSI Adapter";
210 		break;
211 	case PCI_QLOGIC_ISP2100:
212 		x = "Qlogic ISP 2100 PCI FC-AL Adapter";
213 		break;
214 	default:
215 		return (NULL);
216 	}
217 	if (oneshot) {
218 		oneshot = 0;
219 		printf("%s Version %d.%d, Core Version %d.%d\n", PVS,
220 		    ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
221 		    ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
222 	}
223 	return (x);
224 }
225 
226 
227 static void
228 isp_pci_attach(config_id, unit)
229         pcici_t config_id;
230         int unit;
231 {
232 	int mapped;
233 	pci_port_t io_port;
234 	u_int32_t data;
235 	struct isp_pcisoftc *pcs;
236 	struct ispsoftc *isp;
237 	vm_offset_t vaddr, paddr;
238 	ISP_LOCKVAL_DECL;
239 
240 
241 	pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT);
242 	if (pcs == NULL) {
243 		printf("isp%d: cannot allocate softc\n", unit);
244 		return;
245 	}
246 	bzero(pcs, sizeof (struct isp_pcisoftc));
247 
248 	vaddr = paddr = NULL;
249 	mapped = 0;
250 	data = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
251 	if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) {
252 		if (pci_map_mem(config_id, MEM_MAP_REG, &vaddr, &paddr)) {
253 			pcs->pci_st = MEM_SPACE_MAPPING;
254 			pcs->pci_sh = vaddr;
255 			mapped++;
256 		}
257 	}
258 	if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) {
259 		if (pci_map_port(config_id, PCI_MAP_REG_START, &io_port)) {
260 			pcs->pci_st = IO_SPACE_MAPPING;
261 			pcs->pci_sh = io_port;
262 			mapped++;
263 		}
264 	}
265 	if (mapped == 0) {
266 		printf("isp%d: unable to map any ports!\n", unit);
267 		free(pcs, M_DEVBUF);
268 		return;
269 	}
270 	printf("isp%d: using %s space register mapping\n", unit,
271 	    pcs->pci_st == IO_SPACE_MAPPING? "I/O" : "Memory");
272 
273 	isp = &pcs->pci_isp;
274 #if	__FreeBSD_version >= 300006
275 	(void) snprintf(isp->isp_name, sizeof(isp->isp_name), "isp%d", unit);
276 #else
277 	(void) sprintf(isp->isp_name, "isp%d", unit);
278 #endif
279 	isp->isp_osinfo.unit = unit;
280 
281 	data = pci_conf_read(config_id, PCI_ID_REG);
282 	if (data == PCI_QLOGIC_ISP) {
283 		isp->isp_mdvec = &mdvec;
284 		isp->isp_type = ISP_HA_SCSI_UNKNOWN;
285 		isp->isp_param = &pcs->_z._x;
286 	} else if (data == PCI_QLOGIC_ISP2100) {
287 		isp->isp_mdvec = &mdvec_2100;
288 		isp->isp_type = ISP_HA_FC_2100;
289 		isp->isp_param = &pcs->_z._y._a;
290 
291 		ISP_LOCK(isp);
292 		data = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
293 		data |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_INVEN;
294 		pci_conf_write(config_id, PCI_COMMAND_STATUS_REG, data);
295 
296 		/*
297 		 * Wierd- we need to clear the lsb in offset 0x30 to take the
298 		 * chip out of reset state.
299 		 */
300 		data = pci_conf_read(config_id, 0x30);
301 		data &= ~1;
302 		pci_conf_write(config_id, 0x30, data);
303 		ISP_UNLOCK(isp);
304 	} else {
305 		printf("%s: unknown dev (%x)- punting\n", isp->isp_name, data);
306 		free(pcs, M_DEVBUF);
307 		return;
308 	}
309 
310 #if	__FreeBSD_version >= 300004
311 	if (bus_dma_tag_create(NULL, 0, 0, BUS_SPACE_MAXADDR_32BIT,
312 	    BUS_SPACE_MAXADDR, NULL, NULL, 1<<24,
313 	    255, 1<<24, 0, &pcs->parent_dmat) != 0) {
314 		printf("%s: could not create master dma tag\n", isp->isp_name);
315 		free(pcs, M_DEVBUF);
316 		return;
317 	}
318 #endif
319 	if (pci_map_int(config_id, (void (*)(void *))isp_intr,
320 	    (void *)isp, &IMASK) == 0) {
321 		printf("%s: could not map interrupt\n", isp->isp_name);
322 		free(pcs, M_DEVBUF);
323 		return;
324 	}
325 
326 	pcs->pci_id = config_id;
327 	ISP_LOCK(isp);
328 	isp_reset(isp);
329 	if (isp->isp_state != ISP_RESETSTATE) {
330 		ISP_UNLOCK(isp);
331 		free(pcs, M_DEVBUF);
332 		return;
333 	}
334 	isp_init(isp);
335 	if (isp->isp_state != ISP_INITSTATE) {
336 		isp_uninit(isp);
337 		ISP_UNLOCK(isp);
338 		free(pcs, M_DEVBUF);
339 		return;
340 	}
341 	isp_attach(isp);
342 	if (isp->isp_state != ISP_RUNSTATE) {
343 		isp_uninit(isp);
344 		free(pcs, M_DEVBUF);
345 	}
346 	ISP_UNLOCK(isp);
347 #ifdef __alpha__
348 	alpha_register_pci_scsi(config_id->bus, config_id->slot, isp->isp_sim);
349 #endif
350 }
351 
352 #define  PCI_BIU_REGS_OFF		BIU_REGS_OFF
353 
354 static u_int16_t
355 isp_pci_rd_reg(isp, regoff)
356 	struct ispsoftc *isp;
357 	int regoff;
358 {
359 	u_int16_t rv;
360 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
361 	int offset, oldsxp = 0;
362 
363 	if ((regoff & BIU_BLOCK) != 0) {
364 		offset = PCI_BIU_REGS_OFF;
365 	} else if ((regoff & MBOX_BLOCK) != 0) {
366 		if (isp->isp_type & ISP_HA_SCSI)
367 			offset = PCI_MBOX_REGS_OFF;
368 		else
369 			offset = PCI_MBOX_REGS2100_OFF;
370 	} else if ((regoff & SXP_BLOCK) != 0) {
371 		offset = PCI_SXP_REGS_OFF;
372 		/*
373 		 * We will assume that someone has paused the RISC processor.
374 		 */
375 		oldsxp = isp_pci_rd_reg(isp, BIU_CONF1);
376 		isp_pci_wr_reg(isp, BIU_CONF1, oldsxp & ~BIU_PCI_CONF1_SXP);
377 	} else {
378 		offset = PCI_RISC_REGS_OFF;
379 	}
380 	regoff &= 0xff;
381 	offset += regoff;
382 	rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset);
383 	if ((regoff & SXP_BLOCK) != 0) {
384 		isp_pci_wr_reg(isp, BIU_CONF1, oldsxp);
385 	}
386 	return (rv);
387 }
388 
389 static void
390 isp_pci_wr_reg(isp, regoff, val)
391 	struct ispsoftc *isp;
392 	int regoff;
393 	u_int16_t val;
394 {
395 	struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
396 	int offset, oldsxp = 0;
397 	if ((regoff & BIU_BLOCK) != 0) {
398 		offset = PCI_BIU_REGS_OFF;
399 	} else if ((regoff & MBOX_BLOCK) != 0) {
400 		if (isp->isp_type & ISP_HA_SCSI)
401 			offset = PCI_MBOX_REGS_OFF;
402 		else
403 			offset = PCI_MBOX_REGS2100_OFF;
404 	} else if ((regoff & SXP_BLOCK) != 0) {
405 		offset = PCI_SXP_REGS_OFF;
406 		/*
407 		 * We will assume that someone has paused the RISC processor.
408 		 */
409 		oldsxp = isp_pci_rd_reg(isp, BIU_CONF1);
410 		isp_pci_wr_reg(isp, BIU_CONF1, oldsxp & ~BIU_PCI_CONF1_SXP);
411 	} else {
412 		offset = PCI_RISC_REGS_OFF;
413 	}
414 	regoff &= 0xff;
415 	offset += regoff;
416 	bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val);
417 	if ((regoff & SXP_BLOCK) != 0) {
418 		isp_pci_wr_reg(isp, BIU_CONF1, oldsxp);
419 	}
420 }
421 
422 #if	__FreeBSD_version >= 300004
423 static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int));
424 static void isp_map_result __P((void *, bus_dma_segment_t *, int, int));
425 static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int));
426 
427 static void
428 isp_map_rquest(arg, segs, nseg, error)
429 	void *arg;
430 	bus_dma_segment_t *segs;
431 	int nseg;
432 	int error;
433 {
434 	struct ispsoftc *isp = (struct ispsoftc *) arg;
435 	isp->isp_rquest_dma = segs->ds_addr;
436 }
437 
438 static void
439 isp_map_result(arg, segs, nseg, error)
440 	void *arg;
441 	bus_dma_segment_t *segs;
442 	int nseg;
443 	int error;
444 {
445 	struct ispsoftc *isp = (struct ispsoftc *) arg;
446 	isp->isp_result_dma = segs->ds_addr;
447 }
448 
449 static void
450 isp_map_fcscrt(arg, segs, nseg, error)
451 	void *arg;
452 	bus_dma_segment_t *segs;
453 	int nseg;
454 	int error;
455 {
456 	struct ispsoftc *isp = (struct ispsoftc *) arg;
457 	fcparam *fcp = isp->isp_param;
458 	fcp->isp_scdma = segs->ds_addr;
459 }
460 
461 static int
462 isp_pci_mbxdma(isp)
463 	struct ispsoftc *isp;
464 {
465 	struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
466 	caddr_t base;
467 	u_int32_t len;
468 	int i, error;
469 
470 	/*
471 	 * Allocate and map the request, result queues, plus FC scratch area.
472 	 */
473 	len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN);
474 	len += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN);
475 	if (isp->isp_type & ISP_HA_FC) {
476 		len += ISP2100_SCRLEN;
477 	}
478 	if (bus_dma_tag_create(pci->parent_dmat, 0, 0, BUS_SPACE_MAXADDR,
479 	    BUS_SPACE_MAXADDR, NULL, NULL, len, 1, BUS_SPACE_MAXSIZE_32BIT,
480 	    0, &pci->cntrol_dmat) != 0) {
481 		printf("%s: cannot create a dma tag for control spaces\n",
482 		    isp->isp_name);
483 		return (1);
484 	}
485 	if (bus_dmamem_alloc(pci->cntrol_dmat, (void **)&base,
486 	    BUS_DMA_NOWAIT, &pci->cntrol_dmap) != 0) {
487 		printf("%s: cannot allocate %d bytes of CCB memory\n",
488 		    isp->isp_name, len);
489 		return (1);
490 	}
491 
492 	isp->isp_rquest = base;
493 	bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_rquest,
494 	    ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN), isp_map_rquest, pci, 0);
495 
496 	isp->isp_result = base + ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN);
497 	bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap, isp->isp_result,
498 	    ISP_QUEUE_SIZE(RESULT_QUEUE_LEN), isp_map_result, pci, 0);
499 
500 	if (isp->isp_type & ISP_HA_FC) {
501 		fcparam *fcp = (fcparam *) isp->isp_param;
502 		fcp->isp_scratch = isp->isp_result +
503 		    ISP_QUEUE_SIZE(RESULT_QUEUE_LEN);
504 		bus_dmamap_load(pci->cntrol_dmat, pci->cntrol_dmap,
505 		    fcp->isp_scratch, ISP2100_SCRLEN, isp_map_fcscrt, pci, 0);
506 	}
507 
508 	/*
509 	 * Use this opportunity to initialize/create data DMA maps.
510 	 */
511 	for (i = 0; i < MAXISPREQUEST; i++) {
512 		error = bus_dmamap_create(pci->parent_dmat, 0, &pci->dmaps[i]);
513 		if (error) {
514 			printf("%s: error %d creating mailbox DMA maps\n",
515 			    isp->isp_name, error);
516 			return (1);
517 		}
518 	}
519 	return (0);
520 }
521 
522 static void dma2 __P((void *, bus_dma_segment_t *, int, int));
523 typedef struct {
524 	struct ispsoftc *isp;
525 	ISP_SCSI_XFER_T *ccb;
526 	ispreq_t *rq;
527 	u_int8_t *iptrp;
528 	u_int8_t optr;
529 	u_int error;
530 } mush_t;
531 
532 #define	MUSHERR_NOQENTRIES	-2
533 
534 static void
535 dma2(arg, dm_segs, nseg, error)
536 	void *arg;
537 	bus_dma_segment_t *dm_segs;
538 	int nseg;
539 	int error;
540 {
541 	mush_t *mp;
542 	ISP_SCSI_XFER_T *ccb;
543 	struct ispsoftc *isp;
544 	struct isp_pcisoftc *pci;
545 	bus_dmamap_t *dp;
546 	bus_dma_segment_t *eseg;
547 	ispreq_t *rq;
548 	u_int8_t *iptrp;
549 	u_int8_t optr;
550 	ispcontreq_t *crq;
551 	int drq, seglim, datalen;
552 
553 	mp = (mush_t *) arg;
554 	if (error) {
555 		mp->error = error;
556 		return;
557 	}
558 
559 	isp = mp->isp;
560 	if (nseg < 1) {
561 		printf("%s: zero or negative segment count\n", isp->isp_name);
562 		mp->error = EFAULT;
563 		return;
564 	}
565 	ccb = mp->ccb;
566 	rq = mp->rq;
567 	iptrp = mp->iptrp;
568 	optr = mp->optr;
569 
570 	pci = (struct isp_pcisoftc *)isp;
571 	dp = &pci->dmaps[rq->req_handle - 1];
572 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
573 		bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREREAD);
574 		drq = REQFLAG_DATA_IN;
575 	} else {
576 		bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_PREWRITE);
577 		drq = REQFLAG_DATA_OUT;
578 	}
579 
580 	datalen = XS_XFRLEN(ccb);
581 	if (isp->isp_type & ISP_HA_FC) {
582 		seglim = ISP_RQDSEG_T2;
583 		((ispreqt2_t *)rq)->req_totalcnt = datalen;
584 		((ispreqt2_t *)rq)->req_flags |= drq;
585 	} else {
586 		seglim = ISP_RQDSEG;
587 		rq->req_flags |= drq;
588 	}
589 
590 	eseg = dm_segs + nseg;
591 
592 	while (datalen != 0 && rq->req_seg_count < seglim && dm_segs != eseg) {
593 		if (isp->isp_type & ISP_HA_FC) {
594 			ispreqt2_t *rq2 = (ispreqt2_t *)rq;
595 			rq2->req_dataseg[rq2->req_seg_count].ds_base =
596 			    dm_segs->ds_addr;
597 			rq2->req_dataseg[rq2->req_seg_count].ds_count =
598 			    dm_segs->ds_len;
599 		} else {
600 			rq->req_dataseg[rq->req_seg_count].ds_base =
601 				dm_segs->ds_addr;
602 			rq->req_dataseg[rq->req_seg_count].ds_count =
603 				dm_segs->ds_len;
604 		}
605 		datalen -= dm_segs->ds_len;
606 #if	0
607 		if (isp->isp_type & ISP_HA_FC) {
608 			ispreqt2_t *rq2 = (ispreqt2_t *)rq;
609 			printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n",
610 			    isp->isp_name, rq->req_seg_count,
611 			    rq2->req_dataseg[rq2->req_seg_count].ds_count,
612 			    rq2->req_dataseg[rq2->req_seg_count].ds_base);
613 		} else {
614 			printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n",
615 			    isp->isp_name, rq->req_seg_count,
616 			    rq->req_dataseg[rq->req_seg_count].ds_count,
617 			    rq->req_dataseg[rq->req_seg_count].ds_base);
618 		}
619 #endif
620 		rq->req_seg_count++;
621 		dm_segs++;
622 	}
623 
624 	while (datalen > 0 && dm_segs != eseg) {
625 		crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp);
626 		*iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN);
627 		if (*iptrp == optr) {
628 #if	0
629 			printf("%s: Request Queue Overflow++\n", isp->isp_name);
630 #endif
631 			mp->error = MUSHERR_NOQENTRIES;
632 			return;
633 		}
634 		rq->req_header.rqs_entry_count++;
635 		bzero((void *)crq, sizeof (*crq));
636 		crq->req_header.rqs_entry_count = 1;
637 		crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
638 
639 		seglim = 0;
640 		while (datalen > 0 && seglim < ISP_CDSEG && dm_segs != eseg) {
641 			crq->req_dataseg[seglim].ds_base =
642 			    dm_segs->ds_addr;
643 			crq->req_dataseg[seglim].ds_count =
644 			    dm_segs->ds_len;
645 #if	0
646 			printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n",
647 			    isp->isp_name, rq->req_header.rqs_entry_count-1,
648 			    seglim, crq->req_dataseg[seglim].ds_count,
649 			    crq->req_dataseg[seglim].ds_base);
650 #endif
651 			rq->req_seg_count++;
652 			dm_segs++;
653 			seglim++;
654 			datalen -= dm_segs->ds_len;
655 		}
656 	}
657 }
658 
659 static int
660 isp_pci_dmasetup(isp, ccb, rq, iptrp, optr)
661 	struct ispsoftc *isp;
662 	ISP_SCSI_XFER_T *ccb;
663 	ispreq_t *rq;
664 	u_int8_t *iptrp;
665 	u_int8_t optr;
666 {
667 	struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
668 	struct ccb_hdr *ccb_h;
669 	struct ccb_scsiio *csio;
670 	bus_dmamap_t *dp;
671 	mush_t mush, *mp;
672 
673 	csio = (struct ccb_scsiio *) ccb;
674 	ccb_h = &csio->ccb_h;
675 
676 	if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) {
677 		rq->req_seg_count = 1;
678 		return (CMD_QUEUED);
679 	}
680 	dp = &pci->dmaps[rq->req_handle - 1];
681 
682 	/*
683 	 * Do a virtual grapevine step to collect info for
684 	 * the callback dma allocation that we have to use...
685 	 */
686 	mp = &mush;
687 	mp->isp = isp;
688 	mp->ccb = ccb;
689 	mp->rq = rq;
690 	mp->iptrp = iptrp;
691 	mp->optr = optr;
692 	mp->error = 0;
693 
694 	if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) {
695 		if ((ccb_h->flags & CAM_DATA_PHYS) == 0) {
696 			int error, s;
697 
698 			s = splsoftvm();
699 			error = bus_dmamap_load(pci->parent_dmat, *dp,
700 			    csio->data_ptr, csio->dxfer_len, dma2, mp, 0);
701 			if (error == EINPROGRESS) {
702 				bus_dmamap_unload(pci->parent_dmat, *dp);
703 				mp->error = EINVAL;
704 				printf("%s: deferred dma allocation not "
705 				    "supported\n", isp->isp_name);
706 			} else if (error && mp->error == 0) {
707 				mp->error = error;
708 			}
709 			splx(s);
710 		} else {
711 			/* Pointer to physical buffer */
712 			struct bus_dma_segment seg;
713 			seg.ds_addr = (bus_addr_t)csio->data_ptr;
714 			seg.ds_len = csio->dxfer_len;
715 			dma2(mp, &seg, 1, 0);
716 		}
717 	} else {
718 		struct bus_dma_segment *segs;
719 
720 		if ((ccb_h->flags & CAM_DATA_PHYS) != 0) {
721 			printf("%s: Physical segment pointers unsupported",
722 				isp->isp_name);
723 			mp->error = EINVAL;
724 		} else if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) {
725 			printf("%s: Virtual segment addresses unsupported",
726 				isp->isp_name);
727 			mp->error = EINVAL;
728 		} else {
729 			/* Just use the segments provided */
730 			segs = (struct bus_dma_segment *) csio->data_ptr;
731 			dma2(mp, segs, csio->sglist_cnt, 0);
732 		}
733 	}
734 	if (mp->error) {
735 		int retval = CMD_COMPLETE;
736 		if (mp->error == MUSHERR_NOQENTRIES) {
737 			retval = CMD_EAGAIN;
738 			ccb_h->status = CAM_UNREC_HBA_ERROR;
739 		} else if (mp->error == EFBIG) {
740 			ccb_h->status = CAM_REQ_TOO_BIG;
741 		} else if (mp->error == EINVAL) {
742 			ccb_h->status = CAM_REQ_INVALID;
743 		} else {
744 			ccb_h->status = CAM_UNREC_HBA_ERROR;
745 		}
746 		return (retval);
747 	} else {
748 		return (CMD_QUEUED);
749 	}
750 }
751 
752 static void
753 isp_pci_dmateardown(isp, ccb, handle)
754 	struct ispsoftc *isp;
755 	ISP_SCSI_XFER_T *ccb;
756 	u_int32_t handle;
757 {
758 	struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
759 	bus_dmamap_t *dp = &pci->dmaps[handle];
760 
761 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
762 		bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTREAD);
763 	} else {
764 		bus_dmamap_sync(pci->parent_dmat, *dp, BUS_DMASYNC_POSTWRITE);
765 	}
766 	bus_dmamap_unload(pci->parent_dmat, *dp);
767 }
768 
769 #else	/* __FreeBSD_version >= 300004 */
770 
771 
772 static int
773 isp_pci_mbxdma(isp)
774 	struct ispsoftc *isp;
775 {
776 	struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
777 	u_int32_t len;
778 	int rseg;
779 
780 	/* XXXX CHECK FOR ALIGNMENT */
781 	/*
782 	 * Allocate and map the request queue.
783 	 */
784 	len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN);
785 	isp->isp_rquest = malloc(len, M_DEVBUF, M_NOWAIT);
786 	if (isp->isp_rquest == NULL) {
787 		printf("%s: cannot malloc request queue\n", isp->isp_name);
788 		return (1);
789 	}
790 	isp->isp_rquest_dma = vtophys(isp->isp_rquest);
791 
792 #if	0
793 	printf("RQUEST=0x%x (0x%x)...", isp->isp_rquest, isp->isp_rquest_dma);
794 #endif
795 
796 	/*
797 	 * Allocate and map the result queue.
798 	 */
799 	len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN);
800 	isp->isp_result = malloc(len, M_DEVBUF, M_NOWAIT);
801 	if (isp->isp_result == NULL) {
802 		free(isp->isp_rquest, M_DEVBUF);
803 		printf("%s: cannot malloc result queue\n", isp->isp_name);
804 		return (1);
805 	}
806 	isp->isp_result_dma = vtophys(isp->isp_result);
807 #if	0
808 	printf("RESULT=0x%x (0x%x)\n", isp->isp_result, isp->isp_result_dma);
809 #endif
810 	if (isp->isp_type & ISP_HA_FC) {
811 		fcparam *fcp = isp->isp_param;
812 		len = ISP2100_SCRLEN;
813 		fcp->isp_scratch = (volatile caddr_t) &pci->_z._y._b;
814 		fcp->isp_scdma = vtophys(fcp->isp_scratch);
815 	}
816 	return (0);
817 }
818 
819 static int
820 isp_pci_dmasetup(isp, xs, rq, iptrp, optr)
821 	struct ispsoftc *isp;
822 	ISP_SCSI_XFER_T *xs;
823 	ispreq_t *rq;
824 	u_int8_t *iptrp;
825 	u_int8_t optr;
826 {
827 	struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
828 	ispcontreq_t *crq;
829 	vm_offset_t vaddr;
830 	int drq, seglim;
831 	u_int32_t paddr, nextpaddr, datalen, size, *ctrp;
832 
833 	if (xs->datalen == 0) {
834 		rq->req_seg_count = 1;
835 		return (CMD_QUEUED);
836 	}
837 
838 	if (xs->flags & SCSI_DATA_IN) {
839 		drq = REQFLAG_DATA_IN;
840 	} else {
841 		drq = REQFLAG_DATA_OUT;
842 	}
843 
844 	if (isp->isp_type & ISP_HA_FC) {
845 		seglim = ISP_RQDSEG_T2;
846 		((ispreqt2_t *)rq)->req_totalcnt = XS_XFRLEN(xs);
847 		((ispreqt2_t *)rq)->req_flags |= drq;
848 	} else {
849 		seglim = ISP_RQDSEG;
850 		rq->req_flags |= drq;
851 	}
852 
853 	datalen = XS_XFRLEN(xs);
854 	vaddr = (vm_offset_t) xs->data;
855 	paddr = vtophys(vaddr);
856 
857 	while (datalen != 0 && rq->req_seg_count < seglim) {
858 		if (isp->isp_type & ISP_HA_FC) {
859 			ispreqt2_t *rq2 = (ispreqt2_t *)rq;
860 			rq2->req_dataseg[rq2->req_seg_count].ds_base = paddr;
861 			ctrp = &rq2->req_dataseg[rq2->req_seg_count].ds_count;
862 		} else {
863 			rq->req_dataseg[rq->req_seg_count].ds_base = paddr;
864 			ctrp = &rq->req_dataseg[rq->req_seg_count].ds_count;
865 		}
866 		nextpaddr = paddr;
867 		*(ctrp) = 0;
868 
869 		while (datalen != 0 && paddr == nextpaddr) {
870 			nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE;
871 			size = nextpaddr - paddr;
872 			if (size > datalen)
873 				size = datalen;
874 
875 			*(ctrp) += size;
876 			vaddr += size;
877 			datalen -= size;
878 			if (datalen != 0)
879 				paddr = vtophys(vaddr);
880 
881 		}
882 #if	0
883 		if (isp->isp_type & ISP_HA_FC) {
884 			ispreqt2_t *rq2 = (ispreqt2_t *)rq;
885 			printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n",
886 			    isp->isp_name, rq->req_seg_count,
887 			    rq2->req_dataseg[rq2->req_seg_count].ds_count,
888 			    rq2->req_dataseg[rq2->req_seg_count].ds_base);
889 		} else {
890 			printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n",
891 			    isp->isp_name, rq->req_seg_count,
892 			    rq->req_dataseg[rq->req_seg_count].ds_count,
893 			    rq->req_dataseg[rq->req_seg_count].ds_base);
894 		}
895 #endif
896 		rq->req_seg_count++;
897 	}
898 
899 
900 
901 	if (datalen == 0)
902 		return (CMD_QUEUED);
903 
904 	paddr = vtophys(vaddr);
905 	while (datalen > 0) {
906 		crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp);
907 		*iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN);
908 		if (*iptrp == optr) {
909 			printf("%s: Request Queue Overflow\n", isp->isp_name);
910 			XS_SETERR(xs, HBA_BOTCH);
911 			return (CMD_EAGAIN);
912 		}
913 		rq->req_header.rqs_entry_count++;
914 		bzero((void *)crq, sizeof (*crq));
915 		crq->req_header.rqs_entry_count = 1;
916 		crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
917 
918 		for (seglim = 0; datalen != 0 && seglim < ISP_CDSEG; seglim++) {
919 			crq->req_dataseg[seglim].ds_base = paddr;
920 			ctrp = &crq->req_dataseg[seglim].ds_count;
921 			*(ctrp) = 0;
922 			nextpaddr = paddr;
923 			while (datalen != 0 && paddr == nextpaddr) {
924 				nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE;
925 				size = nextpaddr - paddr;
926 				if (size > datalen)
927 					size = datalen;
928 
929 				*(ctrp) += size;
930 				vaddr += size;
931 				datalen -= size;
932 				if (datalen != 0)
933 					paddr = vtophys(vaddr);
934 			}
935 #if	0
936 			printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n",
937 			    isp->isp_name, rq->req_header.rqs_entry_count-1,
938 			    seglim, crq->req_dataseg[seglim].ds_count,
939 			    crq->req_dataseg[seglim].ds_base);
940 #endif
941 			rq->req_seg_count++;
942 		}
943 	}
944 
945 	return (CMD_QUEUED);
946 }
947 #endif
948 
949 static void
950 isp_pci_reset1(isp)
951 	struct ispsoftc *isp;
952 {
953 	/* Make sure the BIOS is disabled */
954 	isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
955 }
956 
957 static void
958 isp_pci_dumpregs(isp)
959 	struct ispsoftc *isp;
960 {
961 	struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
962 	printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name,
963 	    pci_conf_read(pci->pci_id, PCI_COMMAND_STATUS_REG));
964 }
965