isp_pci.c revision 1.45 1 /* $NetBSD: isp_pci.c,v 1.45 1999/10/17 02:40:26 mjacob Exp $ */
2 /*
3 * PCI specific probe and attach routines for Qlogic ISP SCSI adapters.
4 * Matthew Jacob (mjacob (at) nas.nasa.gov)
5 */
6 /*
7 * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <dev/ic/isp_netbsd.h>
34 #include <dev/microcode/isp/asm_pci.h>
35
36 #include <dev/pci/pcireg.h>
37 #include <dev/pci/pcivar.h>
38 #include <dev/pci/pcidevs.h>
39
40 static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int));
41 static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t));
42 #ifndef ISP_DISABLE_1080_SUPPORT
43 static u_int16_t isp_pci_rd_reg_1080 __P((struct ispsoftc *, int));
44 static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t));
45 #endif
46 static int isp_pci_mbxdma __P((struct ispsoftc *));
47 static int isp_pci_dmasetup __P((struct ispsoftc *, struct scsipi_xfer *,
48 ispreq_t *, u_int8_t *, u_int8_t));
49 static void isp_pci_dmateardown __P((struct ispsoftc *, struct scsipi_xfer *,
50 u_int32_t));
51 static void isp_pci_reset1 __P((struct ispsoftc *));
52 static void isp_pci_dumpregs __P((struct ispsoftc *));
53 static int isp_pci_intr __P((void *));
54
55 #ifndef ISP_DISABLE_1020_SUPPORT
56 static struct ispmdvec mdvec = {
57 isp_pci_rd_reg,
58 isp_pci_wr_reg,
59 isp_pci_mbxdma,
60 isp_pci_dmasetup,
61 isp_pci_dmateardown,
62 NULL,
63 isp_pci_reset1,
64 isp_pci_dumpregs,
65 ISP_RISC_CODE,
66 ISP_CODE_LENGTH,
67 ISP_CODE_ORG,
68 0,
69 BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64,
70 0
71 };
72 #endif
73
74 #ifndef ISP_DISABLE_1080_SUPPORT
75 static struct ispmdvec mdvec_1080 = {
76 isp_pci_rd_reg_1080,
77 isp_pci_wr_reg_1080,
78 isp_pci_mbxdma,
79 isp_pci_dmasetup,
80 isp_pci_dmateardown,
81 NULL,
82 isp_pci_reset1,
83 isp_pci_dumpregs,
84 ISP1080_RISC_CODE,
85 ISP1080_CODE_LENGTH,
86 ISP1080_CODE_ORG,
87 0,
88 BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64,
89 0
90 };
91 #endif
92
93 #ifndef ISP_DISABLE_2100_SUPPORT
94 static struct ispmdvec mdvec_2100 = {
95 isp_pci_rd_reg,
96 isp_pci_wr_reg,
97 isp_pci_mbxdma,
98 isp_pci_dmasetup,
99 isp_pci_dmateardown,
100 NULL,
101 isp_pci_reset1,
102 isp_pci_dumpregs,
103 ISP2100_RISC_CODE,
104 ISP2100_CODE_LENGTH,
105 ISP2100_CODE_ORG,
106 0,
107 0,
108 0
109 };
110 #endif
111
112 #ifndef ISP_DISABLE_2200_SUPPORT
113 static struct ispmdvec mdvec_2200 = {
114 isp_pci_rd_reg,
115 isp_pci_wr_reg,
116 isp_pci_mbxdma,
117 isp_pci_dmasetup,
118 isp_pci_dmateardown,
119 NULL,
120 isp_pci_reset1,
121 isp_pci_dumpregs,
122 ISP2200_RISC_CODE,
123 ISP2200_CODE_LENGTH,
124 ISP2200_CODE_ORG,
125 0,
126 0,
127 0
128 };
129 #endif
130
131 #ifndef PCI_VENDOR_QLOGIC
132 #define PCI_VENDOR_QLOGIC 0x1077
133 #endif
134
135 #ifndef PCI_PRODUCT_QLOGIC_ISP1020
136 #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020
137 #endif
138
139 #ifndef PCI_PRODUCT_QLOGIC_ISP1080
140 #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080
141 #endif
142
143 #ifndef PCI_PRODUCT_QLOGIC_ISP1240
144 #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240
145 #endif
146
147 #ifndef PCI_PRODUCT_QLOGIC_ISP2100
148 #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100
149 #endif
150
151 #ifndef PCI_PRODUCT_QLOGIC_ISP2200
152 #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200
153 #endif
154
155 #define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC)
156
157 #define PCI_QLOGIC_ISP1080 \
158 ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC)
159
160 #define PCI_QLOGIC_ISP1240 \
161 ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC)
162
163 #define PCI_QLOGIC_ISP2100 \
164 ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC)
165
166 #define PCI_QLOGIC_ISP2200 \
167 ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC)
168
169 #define IO_MAP_REG 0x10
170 #define MEM_MAP_REG 0x14
171 #define PCIR_ROMADDR 0x30
172
173 #define PCI_DFLT_LTNCY 0x40
174 #define PCI_DFLT_LNSZ 0x10
175
176
177 static int isp_pci_probe __P((struct device *, struct cfdata *, void *));
178 static void isp_pci_attach __P((struct device *, struct device *, void *));
179
180 struct isp_pcisoftc {
181 struct ispsoftc pci_isp;
182 pci_chipset_tag_t pci_pc;
183 pcitag_t pci_tag;
184 bus_space_tag_t pci_st;
185 bus_space_handle_t pci_sh;
186 bus_dma_tag_t pci_dmat;
187 bus_dmamap_t pci_scratch_dmap; /* for fcp only */
188 bus_dmamap_t pci_rquest_dmap;
189 bus_dmamap_t pci_result_dmap;
190 bus_dmamap_t *pci_xfer_dmap;
191 void * pci_ih;
192 int16_t pci_poff[_NREG_BLKS];
193 };
194
195 struct cfattach isp_pci_ca = {
196 sizeof (struct isp_pcisoftc), isp_pci_probe, isp_pci_attach
197 };
198
199 static int
200 isp_pci_probe(parent, match, aux)
201 struct device *parent;
202 struct cfdata *match;
203 void *aux;
204 {
205 struct pci_attach_args *pa = aux;
206 switch (pa->pa_id) {
207 #ifndef ISP_DISABLE_1020_SUPPORT
208 case PCI_QLOGIC_ISP:
209 return (1);
210 #endif
211 #ifndef ISP_DISABLE_1080_SUPPORT
212 case PCI_QLOGIC_ISP1080:
213 case PCI_QLOGIC_ISP1240:
214 return (1);
215 #endif
216 #ifndef ISP_DISABLE_2100_SUPPORT
217 case PCI_QLOGIC_ISP2100:
218 return (1);
219 #endif
220 #ifndef ISP_DISABLE_2200_SUPPORT
221 case PCI_QLOGIC_ISP2200:
222 return (1);
223 #endif
224 default:
225 return (0);
226 }
227 }
228
229
230 static void
231 isp_pci_attach(parent, self, aux)
232 struct device *parent, *self;
233 void *aux;
234 {
235 #ifdef DEBUG
236 static char oneshot = 1;
237 #endif
238 static char *nomem = "%s: no mem for sdparam table\n";
239 u_int32_t data, linesz = PCI_DFLT_LNSZ;
240 struct pci_attach_args *pa = aux;
241 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) self;
242 struct ispsoftc *isp = &pcs->pci_isp;
243 bus_space_tag_t st, iot, memt;
244 bus_space_handle_t sh, ioh, memh;
245 pci_intr_handle_t ih;
246 const char *intrstr;
247 int ioh_valid, memh_valid, i;
248 long foo;
249 ISP_LOCKVAL_DECL;
250
251 ioh_valid = (pci_mapreg_map(pa, IO_MAP_REG,
252 PCI_MAPREG_TYPE_IO, 0,
253 &iot, &ioh, NULL, NULL) == 0);
254 memh_valid = (pci_mapreg_map(pa, MEM_MAP_REG,
255 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
256 &memt, &memh, NULL, NULL) == 0);
257
258 if (memh_valid) {
259 st = memt;
260 sh = memh;
261 } else if (ioh_valid) {
262 st = iot;
263 sh = ioh;
264 } else {
265 printf(": unable to map device registers\n");
266 return;
267 }
268 printf("\n");
269
270 pcs->pci_st = st;
271 pcs->pci_sh = sh;
272 pcs->pci_dmat = pa->pa_dmat;
273 pcs->pci_pc = pa->pa_pc;
274 pcs->pci_tag = pa->pa_tag;
275 pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
276 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
277 pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
278 pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF;
279 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
280
281 #ifndef ISP_DISABLE_1020_SUPPORT
282 if (pa->pa_id == PCI_QLOGIC_ISP) {
283 isp->isp_mdvec = &mdvec;
284 isp->isp_type = ISP_HA_SCSI_UNKNOWN;
285 isp->isp_param = malloc(sizeof (sdparam), M_DEVBUF, M_NOWAIT);
286 if (isp->isp_param == NULL) {
287 printf(nomem, isp->isp_name);
288 return;
289 }
290 bzero(isp->isp_param, sizeof (sdparam));
291 }
292 #endif
293 #ifndef ISP_DISABLE_1080_SUPPORT
294 if (pa->pa_id == PCI_QLOGIC_ISP1080) {
295 isp->isp_mdvec = &mdvec_1080;
296 isp->isp_type = ISP_HA_SCSI_1080;
297 isp->isp_param = malloc(sizeof (sdparam), M_DEVBUF, M_NOWAIT);
298 if (isp->isp_param == NULL) {
299 printf(nomem, isp->isp_name);
300 return;
301 }
302 bzero(isp->isp_param, sizeof (sdparam));
303 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
304 ISP1080_DMA_REGS_OFF;
305 }
306 if (pa->pa_id == PCI_QLOGIC_ISP1240) {
307 isp->isp_mdvec = &mdvec_1080;
308 isp->isp_type = ISP_HA_SCSI_12X0;
309 isp->isp_param =
310 malloc(2 * sizeof (sdparam), M_DEVBUF, M_NOWAIT);
311 if (isp->isp_param == NULL) {
312 printf(nomem, isp->isp_name);
313 return;
314 }
315 bzero(isp->isp_param, 2 * sizeof (sdparam));
316 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
317 ISP1080_DMA_REGS_OFF;
318 }
319 #endif
320 #ifndef ISP_DISABLE_2100_SUPPORT
321 if (pa->pa_id == PCI_QLOGIC_ISP2100) {
322 isp->isp_mdvec = &mdvec_2100;
323 isp->isp_type = ISP_HA_FC_2100;
324 isp->isp_param = malloc(sizeof (fcparam), M_DEVBUF, M_NOWAIT);
325 if (isp->isp_param == NULL) {
326 printf(nomem, isp->isp_name);
327 return;
328 }
329 bzero(isp->isp_param, sizeof (fcparam));
330 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
331 PCI_MBOX_REGS2100_OFF;
332 data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG);
333 if ((data & 0xff) < 3) {
334 /*
335 * XXX: Need to get the actual revision
336 * XXX: number of the 2100 FB. At any rate,
337 * XXX: lower cache line size for early revision
338 * XXX; boards.
339 */
340 linesz = 1;
341 }
342 }
343 #endif
344 #ifndef ISP_DISABLE_2200_SUPPORT
345 if (pa->pa_id == PCI_QLOGIC_ISP2200) {
346 isp->isp_mdvec = &mdvec_2200;
347 isp->isp_type = ISP_HA_FC_2200;
348 isp->isp_param = malloc(sizeof (fcparam), M_DEVBUF, M_NOWAIT);
349 if (isp->isp_param == NULL) {
350 printf(nomem, isp->isp_name);
351 return;
352 }
353 bzero(isp->isp_param, sizeof (fcparam));
354 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
355 PCI_MBOX_REGS2100_OFF;
356 data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG);
357 }
358 #endif
359
360 /*
361 * Make sure that command register set sanely.
362 */
363 data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
364 data |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_INVALIDATE_ENABLE;
365
366 /*
367 * Not so sure about these- but I think it's important that they get
368 * enabled......
369 */
370 data |= PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE;
371 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, data);
372
373 /*
374 * Make sure that the latency timer, cache line size,
375 * and ROM is disabled.
376 */
377 data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
378 data &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
379 data &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT);
380 data |= (PCI_DFLT_LTNCY << PCI_LATTIMER_SHIFT);
381 data |= (linesz << PCI_CACHELINE_SHIFT);
382 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, data);
383
384 data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCIR_ROMADDR);
385 data &= ~1;
386 pci_conf_write(pa->pa_pc, pa->pa_tag, PCIR_ROMADDR, data);
387
388 #ifdef DEBUG
389 if (oneshot) {
390 oneshot = 0;
391 printf("Qlogic ISP Driver, NetBSD (pci) Platform Version "
392 "%d.%d Core Version %d.%d\n",
393 ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
394 ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
395 }
396 #endif
397 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
398 pa->pa_intrline, &ih)) {
399 printf("%s: couldn't map interrupt\n", isp->isp_name);
400 free(isp->isp_param, M_DEVBUF);
401 return;
402 }
403 intrstr = pci_intr_string(pa->pa_pc, ih);
404 if (intrstr == NULL)
405 intrstr = "<I dunno>";
406 pcs->pci_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
407 isp_pci_intr, isp);
408 if (pcs->pci_ih == NULL) {
409 printf("%s: couldn't establish interrupt at %s\n",
410 isp->isp_name, intrstr);
411 free(isp->isp_param, M_DEVBUF);
412 return;
413 }
414 printf("%s: interrupting at %s\n", isp->isp_name, intrstr);
415
416 if (IS_FC(isp)) {
417 /*
418 * This isn't very random, but it's the best we can do for
419 * the real edge case of cards that don't have WWNs.
420 */
421 foo = (long) isp;
422 foo >>= 4;
423 foo &= 0x7;
424 while (version[foo])
425 isp->isp_osinfo.seed += (int) version[foo++];
426 isp->isp_osinfo.seed <<= 8;
427 isp->isp_osinfo.seed += (isp->isp_osinfo._dev.dv_unit + 1);
428 }
429
430 ISP_LOCK(isp);
431 isp_reset(isp);
432 if (isp->isp_state != ISP_RESETSTATE) {
433 ISP_UNLOCK(isp);
434 free(isp->isp_param, M_DEVBUF);
435 return;
436 }
437 isp_init(isp);
438 if (isp->isp_state != ISP_INITSTATE) {
439 isp_uninit(isp);
440 ISP_UNLOCK(isp);
441 free(isp->isp_param, M_DEVBUF);
442 return;
443 }
444
445
446
447 /*
448 * Create the DMA maps for the data transfers.
449 */
450 for (i = 0; i < isp->isp_maxcmds; i++) {
451 if (bus_dmamap_create(pcs->pci_dmat, MAXPHYS,
452 (MAXPHYS / NBPG) + 1, MAXPHYS, 0, BUS_DMA_NOWAIT,
453 &pcs->pci_xfer_dmap[i])) {
454 printf("%s: can't create dma maps\n",
455 isp->isp_name);
456 isp_uninit(isp);
457 ISP_UNLOCK(isp);
458 return;
459 }
460 }
461 /*
462 * Do Generic attach now.
463 */
464 isp_attach(isp);
465 if (isp->isp_state != ISP_RUNSTATE) {
466 isp_uninit(isp);
467 free(isp->isp_param, M_DEVBUF);
468 }
469 ISP_UNLOCK(isp);
470 }
471
472 static u_int16_t
473 isp_pci_rd_reg(isp, regoff)
474 struct ispsoftc *isp;
475 int regoff;
476 {
477 u_int16_t rv;
478 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
479 int offset, oldconf = 0;
480
481 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
482 /*
483 * We will assume that someone has paused the RISC processor.
484 */
485 oldconf = isp_pci_rd_reg(isp, BIU_CONF1);
486 isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP);
487 }
488 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
489 offset += (regoff & 0xff);
490 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset);
491 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
492 isp_pci_wr_reg(isp, BIU_CONF1, oldconf);
493 }
494 return (rv);
495 }
496
497 static void
498 isp_pci_wr_reg(isp, regoff, val)
499 struct ispsoftc *isp;
500 int regoff;
501 u_int16_t val;
502 {
503 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
504 int offset, oldconf = 0;
505
506 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
507 /*
508 * We will assume that someone has paused the RISC processor.
509 */
510 oldconf = isp_pci_rd_reg(isp, BIU_CONF1);
511 isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP);
512 }
513 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
514 offset += (regoff & 0xff);
515 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val);
516 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
517 isp_pci_wr_reg(isp, BIU_CONF1, oldconf);
518 }
519 }
520
521 #ifndef ISP_DISABLE_1080_SUPPORT
522 static u_int16_t
523 isp_pci_rd_reg_1080(isp, regoff)
524 struct ispsoftc *isp;
525 int regoff;
526 {
527 u_int16_t rv;
528 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
529 int offset, oc = 0;
530
531 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
532 /*
533 * We will assume that someone has paused the RISC processor.
534 */
535 oc = isp_pci_rd_reg(isp, BIU_CONF1);
536 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP);
537 } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
538 oc = isp_pci_rd_reg(isp, BIU_CONF1);
539 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA);
540 }
541 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
542 offset += (regoff & 0xff);
543 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset);
544 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
545 ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) {
546 isp_pci_wr_reg(isp, BIU_CONF1, oc);
547 }
548 return (rv);
549 }
550
551 static void
552 isp_pci_wr_reg_1080(isp, regoff, val)
553 struct ispsoftc *isp;
554 int regoff;
555 u_int16_t val;
556 {
557 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
558 int offset, oc = 0;
559
560 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
561 /*
562 * We will assume that someone has paused the RISC processor.
563 */
564 oc = isp_pci_rd_reg(isp, BIU_CONF1);
565 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_SXP);
566 } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
567 oc = isp_pci_rd_reg(isp, BIU_CONF1);
568 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA);
569 }
570 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
571 offset += (regoff & 0xff);
572 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val);
573 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
574 ((regoff & _BLK_REG_MASK) == DMA_BLOCK)) {
575 isp_pci_wr_reg(isp, BIU_CONF1, oc);
576 }
577 }
578 #endif
579
580 static int
581 isp_pci_mbxdma(isp)
582 struct ispsoftc *isp;
583 {
584 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
585 bus_dma_segment_t seg;
586 bus_size_t len;
587 fcparam *fcp;
588 int rseg;
589
590 if (isp->isp_rquest_dma) /* been here before? */
591 return (0);
592
593 len = isp->isp_maxcmds * sizeof (ISP_SCSI_XFER_T);
594 isp->isp_xflist = (ISP_SCSI_XFER_T **) malloc(len, M_DEVBUF, M_WAITOK);
595 if (isp->isp_xflist == NULL) {
596 printf("%s: cannot malloc xflist array\n", isp->isp_name);
597 return (1);
598 }
599 bzero(isp->isp_xflist, len);
600 len = isp->isp_maxcmds * sizeof (bus_dmamap_t);
601 pci->pci_xfer_dmap = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK);
602 if (pci->pci_xfer_dmap == NULL) {
603 printf("%s: cannot malloc xflist array\n", isp->isp_name);
604 return (1);
605 }
606
607 /*
608 * Allocate and map the request queue.
609 */
610 len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN);
611 if (bus_dmamem_alloc(pci->pci_dmat, len, NBPG, 0, &seg, 1, &rseg,
612 BUS_DMA_NOWAIT) || bus_dmamem_map(pci->pci_dmat, &seg, rseg, len,
613 (caddr_t *)&isp->isp_rquest, BUS_DMA_NOWAIT|BUS_DMA_COHERENT))
614 return (1);
615 if (bus_dmamap_create(pci->pci_dmat, len, 1, len, 0, BUS_DMA_NOWAIT,
616 &pci->pci_rquest_dmap) || bus_dmamap_load(pci->pci_dmat,
617 pci->pci_rquest_dmap, (caddr_t)isp->isp_rquest, len, NULL,
618 BUS_DMA_NOWAIT))
619 return (1);
620
621 isp->isp_rquest_dma = pci->pci_rquest_dmap->dm_segs[0].ds_addr;
622
623 /*
624 * Allocate and map the result queue.
625 */
626 len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN);
627 if (bus_dmamem_alloc(pci->pci_dmat, len, NBPG, 0, &seg, 1, &rseg,
628 BUS_DMA_NOWAIT) || bus_dmamem_map(pci->pci_dmat, &seg, rseg, len,
629 (caddr_t *)&isp->isp_result, BUS_DMA_NOWAIT|BUS_DMA_COHERENT))
630 return (1);
631 if (bus_dmamap_create(pci->pci_dmat, len, 1, len, 0, BUS_DMA_NOWAIT,
632 &pci->pci_result_dmap) || bus_dmamap_load(pci->pci_dmat,
633 pci->pci_result_dmap, (caddr_t)isp->isp_result, len, NULL,
634 BUS_DMA_NOWAIT))
635 return (1);
636 isp->isp_result_dma = pci->pci_result_dmap->dm_segs[0].ds_addr;
637
638 if (IS_SCSI(isp)) {
639 return (0);
640 }
641
642 fcp = isp->isp_param;
643 len = ISP2100_SCRLEN;
644 if (bus_dmamem_alloc(pci->pci_dmat, len, NBPG, 0, &seg, 1, &rseg,
645 BUS_DMA_NOWAIT) || bus_dmamem_map(pci->pci_dmat, &seg, rseg, len,
646 (caddr_t *)&fcp->isp_scratch, BUS_DMA_NOWAIT|BUS_DMA_COHERENT))
647 return (1);
648 if (bus_dmamap_create(pci->pci_dmat, len, 1, len, 0, BUS_DMA_NOWAIT,
649 &pci->pci_scratch_dmap) || bus_dmamap_load(pci->pci_dmat,
650 pci->pci_scratch_dmap, (caddr_t)fcp->isp_scratch, len, NULL,
651 BUS_DMA_NOWAIT))
652 return (1);
653 fcp->isp_scdma = pci->pci_scratch_dmap->dm_segs[0].ds_addr;
654 return (0);
655 }
656
657 static int
658 isp_pci_dmasetup(isp, xs, rq, iptrp, optr)
659 struct ispsoftc *isp;
660 struct scsipi_xfer *xs;
661 ispreq_t *rq;
662 u_int8_t *iptrp;
663 u_int8_t optr;
664 {
665 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
666 bus_dmamap_t dmap = pci->pci_xfer_dmap[rq->req_handle - 1];
667 ispcontreq_t *crq;
668 int segcnt, seg, error, ovseg, seglim, drq;
669
670 if (xs->datalen == 0) {
671 rq->req_seg_count = 1;
672 goto mbxsync;
673 }
674 assert(rq->req_handle != 0 && rq->req_handle <= isp->isp_maxcmds);
675 if (xs->xs_control & XS_CTL_DATA_IN) {
676 drq = REQFLAG_DATA_IN;
677 } else {
678 drq = REQFLAG_DATA_OUT;
679 }
680
681 if (IS_FC(isp)) {
682 seglim = ISP_RQDSEG_T2;
683 ((ispreqt2_t *)rq)->req_totalcnt = xs->datalen;
684 ((ispreqt2_t *)rq)->req_flags |= drq;
685 } else {
686 seglim = ISP_RQDSEG;
687 rq->req_flags |= drq;
688 }
689 error = bus_dmamap_load(pci->pci_dmat, dmap, xs->data, xs->datalen,
690 NULL, xs->xs_control & XS_CTL_NOSLEEP ?
691 BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
692 if (error) {
693 XS_SETERR(xs, HBA_BOTCH);
694 return (CMD_COMPLETE);
695 }
696
697 segcnt = dmap->dm_nsegs;
698
699 for (seg = 0, rq->req_seg_count = 0;
700 seg < segcnt && rq->req_seg_count < seglim;
701 seg++, rq->req_seg_count++) {
702 if (IS_FC(isp)) {
703 ispreqt2_t *rq2 = (ispreqt2_t *)rq;
704 rq2->req_dataseg[rq2->req_seg_count].ds_count =
705 dmap->dm_segs[seg].ds_len;
706 rq2->req_dataseg[rq2->req_seg_count].ds_base =
707 dmap->dm_segs[seg].ds_addr;
708 } else {
709 rq->req_dataseg[rq->req_seg_count].ds_count =
710 dmap->dm_segs[seg].ds_len;
711 rq->req_dataseg[rq->req_seg_count].ds_base =
712 dmap->dm_segs[seg].ds_addr;
713 }
714 }
715
716 if (seg == segcnt)
717 goto dmasync;
718
719 do {
720 crq = (ispcontreq_t *)
721 ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp);
722 *iptrp = (*iptrp + 1) & (RQUEST_QUEUE_LEN - 1);
723 if (*iptrp == optr) {
724 printf("%s: Request Queue Overflow++\n", isp->isp_name);
725 bus_dmamap_unload(pci->pci_dmat, dmap);
726 XS_SETERR(xs, HBA_BOTCH);
727 return (CMD_COMPLETE);
728 }
729 rq->req_header.rqs_entry_count++;
730 bzero((void *)crq, sizeof (*crq));
731 crq->req_header.rqs_entry_count = 1;
732 crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
733
734 for (ovseg = 0; seg < segcnt && ovseg < ISP_CDSEG;
735 rq->req_seg_count++, seg++, ovseg++) {
736 crq->req_dataseg[ovseg].ds_count =
737 dmap->dm_segs[seg].ds_len;
738 crq->req_dataseg[ovseg].ds_base =
739 dmap->dm_segs[seg].ds_addr;
740 }
741 } while (seg < segcnt);
742
743 dmasync:
744 bus_dmamap_sync(pci->pci_dmat, dmap, 0, dmap->dm_mapsize,
745 (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
746 BUS_DMASYNC_PREWRITE);
747
748 mbxsync:
749 ISP_SWIZZLE_REQUEST(isp, rq);
750 bus_dmamap_sync(pci->pci_dmat, pci->pci_rquest_dmap, 0,
751 pci->pci_rquest_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
752 return (CMD_QUEUED);
753 }
754
755 static int
756 isp_pci_intr(arg)
757 void *arg;
758 {
759 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)arg;
760 bus_dmamap_sync(pci->pci_dmat, pci->pci_result_dmap, 0,
761 pci->pci_result_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
762 return (isp_intr(arg));
763 }
764
765 static void
766 isp_pci_dmateardown(isp, xs, handle)
767 struct ispsoftc *isp;
768 struct scsipi_xfer *xs;
769 u_int32_t handle;
770 {
771 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
772 bus_dmamap_t dmap;
773 assert(handle != 0 && handle <= isp->isp_maxcmds);
774 dmap = pci->pci_xfer_dmap[handle-1];
775 bus_dmamap_sync(pci->pci_dmat, dmap, 0, dmap->dm_mapsize,
776 xs->xs_control & XS_CTL_DATA_IN ?
777 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
778 bus_dmamap_unload(pci->pci_dmat, dmap);
779 }
780
781 static void
782 isp_pci_reset1(isp)
783 struct ispsoftc *isp;
784 {
785 /* Make sure the BIOS is disabled */
786 isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
787 }
788
789 static void
790 isp_pci_dumpregs(isp)
791 struct ispsoftc *isp;
792 {
793 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
794 printf("%s: PCI Status Command/Status=%x\n", pci->pci_isp.isp_name,
795 pci_conf_read(pci->pci_pc, pci->pci_tag, PCI_COMMAND_STATUS_REG));
796 }
797