Annotation of sys/dev/pci/isp_pci.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: isp_pci.c,v 1.39 2007/02/28 19:40:38 kettenis Exp $ */
2: /*
3: * PCI specific probe and attach routines for Qlogic ISP SCSI adapters.
4: *
5: *---------------------------------------
6: * Copyright (c) 1997, 1998, 1999 by Matthew Jacob
7: * NASA/Ames Research Center
8: * All rights reserved.
9: *---------------------------------------
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice immediately at the beginning of the file, without modification,
16: * this list of conditions, and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
27: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: *
35: */
36:
37: #include <dev/ic/isp_openbsd.h>
38:
39: #include <dev/pci/pcireg.h>
40: #include <dev/pci/pcivar.h>
41: #include <dev/pci/pcidevs.h>
42:
43: #ifdef __sparc64__
44: #include <dev/ofw/openfirm.h>
45: #endif
46:
47: static u_int16_t isp_pci_rd_reg(struct ispsoftc *, int);
48: static void isp_pci_wr_reg(struct ispsoftc *, int, u_int16_t);
49: #if !(defined(ISP_DISABLE_1080_SUPPORT) && defined(ISP_DISABLE_12160_SUPPORT))
50: static u_int16_t isp_pci_rd_reg_1080(struct ispsoftc *, int);
51: static void isp_pci_wr_reg_1080(struct ispsoftc *, int, u_int16_t);
52: #endif
53: static int
54: isp_pci_rd_isr(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *);
55: #ifndef ISP_DISABLE_2300_SUPPORT
56: static int
57: isp_pci_rd_isr_2300(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *);
58: #endif
59: static int isp_pci_mbxdma(struct ispsoftc *);
60: static int isp_pci_dmasetup(struct ispsoftc *, struct scsi_xfer *,
61: ispreq_t *, u_int16_t *, u_int16_t);
62: static void
63: isp_pci_dmateardown (struct ispsoftc *, struct scsi_xfer *, u_int16_t);
64: static void isp_pci_reset1 (struct ispsoftc *);
65: static void isp_pci_dumpregs (struct ispsoftc *, const char *);
66: static int isp_pci_intr (void *);
67:
68: #ifdef ISP_COMPILE_FW
69: #define ISP_COMPILE_1040_FW 1
70: #define ISP_COMPILE_1080_FW 1
71: #define ISP_COMPILE_12160_FW 1
72: #define ISP_COMPILE_2100_FW 1
73: #define ISP_COMPILE_2200_FW 1
74: #define ISP_COMPILE_2300_FW 1
75: #endif
76:
77: #if defined(ISP_DISABLE_1040_SUPPORT) || !defined(ISP_COMPILE_1040_FW)
78: #define ISP_1040_RISC_CODE NULL
79: #else
80: #define ISP_1040_RISC_CODE (u_int16_t *) isp_1040_risc_code
81: #include <dev/microcode/isp/asm_1040.h>
82: #endif
83:
84: #if defined(ISP_DISABLE_1080_SUPPORT) || !defined(ISP_COMPILE_1080_FW)
85: #define ISP_1080_RISC_CODE NULL
86: #else
87: #define ISP_1080_RISC_CODE (u_int16_t *) isp_1080_risc_code
88: #include <dev/microcode/isp/asm_1080.h>
89: #endif
90:
91: #if defined(ISP_DISABLE_12160_SUPPORT) || !defined(ISP_COMPILE_12160_FW)
92: #define ISP_12160_RISC_CODE (u_int16_t *) NULL
93: #else
94: #define ISP_12160_RISC_CODE (u_int16_t *) isp_12160_risc_code
95: #include <dev/microcode/isp/asm_12160.h>
96: #endif
97:
98: #if defined(ISP_DISABLE_2100_SUPPORT) || !defined(ISP_COMPILE_2100_FW)
99: #define ISP_2100_RISC_CODE NULL
100: #else
101: #define ISP_2100_RISC_CODE (u_int16_t *) isp_2100_risc_code
102: #include <dev/microcode/isp/asm_2100.h>
103: #endif
104:
105: #if defined(ISP_DISABLE_2200_SUPPORT) || !defined(ISP_COMPILE_2200_FW)
106: #define ISP_2200_RISC_CODE NULL
107: #else
108: #define ISP_2200_RISC_CODE (u_int16_t *) isp_2200_risc_code
109: #include <dev/microcode/isp/asm_2200.h>
110: #endif
111:
112: #if defined(ISP_DISABLE_2300_SUPPORT) || !defined(ISP_COMPILE_2300_FW)
113: #define ISP_2300_RISC_CODE NULL
114: #else
115: #define ISP_2300_RISC_CODE (u_int16_t *) isp_2300_risc_code
116: #include <dev/microcode/isp/asm_2300.h>
117: #endif
118:
119: #ifndef ISP_DISABLE_1020_SUPPORT
120: static struct ispmdvec mdvec = {
121: isp_pci_rd_isr,
122: isp_pci_rd_reg,
123: isp_pci_wr_reg,
124: isp_pci_mbxdma,
125: isp_pci_dmasetup,
126: isp_pci_dmateardown,
127: NULL,
128: isp_pci_reset1,
129: isp_pci_dumpregs,
130: ISP_1040_RISC_CODE,
131: BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
132: };
133: #endif
134:
135: #ifndef ISP_DISABLE_1080_SUPPORT
136: static struct ispmdvec mdvec_1080 = {
137: isp_pci_rd_isr,
138: isp_pci_rd_reg_1080,
139: isp_pci_wr_reg_1080,
140: isp_pci_mbxdma,
141: isp_pci_dmasetup,
142: isp_pci_dmateardown,
143: NULL,
144: isp_pci_reset1,
145: isp_pci_dumpregs,
146: ISP_1080_RISC_CODE,
147: BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
148: };
149: #endif
150:
151: #ifndef ISP_DISABLE_12160_SUPPORT
152: static struct ispmdvec mdvec_12160 = {
153: isp_pci_rd_isr,
154: isp_pci_rd_reg_1080,
155: isp_pci_wr_reg_1080,
156: isp_pci_mbxdma,
157: isp_pci_dmasetup,
158: isp_pci_dmateardown,
159: NULL,
160: isp_pci_reset1,
161: isp_pci_dumpregs,
162: ISP_12160_RISC_CODE,
163: BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64
164: };
165: #endif
166:
167: #ifndef ISP_DISABLE_2100_SUPPORT
168: static struct ispmdvec mdvec_2100 = {
169: isp_pci_rd_isr,
170: isp_pci_rd_reg,
171: isp_pci_wr_reg,
172: isp_pci_mbxdma,
173: isp_pci_dmasetup,
174: isp_pci_dmateardown,
175: NULL,
176: isp_pci_reset1,
177: isp_pci_dumpregs,
178: ISP_2100_RISC_CODE
179: };
180: #endif
181:
182: #ifndef ISP_DISABLE_2200_SUPPORT
183: static struct ispmdvec mdvec_2200 = {
184: isp_pci_rd_isr,
185: isp_pci_rd_reg,
186: isp_pci_wr_reg,
187: isp_pci_mbxdma,
188: isp_pci_dmasetup,
189: isp_pci_dmateardown,
190: NULL,
191: isp_pci_reset1,
192: isp_pci_dumpregs,
193: ISP_2200_RISC_CODE
194: };
195: #endif
196:
197: #ifndef ISP_DISABLE_2300_SUPPORT
198: static struct ispmdvec mdvec_2300 = {
199: isp_pci_rd_isr_2300,
200: isp_pci_rd_reg,
201: isp_pci_wr_reg,
202: isp_pci_mbxdma,
203: isp_pci_dmasetup,
204: isp_pci_dmateardown,
205: NULL,
206: isp_pci_reset1,
207: isp_pci_dumpregs,
208: ISP_2300_RISC_CODE
209: };
210: #endif
211:
212: #ifndef PCI_VENDOR_QLOGIC
213: #define PCI_VENDOR_QLOGIC 0x1077
214: #endif
215:
216: #ifndef PCI_PRODUCT_QLOGIC_ISP1020
217: #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020
218: #endif
219:
220: #ifndef PCI_PRODUCT_QLOGIC_ISP1080
221: #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080
222: #endif
223:
224: #ifndef PCI_PRODUCT_QLOGIC_ISP1240
225: #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240
226: #endif
227:
228: #ifndef PCI_PRODUCT_QLOGIC_ISP1280
229: #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280
230: #endif
231:
232: #ifndef PCI_PRODUCT_QLOGIC_ISP10160
233: #define PCI_PRODUCT_QLOGIC_ISP10160 0x1016
234: #endif
235:
236: #ifndef PCI_PRODUCT_QLOGIC_ISP12160
237: #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216
238: #endif
239:
240: #ifndef PCI_PRODUCT_QLOGIC_ISP2100
241: #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100
242: #endif
243:
244: #ifndef PCI_PRODUCT_QLOGIC_ISP2200
245: #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200
246: #endif
247:
248: #ifndef PCI_PRODUCT_QLOGIC_ISP2300
249: #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300
250: #endif
251:
252: #ifndef PCI_PRODUCT_QLOGIC_ISP2312
253: #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312
254: #endif
255:
256: #ifndef PCI_PRODUCT_QLOGIC_ISP6312
257: #define PCI_PRODUCT_QLOGIC_ISP6312 0x6312
258: #endif
259:
260: #define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC)
261:
262: #define PCI_QLOGIC_ISP1080 \
263: ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC)
264:
265: #define PCI_QLOGIC_ISP1240 \
266: ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC)
267:
268: #define PCI_QLOGIC_ISP1280 \
269: ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC)
270:
271: #define PCI_QLOGIC_ISP10160 \
272: ((PCI_PRODUCT_QLOGIC_ISP10160 << 16) | PCI_VENDOR_QLOGIC)
273:
274: #define PCI_QLOGIC_ISP12160 \
275: ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC)
276:
277: #define PCI_QLOGIC_ISP2100 \
278: ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC)
279:
280: #define PCI_QLOGIC_ISP2200 \
281: ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC)
282:
283: #define PCI_QLOGIC_ISP2300 \
284: ((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC)
285:
286: #define PCI_QLOGIC_ISP2312 \
287: ((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC)
288:
289: #define PCI_QLOGIC_ISP6312 \
290: ((PCI_PRODUCT_QLOGIC_ISP6312 << 16) | PCI_VENDOR_QLOGIC)
291:
292: /*
293: * Odd case for some AMI raid cards... We need to *not* attach to this.
294: */
295: #define AMI_RAID_SUBVENDOR_ID 0x101e
296:
297:
298: #define IO_MAP_REG 0x10
299: #define MEM_MAP_REG 0x14
300: #define PCIR_ROMADDR 0x30
301:
302: #define PCI_DFLT_LTNCY 0x40
303: #define PCI_DFLT_LNSZ 0x10
304:
305: #ifndef SCSI_ISP_PREFER_MEM_MAP
306: #ifdef __alpha__
307: #define SCSI_ISP_PREFER_MEM_MAP 1
308: #else
309: #define SCSI_ISP_PREFER_MEM_MAP 0
310: #endif
311: #endif
312:
313: #ifndef BUS_DMA_COHERENT
314: #define BUS_DMA_COHERENT BUS_DMAMEM_NOSYNC
315: #endif
316:
317: static int isp_pci_probe (struct device *, void *, void *);
318: static void isp_pci_attach (struct device *, struct device *, void *);
319:
320: struct isp_pcisoftc {
321: struct ispsoftc pci_isp;
322: pci_chipset_tag_t pci_pc;
323: pcitag_t pci_tag;
324: bus_space_tag_t pci_st;
325: bus_space_handle_t pci_sh;
326: bus_dmamap_t *pci_xfer_dmap;
327: void * pci_ih;
328: int16_t pci_poff[_NREG_BLKS];
329: };
330:
331: struct cfattach isp_pci_ca = {
332: sizeof (struct isp_pcisoftc), isp_pci_probe, isp_pci_attach
333: };
334:
335: #ifdef DEBUG
336: const char vstring[] =
337: "Qlogic ISP Driver, NetBSD (pci) Platform Version %d.%d Core Version %d.%d";
338: #endif
339:
340: const struct pci_matchid ispdev[] = {
341: #ifndef ISP_DISABLE_1020_SUPPORT
342: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1020 },
343: #endif
344: #ifndef ISP_DISABLE_1080_SUPPORT
345: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1080 },
346: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1240 },
347: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1280 },
348: #endif
349: #ifndef ISP_DISABLE_12160_SUPPORT
350: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP10160 },
351: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP12160 },
352: #endif
353: #ifndef ISP_DISABLE_2100_SUPPORT
354: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2100 },
355: #endif
356: #ifndef ISP_DISABLE_2200_SUPPORT
357: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2200 },
358: #endif
359: #ifndef ISP_DISABLE_2300_SUPPORT
360: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2300 },
361: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP2312 },
362: { PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP6312 },
363: #endif
364: { 0, 0 }
365: };
366:
367: static int
368: isp_pci_probe(struct device *parent, void *match, void *aux)
369: {
370: struct pci_attach_args *pa = aux;
371:
372: #ifndef ISP_DISABLE_12160_SUPPORT
373: /*
374: * Sigh. Check for subvendor id match here. Too bad we
375: * can't give an exclude mask in matchbyid.
376: */
377: if (pa->pa_id == PCI_QLOGIC_ISP12160) {
378: pcireg_t subvid =
379: pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBVEND_0);
380: if (PCI_VENDOR(subvid) == AMI_RAID_SUBVENDOR_ID) {
381: return (0);
382: }
383: }
384: #endif
385: return (pci_matchbyid(pa, ispdev, sizeof(ispdev)/sizeof(ispdev[0])));
386: }
387:
388:
389: static void
390: isp_pci_attach(struct device *parent, struct device *self, void *aux)
391: {
392: #ifdef DEBUG
393: static char oneshot = 1;
394: #endif
395: static const char nomem[] = ": no mem for sdparam table\n";
396: u_int32_t data, rev, linesz = PCI_DFLT_LNSZ;
397: struct pci_attach_args *pa = aux;
398: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) self;
399: struct ispsoftc *isp = &pcs->pci_isp;
400: bus_space_tag_t st, iot, memt;
401: bus_space_handle_t sh, ioh, memh;
402: pci_intr_handle_t ih;
403: const char *intrstr;
404: int ioh_valid, memh_valid;
405: bus_size_t iosize, msize;
406: u_int32_t confopts = 0;
407:
408: ioh_valid = memh_valid = 0;
409:
410: #if SCSI_ISP_PREFER_MEM_MAP == 1
411: if (pci_mapreg_map(pa, MEM_MAP_REG, PCI_MAPREG_TYPE_MEM, 0,
412: &memt, &memh, NULL, &msize, 0)) {
413: printf(": can't map mem space\n");
414: } else {
415: st = memt;
416: sh = memh;
417: memh_valid = 1;
418: }
419: if (memh_valid == 0) {
420: if (pci_mapreg_map(pa, IO_MAP_REG, PCI_MAPREG_TYPE_IO, 0,
421: &iot, &ioh, NULL, &iosize, 0)) {
422: } else {
423: st = iot;
424: sh = ioh;
425: ioh_valid = 1;
426: }
427: }
428: #else
429: if (pci_mapreg_map(pa, IO_MAP_REG, PCI_MAPREG_TYPE_IO, 0,
430: &iot, &ioh, NULL, &iosize, 0)) {
431: printf(": can't map i/o space\n");
432: } else {
433: st = iot;
434: sh = ioh;
435: ioh_valid = 1;
436: }
437: if (ioh_valid == 0) {
438: if (pci_mapreg_map(pa, MEM_MAP_REG, PCI_MAPREG_TYPE_MEM, 0,
439: &memt, &memh, NULL, &msize, 0)) {
440: printf(": can't map mem space\n");
441: } else {
442: st = memt;
443: sh = memh;
444: memh_valid = 1;
445: }
446: }
447: #endif
448: if (ioh_valid == 0 && memh_valid == 0) {
449: printf(": unable to map device registers\n");
450: return;
451: }
452: #if 0
453: printf("\n");
454: #endif
455:
456: pcs->pci_st = st;
457: pcs->pci_sh = sh;
458: pcs->pci_pc = pa->pa_pc;
459: pcs->pci_tag = pa->pa_tag;
460: pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
461: pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
462: pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
463: pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF;
464: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
465: rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0xff;
466: #ifndef ISP_DISABLE_1020_SUPPORT
467: if (pa->pa_id == PCI_QLOGIC_ISP) {
468: isp->isp_mdvec = &mdvec;
469: isp->isp_type = ISP_HA_SCSI_UNKNOWN;
470: isp->isp_param = malloc(sizeof (sdparam), M_DEVBUF, M_NOWAIT);
471: if (isp->isp_param == NULL) {
472: printf(nomem);
473: return;
474: }
475: bzero(isp->isp_param, sizeof (sdparam));
476: }
477: #endif
478: #ifndef ISP_DISABLE_1080_SUPPORT
479: if (pa->pa_id == PCI_QLOGIC_ISP1080) {
480: isp->isp_mdvec = &mdvec_1080;
481: isp->isp_type = ISP_HA_SCSI_1080;
482: isp->isp_param = malloc(sizeof (sdparam), M_DEVBUF, M_NOWAIT);
483: if (isp->isp_param == NULL) {
484: printf(nomem);
485: return;
486: }
487: bzero(isp->isp_param, sizeof (sdparam));
488: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
489: ISP1080_DMA_REGS_OFF;
490: }
491: if (pa->pa_id == PCI_QLOGIC_ISP1240) {
492: isp->isp_mdvec = &mdvec_1080;
493: isp->isp_type = ISP_HA_SCSI_1240;
494: isp->isp_param = malloc(2 * sizeof (sdparam),
495: M_DEVBUF, M_NOWAIT);
496: if (isp->isp_param == NULL) {
497: printf(nomem);
498: return;
499: }
500: bzero(isp->isp_param, sizeof (sdparam));
501: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
502: ISP1080_DMA_REGS_OFF;
503: }
504: if (pa->pa_id == PCI_QLOGIC_ISP1280) {
505: isp->isp_mdvec = &mdvec_1080;
506: isp->isp_type = ISP_HA_SCSI_1280;
507: isp->isp_param = malloc(2 * sizeof (sdparam),
508: M_DEVBUF, M_NOWAIT);
509: if (isp->isp_param == NULL) {
510: printf(nomem);
511: return;
512: }
513: bzero(isp->isp_param, sizeof (sdparam));
514: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
515: ISP1080_DMA_REGS_OFF;
516: }
517: #endif
518: #ifndef ISP_DISABLE_12160_SUPPORT
519: if (pa->pa_id == PCI_QLOGIC_ISP10160) {
520: isp->isp_mdvec = &mdvec_12160;
521: isp->isp_type = ISP_HA_SCSI_10160;
522: isp->isp_param = malloc(sizeof (sdparam), M_DEVBUF, M_NOWAIT);
523: if (isp->isp_param == NULL) {
524: printf(nomem);
525: return;
526: }
527: bzero(isp->isp_param, sizeof (sdparam));
528: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
529: ISP1080_DMA_REGS_OFF;
530: }
531: if (pa->pa_id == PCI_QLOGIC_ISP12160) {
532: isp->isp_mdvec = &mdvec_12160;
533: isp->isp_type = ISP_HA_SCSI_12160;
534: isp->isp_param = malloc(2 * sizeof (sdparam),
535: M_DEVBUF, M_NOWAIT);
536: if (isp->isp_param == NULL) {
537: printf(nomem);
538: return;
539: }
540: bzero(isp->isp_param, 2 * sizeof (sdparam));
541: pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
542: ISP1080_DMA_REGS_OFF;
543: }
544: #endif
545: #ifndef ISP_DISABLE_2100_SUPPORT
546: if (pa->pa_id == PCI_QLOGIC_ISP2100) {
547: isp->isp_mdvec = &mdvec_2100;
548: isp->isp_type = ISP_HA_FC_2100;
549: isp->isp_param = malloc(sizeof (fcparam), M_DEVBUF, M_NOWAIT);
550: if (isp->isp_param == NULL) {
551: printf(nomem);
552: return;
553: }
554: bzero(isp->isp_param, sizeof (fcparam));
555: pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
556: PCI_MBOX_REGS2100_OFF;
557: if (rev < 3) {
558: /*
559: * XXX: Need to get the actual revision
560: * XXX: number of the 2100 FB. At any rate,
561: * XXX: lower cache line size for early revision
562: * XXX; boards.
563: */
564: linesz = 1;
565: }
566: }
567: #endif
568: #ifndef ISP_DISABLE_2200_SUPPORT
569: if (pa->pa_id == PCI_QLOGIC_ISP2200) {
570: isp->isp_mdvec = &mdvec_2200;
571: isp->isp_type = ISP_HA_FC_2200;
572: isp->isp_param = malloc(sizeof (fcparam), M_DEVBUF, M_NOWAIT);
573: if (isp->isp_param == NULL) {
574: printf(nomem);
575: return;
576: }
577: bzero(isp->isp_param, sizeof (fcparam));
578: pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
579: PCI_MBOX_REGS2100_OFF;
580: data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG);
581: #ifdef __sparc64__
582: {
583: char name[32];
584:
585: bzero(name, sizeof(name));
586: OF_getprop(PCITAG_NODE(pa->pa_tag),
587: "name", name, sizeof(name));
588: if (strcmp(name, "SUNW,qlc") == 0)
589: confopts |= ISP_CFG_NONVRAM;
590: }
591: #endif
592: }
593: #endif
594: #ifndef ISP_DISABLE_2300_SUPPORT
595: if (pa->pa_id == PCI_QLOGIC_ISP2300 ||
596: pa->pa_id == PCI_QLOGIC_ISP2312 ||
597: pa->pa_id == PCI_QLOGIC_ISP6312) {
598: isp->isp_mdvec = &mdvec_2300;
599: if (pa->pa_id == PCI_QLOGIC_ISP2300) {
600: isp->isp_type = ISP_HA_FC_2300;
601: } else {
602: isp->isp_type = ISP_HA_FC_2312;
603: isp->isp_port = pa->pa_function;
604: }
605: isp->isp_param = malloc(sizeof (fcparam), M_DEVBUF, M_NOWAIT);
606: if (isp->isp_param == NULL) {
607: printf(nomem);
608: return;
609: }
610: bzero(isp->isp_param, sizeof (fcparam));
611: pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
612: PCI_MBOX_REGS2300_OFF;
613: data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG);
614: }
615: #endif
616: /*
617: * Set up logging levels.
618: */
619: #ifdef ISP_LOGDEFAULT
620: isp->isp_dblev = ISP_LOGDEFAULT;
621: #else
622: isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR;
623: #ifdef SCSIDEBUG
624: isp->isp_dblev |= ISP_LOGDEBUG1|ISP_LOGDEBUG2;
625: #endif
626: #ifdef DEBUG
627: isp->isp_dblev |= ISP_LOGDEBUG0|ISP_LOGCONFIG|ISP_LOGINFO;
628: #endif
629: #endif
630:
631: #ifdef DEBUG
632: if (oneshot) {
633: oneshot = 0;
634: isp_prt(isp, ISP_LOGCONFIG, vstring,
635: ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
636: ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
637: }
638: #endif
639:
640: isp->isp_dmatag = pa->pa_dmat;
641: isp->isp_revision = rev;
642:
643: /*
644: * Make sure that command register set sanely.
645: */
646: data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
647: if (IS_2300(isp)) { /* per QLogic errata */
648: data &= ~PCI_COMMAND_PARITY_ENABLE;
649: }
650: if (IS_23XX(isp)) {
651: isp->isp_touched = 1;
652: }
653: data |= PCI_COMMAND_INVALIDATE_ENABLE;
654:
655: /*
656: * Not so sure about these- but I think it's important that they get
657: * enabled......
658: */
659: data |= PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE;
660: pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, data);
661:
662: /*
663: * Make sure that the latency timer, cache line size,
664: * and ROM is disabled.
665: */
666: data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
667: data &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
668: data &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT);
669: data |= (0x40 << PCI_LATTIMER_SHIFT);
670: data |= (0x10 << PCI_CACHELINE_SHIFT);
671: pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, data);
672:
673: data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCIR_ROMADDR);
674: data &= ~1;
675: pci_conf_write(pa->pa_pc, pa->pa_tag, PCIR_ROMADDR, data);
676:
677: if (pci_intr_map(pa, &ih)) {
678: printf(": couldn't map interrupt\n");
679: free(isp->isp_param, M_DEVBUF);
680: return;
681: }
682: intrstr = pci_intr_string(pa->pa_pc, ih);
683: if (intrstr == NULL)
684: intrstr = "<I dunno>";
685: pcs->pci_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, isp_pci_intr,
686: isp, isp->isp_name);
687: if (pcs->pci_ih == NULL) {
688: printf(": couldn't establish interrupt at %s\n",
689: intrstr);
690: free(isp->isp_param, M_DEVBUF);
691: return;
692: }
693:
694: printf(": %s\n", intrstr);
695:
696: if (IS_FC(isp)) {
697: DEFAULT_NODEWWN(isp) = 0x400000007F000003ULL;
698: DEFAULT_PORTWWN(isp) = 0x400000007F000003ULL;
699: }
700:
701: isp->isp_confopts = confopts | self->dv_cfdata->cf_flags;
702: isp->isp_role = ISP_DEFAULT_ROLES;
703: ISP_LOCK(isp);
704: isp->isp_osinfo.no_mbox_ints = 1;
705: isp_reset(isp);
706: if (isp->isp_state != ISP_RESETSTATE) {
707: ISP_UNLOCK(isp);
708: free(isp->isp_param, M_DEVBUF);
709: return;
710: }
711: ENABLE_INTS(isp);
712: isp_init(isp);
713: if (isp->isp_state != ISP_INITSTATE) {
714: isp_uninit(isp);
715: ISP_UNLOCK(isp);
716: free(isp->isp_param, M_DEVBUF);
717: return;
718: }
719: /*
720: * Do Generic attach now.
721: */
722: isp_attach(isp);
723: if (isp->isp_state != ISP_RUNSTATE) {
724: isp_uninit(isp);
725: ISP_UNLOCK(isp);
726: free(isp->isp_param, M_DEVBUF);
727: } else {
728: ISP_UNLOCK(isp);
729: }
730: }
731:
732: #define IspVirt2Off(a, x) \
733: (((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \
734: _BLK_REG_SHFT] + ((x) & 0xff))
735:
736: #define BXR2(pcs, off) \
737: bus_space_read_2(pcs->pci_st, pcs->pci_sh, off)
738: #define BXW2(pcs, off, v) \
739: bus_space_write_2(pcs->pci_st, pcs->pci_sh, off, v)
740:
741:
742: static INLINE int
743: isp_pci_rd_debounced(struct ispsoftc *isp, int off, u_int16_t *rp)
744: {
745: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
746: u_int16_t val0, val1;
747: int i = 0;
748:
749: do {
750: val0 = BXR2(pcs, IspVirt2Off(isp, off));
751: val1 = BXR2(pcs, IspVirt2Off(isp, off));
752: } while (val0 != val1 && ++i < 1000);
753: if (val0 != val1) {
754: return (1);
755: }
756: *rp = val0;
757: return (0);
758: }
759:
760: static int
761: isp_pci_rd_isr(struct ispsoftc *isp, u_int16_t *isrp,
762: u_int16_t *semap, u_int16_t *mbp)
763: {
764: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
765: u_int16_t isr, sema;
766:
767: if (IS_2100(isp)) {
768: if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) {
769: return (0);
770: }
771: if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) {
772: return (0);
773: }
774: } else {
775: isr = BXR2(pcs, IspVirt2Off(isp, BIU_ISR));
776: sema = BXR2(pcs, IspVirt2Off(isp, BIU_SEMA));
777: }
778: isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema);
779: isr &= INT_PENDING_MASK(isp);
780: sema &= BIU_SEMA_LOCK;
781: if (isr == 0 && sema == 0) {
782: return (0);
783: }
784: *isrp = isr;
785: if ((*semap = sema) != 0) {
786: if (IS_2100(isp)) {
787: if (isp_pci_rd_debounced(isp, OUTMAILBOX0, mbp)) {
788: return (0);
789: }
790: } else {
791: *mbp = BXR2(pcs, IspVirt2Off(isp, OUTMAILBOX0));
792: }
793: }
794: return (1);
795: }
796:
797: #ifndef ISP_DISABLE_2300_SUPPORT
798: static int
799: isp_pci_rd_isr_2300(struct ispsoftc *isp, u_int16_t *isrp,
800: u_int16_t *semap, u_int16_t *mbox0p)
801: {
802: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
803: u_int32_t r2hisr;
804:
805: if (!(BXR2(pcs, IspVirt2Off(isp, BIU_ISR)) & BIU2100_ISR_RISC_INT)) {
806: *isrp = 0;
807: return (0);
808: }
809: r2hisr = bus_space_read_4(pcs->pci_st, pcs->pci_sh,
810: IspVirt2Off(pcs, BIU_R2HSTSLO));
811: isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr);
812: if ((r2hisr & BIU_R2HST_INTR) == 0) {
813: *isrp = 0;
814: return (0);
815: }
816: switch (r2hisr & BIU_R2HST_ISTAT_MASK) {
817: case ISPR2HST_ROM_MBX_OK:
818: case ISPR2HST_ROM_MBX_FAIL:
819: case ISPR2HST_MBX_OK:
820: case ISPR2HST_MBX_FAIL:
821: case ISPR2HST_ASYNC_EVENT:
822: *isrp = r2hisr & 0xffff;
823: *mbox0p = (r2hisr >> 16);
824: *semap = 1;
825: return (1);
826: case ISPR2HST_RIO_16:
827: *isrp = r2hisr & 0xffff;
828: *mbox0p = ASYNC_RIO1;
829: *semap = 1;
830: return (1);
831: case ISPR2HST_FPOST:
832: *isrp = r2hisr & 0xffff;
833: *mbox0p = ASYNC_CMD_CMPLT;
834: *semap = 1;
835: return (1);
836: case ISPR2HST_FPOST_CTIO:
837: *isrp = r2hisr & 0xffff;
838: *mbox0p = ASYNC_CTIO_DONE;
839: *semap = 1;
840: return (1);
841: case ISPR2HST_RSPQ_UPDATE:
842: *isrp = r2hisr & 0xffff;
843: *mbox0p = 0;
844: *semap = 0;
845: return (1);
846: default:
847: return (0);
848: }
849: }
850: #endif
851:
852: static u_int16_t
853: isp_pci_rd_reg(struct ispsoftc *isp, int regoff)
854: {
855: u_int16_t rv;
856: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
857: int oldconf = 0;
858:
859: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
860: /*
861: * We will assume that someone has paused the RISC processor.
862: */
863: oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
864: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
865: oldconf | BIU_PCI_CONF1_SXP);
866: }
867: rv = BXR2(pcs, IspVirt2Off(isp, regoff));
868: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
869: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf);
870: }
871: return (rv);
872: }
873:
874: static void
875: isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val)
876: {
877: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
878: int oldconf = 0;
879:
880: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
881: /*
882: * We will assume that someone has paused the RISC processor.
883: */
884: oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
885: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
886: oldconf | BIU_PCI_CONF1_SXP);
887: }
888: BXW2(pcs, IspVirt2Off(isp, regoff), val);
889: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
890: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf);
891: }
892: }
893:
894: #if !(defined(ISP_DISABLE_1080_SUPPORT) && defined(ISP_DISABLE_12160_SUPPORT))
895: static u_int16_t
896: isp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff)
897: {
898: u_int16_t rv, oc = 0;
899: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
900:
901: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
902: (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
903: u_int16_t tc;
904: /*
905: * We will assume that someone has paused the RISC processor.
906: */
907: oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
908: tc = oc & ~BIU_PCI1080_CONF1_DMA;
909: if (regoff & SXP_BANK1_SELECT)
910: tc |= BIU_PCI1080_CONF1_SXP1;
911: else
912: tc |= BIU_PCI1080_CONF1_SXP0;
913: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc);
914: } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
915: oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
916: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
917: oc | BIU_PCI1080_CONF1_DMA);
918: }
919: rv = BXR2(pcs, IspVirt2Off(isp, regoff));
920: if (oc) {
921: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc);
922: }
923: return (rv);
924: }
925:
926: static void
927: isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val)
928: {
929: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
930: int oc = 0;
931:
932: if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
933: (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
934: u_int16_t tc;
935: /*
936: * We will assume that someone has paused the RISC processor.
937: */
938: oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
939: tc = oc & ~BIU_PCI1080_CONF1_DMA;
940: if (regoff & SXP_BANK1_SELECT)
941: tc |= BIU_PCI1080_CONF1_SXP1;
942: else
943: tc |= BIU_PCI1080_CONF1_SXP0;
944: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc);
945: } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
946: oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
947: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
948: oc | BIU_PCI1080_CONF1_DMA);
949: }
950: BXW2(pcs, IspVirt2Off(isp, regoff), val);
951: if (oc) {
952: BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc);
953: }
954: }
955: #endif
956:
957: static int
958: isp_pci_mbxdma(struct ispsoftc *isp)
959: {
960: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
961: bus_dma_tag_t dmat = isp->isp_dmatag;
962: bus_dma_segment_t sg;
963: bus_size_t len;
964: fcparam *fcp;
965: int rs, i;
966:
967: if (isp->isp_rquest_dma) /* been here before? */
968: return (0);
969:
970: len = isp->isp_maxcmds * sizeof (XS_T *);
971: isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK);
972: if (isp->isp_xflist == NULL) {
973: isp_prt(isp, ISP_LOGERR, "cannot malloc xflist array");
974: return (1);
975: }
976: bzero(isp->isp_xflist, len);
977: len = isp->isp_maxcmds * sizeof (bus_dmamap_t);
978: pcs->pci_xfer_dmap = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK);
979: if (pcs->pci_xfer_dmap == NULL) {
980: free(isp->isp_xflist, M_DEVBUF);
981: isp->isp_xflist = NULL;
982: isp_prt(isp, ISP_LOGERR, "cannot malloc dma map array");
983: return (1);
984: }
985:
986: for (i = 0; i < isp->isp_maxcmds; i++) {
987: if (bus_dmamap_create(dmat, MAXPHYS, (MAXPHYS / NBPG) + 1,
988: MAXPHYS, 0, BUS_DMA_NOWAIT, &pcs->pci_xfer_dmap[i])) {
989: isp_prt(isp, ISP_LOGERR, "cannot create dma maps");
990: break;
991: }
992: }
993:
994: if (i < isp->isp_maxcmds) {
995: while (--i >= 0) {
996: bus_dmamap_destroy(dmat, pcs->pci_xfer_dmap[i]);
997: }
998: free(isp->isp_xflist, M_DEVBUF);
999: free(pcs->pci_xfer_dmap, M_DEVBUF);
1000: isp->isp_xflist = NULL;
1001: pcs->pci_xfer_dmap = NULL;
1002: return (1);
1003: }
1004:
1005: /*
1006: * Allocate and map the request queue.
1007: */
1008: len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
1009: if (bus_dmamem_alloc(dmat, len, PAGE_SIZE, 0, &sg, 1, &rs,
1010: BUS_DMA_NOWAIT) ||
1011: bus_dmamem_map(isp->isp_dmatag, &sg, rs, len,
1012: (caddr_t *)&isp->isp_rquest, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
1013: goto dmafail;
1014: }
1015:
1016: if (bus_dmamap_create(dmat, len, 1, len, 0, BUS_DMA_NOWAIT,
1017: &isp->isp_rqdmap) || bus_dmamap_load(dmat, isp->isp_rqdmap,
1018: (caddr_t)isp->isp_rquest, len, NULL,
1019: BUS_DMA_NOWAIT)) {
1020: goto dmafail;
1021: }
1022: isp->isp_rquest_dma = isp->isp_rqdmap->dm_segs[0].ds_addr;
1023:
1024: /*
1025: * Allocate and map the result queue.
1026: */
1027: len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
1028: if (bus_dmamem_alloc(dmat, len, PAGE_SIZE, 0, &sg, 1, &rs,
1029: BUS_DMA_NOWAIT) ||
1030: bus_dmamem_map(dmat, &sg, rs, len, (caddr_t *)&isp->isp_result,
1031: BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
1032: goto dmafail;
1033: }
1034: if (bus_dmamap_create(dmat, len, 1, len, 0, BUS_DMA_NOWAIT,
1035: &isp->isp_rsdmap) || bus_dmamap_load(isp->isp_dmatag,
1036: isp->isp_rsdmap, (caddr_t)isp->isp_result, len, NULL,
1037: BUS_DMA_NOWAIT)) {
1038: goto dmafail;
1039: }
1040: isp->isp_result_dma = isp->isp_rsdmap->dm_segs[0].ds_addr;
1041:
1042: if (IS_SCSI(isp)) {
1043: return (0);
1044: }
1045:
1046: fcp = isp->isp_param;
1047: len = ISP2100_SCRLEN;
1048: if (bus_dmamem_alloc(dmat, len, PAGE_SIZE, 0, &sg, 1, &rs,
1049: BUS_DMA_NOWAIT) ||
1050: bus_dmamem_map(dmat, &sg, rs, len, (caddr_t *)&fcp->isp_scratch,
1051: BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
1052: goto dmafail;
1053: }
1054: if (bus_dmamap_create(dmat, len, 1, len, 0, BUS_DMA_NOWAIT,
1055: &isp->isp_scdmap) || bus_dmamap_load(dmat,
1056: isp->isp_scdmap, (caddr_t)fcp->isp_scratch, len, NULL,
1057: BUS_DMA_NOWAIT)) {
1058: goto dmafail;
1059: }
1060: fcp->isp_scdma = isp->isp_scdmap->dm_segs[0].ds_addr;
1061: return (0);
1062: dmafail:
1063: isp_prt(isp, ISP_LOGERR, "mailbox dma setup failure");
1064: for (i = 0; i < isp->isp_maxcmds; i++) {
1065: bus_dmamap_destroy(dmat, pcs->pci_xfer_dmap[i]);
1066: }
1067: free(isp->isp_xflist, M_DEVBUF);
1068: free(pcs->pci_xfer_dmap, M_DEVBUF);
1069: isp->isp_xflist = NULL;
1070: pcs->pci_xfer_dmap = NULL;
1071: return (1);
1072: }
1073:
1074: static int
1075: isp_pci_dmasetup(struct ispsoftc *isp, XS_T *xs, ispreq_t *rq,
1076: u_int16_t *nxtip, u_int16_t optr)
1077: {
1078: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
1079: bus_dmamap_t dmap;
1080: u_int16_t starti = isp->isp_reqidx, nxti = *nxtip;
1081: ispreq_t *qep;
1082: int segcnt, seg, error, ovseg, seglim, drq;
1083:
1084: qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, starti);
1085: dmap = pcs->pci_xfer_dmap[isp_handle_index(rq->req_handle)];
1086: if (xs->datalen == 0) {
1087: rq->req_seg_count = 1;
1088: goto mbxsync;
1089: }
1090:
1091: if (xs->flags & SCSI_DATA_IN) {
1092: drq = REQFLAG_DATA_IN;
1093: } else {
1094: drq = REQFLAG_DATA_OUT;
1095: }
1096:
1097: if (IS_FC(isp)) {
1098: seglim = ISP_RQDSEG_T2;
1099: ((ispreqt2_t *)rq)->req_totalcnt = xs->datalen;
1100: ((ispreqt2_t *)rq)->req_flags |= drq;
1101: } else {
1102: rq->req_flags |= drq;
1103: if (XS_CDBLEN(xs) > 12)
1104: seglim = 0;
1105: else
1106: seglim = ISP_RQDSEG;
1107: }
1108: error = bus_dmamap_load(isp->isp_dmatag, dmap, xs->data, xs->datalen,
1109: NULL, (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
1110: if (error) {
1111: XS_SETERR(xs, HBA_BOTCH);
1112: return (CMD_COMPLETE);
1113: }
1114:
1115: segcnt = dmap->dm_nsegs;
1116:
1117: isp_prt(isp, ISP_LOGDEBUG2, "%d byte %s %p in %d segs",
1118: xs->datalen, (xs->flags & SCSI_DATA_IN)? "read to" :
1119: "write from", xs->data, segcnt);
1120:
1121: for (seg = 0, rq->req_seg_count = 0;
1122: seg < segcnt && rq->req_seg_count < seglim;
1123: seg++, rq->req_seg_count++) {
1124: if (isp->isp_type & ISP_HA_FC) {
1125: ispreqt2_t *rq2 = (ispreqt2_t *)rq;
1126: rq2->req_dataseg[rq2->req_seg_count].ds_count =
1127: dmap->dm_segs[seg].ds_len;
1128: rq2->req_dataseg[rq2->req_seg_count].ds_base =
1129: dmap->dm_segs[seg].ds_addr;
1130: } else {
1131: rq->req_dataseg[rq->req_seg_count].ds_count =
1132: dmap->dm_segs[seg].ds_len;
1133: rq->req_dataseg[rq->req_seg_count].ds_base =
1134: dmap->dm_segs[seg].ds_addr;
1135: }
1136: isp_prt(isp, ISP_LOGDEBUG2, "seg0.[%d]={0x%lx,%lu}",
1137: rq->req_seg_count, (long) dmap->dm_segs[seg].ds_addr,
1138: (unsigned long) dmap->dm_segs[seg].ds_len);
1139: }
1140:
1141: if (seg == segcnt) {
1142: goto dmasync;
1143: }
1144:
1145: do {
1146: u_int16_t onxti;
1147: ispcontreq_t *crq, *cqe, local;
1148:
1149: crq = &local;
1150:
1151: cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
1152: onxti = nxti;
1153: nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp));
1154: if (nxti == optr) {
1155: isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++");
1156: bus_dmamap_unload(isp->isp_dmatag, dmap);
1157: XS_SETERR(xs, HBA_BOTCH);
1158: return (CMD_EAGAIN);
1159: }
1160: rq->req_header.rqs_entry_count++;
1161: bzero((void *)crq, sizeof (*crq));
1162: crq->req_header.rqs_entry_count = 1;
1163: crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
1164:
1165: for (ovseg = 0; seg < segcnt && ovseg < ISP_CDSEG;
1166: rq->req_seg_count++, seg++, ovseg++) {
1167: crq->req_dataseg[ovseg].ds_count =
1168: dmap->dm_segs[seg].ds_len;
1169: crq->req_dataseg[ovseg].ds_base =
1170: dmap->dm_segs[seg].ds_addr;
1171: isp_prt(isp, ISP_LOGDEBUG2, "seg%d.[%d]={0x%lx,%lu}",
1172: rq->req_header.rqs_entry_count - 1,
1173: rq->req_seg_count, (long)dmap->dm_segs[seg].ds_addr,
1174: (unsigned long) dmap->dm_segs[seg].ds_len);
1175: }
1176: isp_put_cont_req(isp, crq, cqe);
1177: MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
1178: } while (seg < segcnt);
1179:
1180: dmasync:
1181: bus_dmamap_sync(isp->isp_dmatag, dmap, 0, dmap->dm_mapsize,
1182: (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1183: BUS_DMASYNC_PREWRITE);
1184:
1185: mbxsync:
1186: switch (rq->req_header.rqs_entry_type) {
1187: case RQSTYPE_REQUEST:
1188: isp_put_request(isp, rq, qep);
1189: break;
1190: case RQSTYPE_CMDONLY:
1191: isp_put_extended_request(isp, (ispextreq_t *)rq,
1192: (ispextreq_t *)qep);
1193: break;
1194: case RQSTYPE_T2RQS:
1195: isp_put_request_t2(isp, (ispreqt2_t *) rq, (ispreqt2_t *) qep);
1196: break;
1197: }
1198: *nxtip = nxti;
1199: return (CMD_QUEUED);
1200: }
1201:
1202: static int
1203: isp_pci_intr(void *arg)
1204: {
1205: u_int16_t isr, sema, mbox;
1206: struct ispsoftc *isp = (struct ispsoftc *)arg;
1207:
1208: isp->isp_intcnt++;
1209: if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
1210: isp->isp_intbogus++;
1211: return (0);
1212: } else {
1213: isp->isp_osinfo.onintstack = 1;
1214: isp_intr(isp, isr, sema, mbox);
1215: isp->isp_osinfo.onintstack = 0;
1216: return (1);
1217: }
1218: }
1219:
1220: static void
1221: isp_pci_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int16_t handle)
1222: {
1223: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
1224: bus_dmamap_t dmap = pcs->pci_xfer_dmap[isp_handle_index(handle)];
1225: bus_dmamap_sync(isp->isp_dmatag, dmap, 0, dmap->dm_mapsize,
1226: (xs->flags & SCSI_DATA_IN)?
1227: BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1228: bus_dmamap_unload(isp->isp_dmatag, dmap);
1229: }
1230:
1231: static void
1232: isp_pci_reset1(struct ispsoftc *isp)
1233: {
1234: /* Make sure the BIOS is disabled */
1235: isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
1236: if (isp->isp_osinfo.no_mbox_ints == 0) {
1237: ENABLE_INTS(isp);
1238: }
1239: }
1240:
1241: static void
1242: isp_pci_dumpregs(struct ispsoftc *isp, const char *msg)
1243: {
1244: struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
1245: if (msg)
1246: isp_prt(isp, ISP_LOGERR, "%s", msg);
1247: isp_prt(isp, ISP_LOGERR, "PCI Status Command/Status=%x\n",
1248: pci_conf_read(pcs->pci_pc, pcs->pci_tag, PCI_COMMAND_STATUS_REG));
1249: }
CVSweb