FreeBSD/Linux Kernel Cross Reference
sys/pci/isp_pci.c
1 /* $FreeBSD: src/sys/pci/isp_pci.c,v 1.24.2.6 2000/03/04 06:04:42 mjacob Exp $ */
2 /*
3 * PCI specific probe and attach routines for Qlogic ISP SCSI adapters.
4 * FreeBSD 2.X Version.
5 *
6 *---------------------------------------
7 * Copyright (c) 1997, 1998, 1999, 2000 by Matthew Jacob
8 * NASA/Ames Research Center
9 * All rights reserved.
10 *---------------------------------------
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice immediately at the beginning of the file, without modification,
17 * this list of conditions, and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
28 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36 #include <dev/isp/isp_freebsd.h>
37 #include <dev/isp/asm_pci.h>
38 #include <sys/malloc.h>
39 #include <vm/vm.h>
40 #include <vm/pmap.h>
41 #include <vm/vm_extern.h>
42
43
44 #include <pci/pcireg.h>
45 #include <pci/pcivar.h>
46
47 static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int));
48 static void isp_pci_wr_reg __P((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 __P((struct ispsoftc *, int));
51 static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t));
52 #endif
53 static int isp_pci_mbxdma __P((struct ispsoftc *));
54 static int isp_pci_dmasetup __P((struct ispsoftc *, ISP_SCSI_XFER_T *,
55 ispreq_t *, u_int16_t *, u_int16_t));
56 typedef u_int16_t pci_port_t;
57
58 static void isp_pci_reset1 __P((struct ispsoftc *));
59 static void isp_pci_dumpregs __P((struct ispsoftc *));
60
61 #ifndef ISP_CODE_ORG
62 #define ISP_CODE_ORG 0x1000
63 #endif
64 #ifndef ISP_1040_RISC_CODE
65 #define ISP_1040_RISC_CODE NULL
66 #endif
67 #ifndef ISP_1080_RISC_CODE
68 #define ISP_1080_RISC_CODE NULL
69 #endif
70 #ifndef ISP_12160_RISC_CODE
71 #define ISP_12160_RISC_CODE NULL
72 #endif
73 #ifndef ISP_2100_RISC_CODE
74 #define ISP_2100_RISC_CODE NULL
75 #endif
76 #ifndef ISP_2200_RISC_CODE
77 #define ISP_2200_RISC_CODE NULL
78 #endif
79
80 #ifndef ISP_DISABLE_1020_SUPPORT
81 static struct ispmdvec mdvec = {
82 isp_pci_rd_reg,
83 isp_pci_wr_reg,
84 isp_pci_mbxdma,
85 isp_pci_dmasetup,
86 NULL,
87 NULL,
88 isp_pci_reset1,
89 isp_pci_dumpregs,
90 ISP_1040_RISC_CODE,
91 0,
92 ISP_CODE_ORG,
93 0,
94 BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64,
95 0
96 };
97 #endif
98
99 #ifndef ISP_DISABLE_1080_SUPPORT
100 static struct ispmdvec mdvec_1080 = {
101 isp_pci_rd_reg_1080,
102 isp_pci_wr_reg_1080,
103 isp_pci_mbxdma,
104 isp_pci_dmasetup,
105 NULL,
106 NULL,
107 isp_pci_reset1,
108 isp_pci_dumpregs,
109 ISP_1080_RISC_CODE,
110 0,
111 ISP_CODE_ORG,
112 0,
113 BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64,
114 0
115 };
116 #endif
117
118 #ifndef ISP_DISABLE_12160_SUPPORT
119 static struct ispmdvec mdvec_12160 = {
120 isp_pci_rd_reg_1080,
121 isp_pci_wr_reg_1080,
122 isp_pci_mbxdma,
123 isp_pci_dmasetup,
124 NULL,
125 NULL,
126 isp_pci_reset1,
127 isp_pci_dumpregs,
128 ISP_12160_RISC_CODE,
129 0,
130 ISP_CODE_ORG,
131 0,
132 BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64,
133 0
134 };
135 #endif
136
137 #ifndef ISP_DISABLE_2100_SUPPORT
138 static struct ispmdvec mdvec_2100 = {
139 isp_pci_rd_reg,
140 isp_pci_wr_reg,
141 isp_pci_mbxdma,
142 isp_pci_dmasetup,
143 NULL,
144 NULL,
145 isp_pci_reset1,
146 isp_pci_dumpregs,
147 ISP_2100_RISC_CODE,
148 0,
149 ISP_CODE_ORG,
150 0,
151 0, /* Irrelevant to the 2100 */
152 0
153 };
154 #endif
155
156 #ifndef ISP_DISABLE_2200_SUPPORT
157 static struct ispmdvec mdvec_2200 = {
158 isp_pci_rd_reg,
159 isp_pci_wr_reg,
160 isp_pci_mbxdma,
161 isp_pci_dmasetup,
162 NULL,
163 NULL,
164 isp_pci_reset1,
165 isp_pci_dumpregs,
166 ISP_2200_RISC_CODE,
167 0,
168 ISP_CODE_ORG,
169 0,
170 0,
171 0
172 };
173 #endif
174
175 #ifndef SCSI_ISP_PREFER_MEM_MAP
176 #ifdef __alpha__
177 #define SCSI_ISP_PREFER_MEM_MAP 0
178 #else
179 #define SCSI_ISP_PREFER_MEM_MAP 1
180 #endif
181 #endif
182
183 #ifndef PCIM_CMD_INVEN
184 #define PCIM_CMD_INVEN 0x10
185 #endif
186 #ifndef PCIM_CMD_BUSMASTEREN
187 #define PCIM_CMD_BUSMASTEREN 0x0004
188 #endif
189 #ifndef PCIM_CMD_PERRESPEN
190 #define PCIM_CMD_PERRESPEN 0x0040
191 #endif
192 #ifndef PCIM_CMD_SEREN
193 #define PCIM_CMD_SEREN 0x0100
194 #endif
195
196 #ifndef PCIR_COMMAND
197 #define PCIR_COMMAND 0x04
198 #endif
199
200 #ifndef PCIR_CACHELNSZ
201 #define PCIR_CACHELNSZ 0x0c
202 #endif
203
204 #ifndef PCIR_LATTIMER
205 #define PCIR_LATTIMER 0x0d
206 #endif
207
208 #ifndef PCIR_ROMADDR
209 #define PCIR_ROMADDR 0x30
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_ISP12160
233 #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216
234 #endif
235
236 #ifndef PCI_PRODUCT_QLOGIC_ISP2100
237 #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100
238 #endif
239
240 #ifndef PCI_PRODUCT_QLOGIC_ISP2200
241 #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200
242 #endif
243
244 #define PCI_QLOGIC_ISP ((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC)
245
246 #define PCI_QLOGIC_ISP1080 \
247 ((PCI_PRODUCT_QLOGIC_ISP1080 << 16) | PCI_VENDOR_QLOGIC)
248
249 #define PCI_QLOGIC_ISP1240 \
250 ((PCI_PRODUCT_QLOGIC_ISP1240 << 16) | PCI_VENDOR_QLOGIC)
251
252 #define PCI_QLOGIC_ISP12160 \
253 ((PCI_PRODUCT_QLOGIC_ISP12160 << 16) | PCI_VENDOR_QLOGIC)
254
255 #define PCI_QLOGIC_ISP1280 \
256 ((PCI_PRODUCT_QLOGIC_ISP1280 << 16) | PCI_VENDOR_QLOGIC)
257
258 #define PCI_QLOGIC_ISP2100 \
259 ((PCI_PRODUCT_QLOGIC_ISP2100 << 16) | PCI_VENDOR_QLOGIC)
260
261 #define PCI_QLOGIC_ISP2200 \
262 ((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC)
263
264 #define IO_MAP_REG 0x10
265 #define MEM_MAP_REG 0x14
266
267 #define PCI_DFLT_LTNCY 0x40
268 #define PCI_DFLT_LNSZ 0x10
269
270 static char *isp_pci_probe __P((pcici_t tag, pcidi_t type));
271 static void isp_pci_attach __P((pcici_t config_d, int unit));
272
273 /* This distinguishing define is not right, but it does work */
274
275 #define IO_SPACE_MAPPING 0
276 #define MEM_SPACE_MAPPING 1
277 typedef int bus_space_tag_t;
278 typedef u_long bus_space_handle_t;
279 typedef unsigned int __uintptr_t;
280 typedef __uintptr_t uintptr_t;
281 #ifdef __alpha__
282 #define bus_space_read_2(st, sh, offset) \
283 alpha_mb(),
284 (st == IO_SPACE_MAPPING)? \
285 inw((pci_port_t)sh + offset) : readw((pci_port_t)sh + offset)
286 #define bus_space_write_2(st, sh, offset, val) \
287 ((st == IO_SPACE_MAPPING)? outw((pci_port_t)sh + offset, val) : \
288 writew((pci_port_t)sh + offset, val)), alpha_mb()
289 #else
290 #define bus_space_read_2(st, sh, offset) \
291 (st == IO_SPACE_MAPPING)? \
292 inw((pci_port_t)sh + offset) : *((u_int16_t *)(uintptr_t)sh)
293 #define bus_space_write_2(st, sh, offset, val) \
294 if (st == IO_SPACE_MAPPING) outw((pci_port_t)sh + offset, val); else \
295 *((u_int16_t *)(uintptr_t)sh) = val
296 #endif
297
298 struct isp_pcisoftc {
299 struct ispsoftc pci_isp;
300 pcici_t pci_id;
301 bus_space_tag_t pci_st;
302 bus_space_handle_t pci_sh;
303 int16_t pci_poff[_NREG_BLKS];
304 };
305
306 static u_long ispunit;
307
308 static struct pci_device isp_pci_driver = {
309 "isp",
310 isp_pci_probe,
311 isp_pci_attach,
312 &ispunit,
313 NULL
314 };
315 DATA_SET (pcidevice_set, isp_pci_driver);
316
317
318 static char *
319 isp_pci_probe(pcici_t tag, pcidi_t type)
320 {
321 static int oneshot = 1;
322 char *x;
323
324 switch (type) {
325 #ifndef ISP_DISABLE_1020_SUPPORT
326 case PCI_QLOGIC_ISP:
327 x = "Qlogic ISP 1020/1040 PCI SCSI Adapter";
328 break;
329 #endif
330 #ifndef ISP_DISABLE_1080_SUPPORT
331 case PCI_QLOGIC_ISP1080:
332 x = "Qlogic ISP 1080 PCI SCSI Adapter";
333 break;
334 case PCI_QLOGIC_ISP1240:
335 x = "Qlogic ISP 1240 PCI SCSI Adapter";
336 break;
337 case PCI_QLOGIC_ISP1280:
338 x = "Qlogic ISP 1280 PCI SCSI Adapter";
339 break;
340 #endif
341 #ifndef ISP_DISABLE_12160_SUPPORT
342 case PCI_QLOGIC_ISP12160:
343 x = "Qlogic ISP 12160 PCI SCSI Adapter";
344 break;
345 #endif
346 #ifndef ISP_DISABLE_2100_SUPPORT
347 case PCI_QLOGIC_ISP2100:
348 x = "Qlogic ISP 2100 PCI FC-AL Adapter";
349 break;
350 #endif
351 #ifndef ISP_DISABLE_2200_SUPPORT
352 case PCI_QLOGIC_ISP2200:
353 x = "Qlogic ISP 2200 PCI FC-AL Adapter";
354 break;
355 #endif
356 default:
357 return (NULL);
358 }
359 if (oneshot) {
360 oneshot = 0;
361 printf("Qlogic ISP Driver, FreeBSD Version %d.%d, "
362 "Core Version %d.%d\n",
363 ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
364 ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
365 }
366 return (x);
367 }
368
369
370 #if SCSI_ISP_PREFER_MEM_MAP == 1
371 #define prefer_mem_map 1
372 #else
373 #define prefer_mem_map 0
374 #endif
375
376 static void
377 isp_pci_attach(pcici_t cfid, int unit)
378 {
379 int mapped;
380 pci_port_t io_port;
381 u_int32_t data, rev, linesz, psize, basetype;
382 struct isp_pcisoftc *pcs;
383 struct ispsoftc *isp;
384 vm_offset_t vaddr, paddr;
385 struct ispmdvec *mdvp;
386 long i;
387 ISP_LOCKVAL_DECL;
388
389
390 pcs = malloc(sizeof (struct isp_pcisoftc), M_DEVBUF, M_NOWAIT);
391 if (pcs == NULL) {
392 printf("isp%d: cannot allocate softc\n", unit);
393 return;
394 }
395 bzero(pcs, sizeof (struct isp_pcisoftc));
396
397 /*
398 * Figure out which we should try first - memory mapping or i/o mapping?
399 */
400
401 vaddr = paddr = NULL;
402 mapped = 0;
403 linesz = PCI_DFLT_LNSZ;
404
405 /*
406 * Note that pci_conf_read is a 32 bit word aligned function.
407 */
408 data = pci_conf_read(cfid, PCIR_COMMAND);
409 if (prefer_mem_map) {
410 if (data & PCI_COMMAND_MEM_ENABLE) {
411 if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) {
412 pcs->pci_st = MEM_SPACE_MAPPING;
413 pcs->pci_sh = vaddr;
414 mapped++;
415 }
416 }
417 if (mapped == 0 && (data & PCI_COMMAND_IO_ENABLE)) {
418 if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) {
419 pcs->pci_st = IO_SPACE_MAPPING;
420 pcs->pci_sh = io_port;
421 mapped++;
422 }
423 }
424 } else {
425 if (data & PCI_COMMAND_IO_ENABLE) {
426 if (pci_map_port(cfid, PCI_MAP_REG_START, &io_port)) {
427 pcs->pci_st = IO_SPACE_MAPPING;
428 pcs->pci_sh = io_port;
429 mapped++;
430 }
431 }
432 if (mapped == 0 && (data & PCI_COMMAND_MEM_ENABLE)) {
433 if (pci_map_mem(cfid, MEM_MAP_REG, &vaddr, &paddr)) {
434 pcs->pci_st = MEM_SPACE_MAPPING;
435 pcs->pci_sh = vaddr;
436 mapped++;
437 }
438 }
439 }
440 if (mapped == 0) {
441 printf("isp%d: unable to map any ports!\n", unit);
442 free(pcs, M_DEVBUF);
443 return;
444 }
445 if (bootverbose)
446 printf("isp%d: using %s space register mapping\n", unit,
447 pcs->pci_st == IO_SPACE_MAPPING? "I/O" : "Memory");
448
449 data = pci_conf_read(cfid, PCI_ID_REG);
450 rev = pci_conf_read(cfid, PCI_CLASS_REG) & 0xff; /* revision */
451 pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
452 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
453 pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
454 pcs->pci_poff[RISC_BLOCK >> _BLK_REG_SHFT] = PCI_RISC_REGS_OFF;
455 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
456 /*
457 * GCC!
458 */
459 mdvp = &mdvec;
460 basetype = ISP_HA_SCSI_UNKNOWN;
461 psize = sizeof (sdparam);
462 #ifndef ISP_DISABLE_1020_SUPPORT
463 if (data == PCI_QLOGIC_ISP) {
464 mdvp = &mdvec;
465 basetype = ISP_HA_SCSI_UNKNOWN;
466 psize = sizeof (sdparam);
467 }
468 #endif
469 #ifndef ISP_DISABLE_1080_SUPPORT
470 if (data == PCI_QLOGIC_ISP1080) {
471 mdvp = &mdvec_1080;
472 basetype = ISP_HA_SCSI_1080;
473 psize = sizeof (sdparam);
474 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
475 ISP1080_DMA_REGS_OFF;
476 }
477 if (data == PCI_QLOGIC_ISP1240) {
478 mdvp = &mdvec_1080;
479 basetype = ISP_HA_SCSI_1240;
480 psize = 2 * sizeof (sdparam);
481 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
482 ISP1080_DMA_REGS_OFF;
483 }
484 if (data == PCI_QLOGIC_ISP1280) {
485 mdvp = &mdvec_1080;
486 basetype = ISP_HA_SCSI_1280;
487 psize = 2 * sizeof (sdparam);
488 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
489 ISP1080_DMA_REGS_OFF;
490 }
491 #endif
492 #ifndef ISP_DISABLE_12160_SUPPORT
493 if (data == PCI_QLOGIC_ISP12160) {
494 mdvp = &mdvec_1080;
495 basetype = ISP_HA_SCSI_12160;
496 psize = 2 * sizeof (sdparam);
497 pcs->pci_poff[DMA_BLOCK >> _BLK_REG_SHFT] =
498 ISP1080_DMA_REGS_OFF;
499 }
500 #endif
501 #ifndef ISP_DISABLE_2100_SUPPORT
502 if (data == PCI_QLOGIC_ISP2100) {
503 mdvp = &mdvec_2100;
504 basetype = ISP_HA_FC_2100;
505 psize = sizeof (fcparam);
506 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
507 PCI_MBOX_REGS2100_OFF;
508 if (rev < 3) {
509 /*
510 * XXX: Need to get the actual revision
511 * XXX: number of the 2100 FB. At any rate,
512 * XXX: lower cache line size for early revision
513 * XXX; boards.
514 */
515 linesz = 1;
516 }
517 }
518 #endif
519 #ifndef ISP_DISABLE_2200_SUPPORT
520 if (data == PCI_QLOGIC_ISP2200) {
521 mdvp = &mdvec_2200;
522 basetype = ISP_HA_FC_2200;
523 psize = sizeof (fcparam);
524 pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
525 PCI_MBOX_REGS2100_OFF;
526 }
527 #endif
528 isp = &pcs->pci_isp;
529 isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT);
530 if (isp->isp_param == NULL) {
531 printf("isp%d: cannot allocate parameter data\n", unit);
532 return;
533 }
534 bzero(isp->isp_param, psize);
535 isp->isp_mdvec = mdvp;
536 isp->isp_type = basetype;
537 isp->isp_revision = rev;
538 (void) sprintf(isp->isp_name, "isp%d", unit);
539 isp->isp_osinfo.unit = unit;
540 /*
541 * poor man's attempt at pseudo randomness.
542 */
543 i = (long) isp;
544 i >>= 5;
545 i &= 0x7;
546 /*
547 * This isn't very random, but it's the best we can do for
548 * the real edge case of cards that don't have WWNs.
549 */
550 isp->isp_osinfo.seed += ((int) cfid.tag);
551 while (version[i])
552 isp->isp_osinfo.seed += (int) version[i++];
553 isp->isp_osinfo.seed <<= 8;
554 isp->isp_osinfo.seed += (unit + 1);
555
556 ISP_LOCK(isp);
557 data = pci_conf_read(cfid, PCIR_COMMAND);
558 data |= PCIM_CMD_SEREN |
559 PCIM_CMD_PERRESPEN |
560 PCIM_CMD_BUSMASTEREN |
561 PCIM_CMD_INVEN;
562 pci_conf_write(cfid, PCIR_COMMAND, data);
563 data = pci_conf_read(cfid, PCIR_CACHELNSZ);
564 if ((data & ~0xffff) != ((PCI_DFLT_LTNCY << 8) | linesz)) {
565 data &= ~0xffff;
566 data |= (PCI_DFLT_LTNCY << 8) | linesz;
567 pci_conf_write(cfid, PCIR_CACHELNSZ, data);
568 CFGPRINTF("%s: set PCI line size to %d\n",
569 isp->isp_name, linesz);
570 CFGPRINTF("%s: set PCI latency to %d\n", isp->isp_name,
571 PCI_DFLT_LTNCY);
572 }
573
574 /*
575 * Make sure we've disabled the ROM.
576 */
577 data = pci_conf_read(cfid, PCIR_ROMADDR);
578 data &= ~1;
579 pci_conf_write(cfid, PCIR_ROMADDR, data);
580 ISP_UNLOCK(isp);
581 if (pci_map_int(cfid, (void (*)(void *))isp_intr,
582 (void *)isp, &IMASK) == 0) {
583 printf("%s: could not map interrupt\n", isp->isp_name);
584 free(pcs, M_DEVBUF);
585 return;
586 }
587
588 pcs->pci_id = cfid;
589 #ifdef SCSI_ISP_NO_FWLOAD_MASK
590 if (SCSI_ISP_NO_FWLOAD_MASK && (SCSI_ISP_NO_FWLOAD_MASK & (1 << unit)))
591 isp->isp_confopts |= ISP_CFG_NORELOAD;
592 #endif
593 #ifdef SCSI_ISP_NO_NVRAM_MASK
594 if (SCSI_ISP_NO_NVRAM_MASK && (SCSI_ISP_NO_NVRAM_MASK & (1 << unit))) {
595 printf("%s: ignoring NVRAM\n", isp->isp_name);
596 isp->isp_confopts |= ISP_CFG_NONVRAM;
597 }
598 #endif
599 #ifdef SCSI_ISP_FCDUPLEX
600 if (IS_FC(isp)) {
601 if (SCSI_ISP_FCDUPLEX && (SCSI_ISP_FCDUPLEX & (1 << unit))) {
602 isp->isp_confopts |= ISP_CFG_FULL_DUPLEX;
603 }
604 }
605 #endif
606 ISP_LOCK(isp);
607 isp_reset(isp);
608 if (isp->isp_state != ISP_RESETSTATE) {
609 (void) pci_unmap_int(cfid);
610 ISP_UNLOCK(isp);
611 free(pcs, M_DEVBUF);
612 return;
613 }
614 isp_init(isp);
615 if (isp->isp_state != ISP_INITSTATE) {
616 /* If we're a Fibre Channel Card, we allow deferred attach */
617 if (IS_SCSI(isp)) {
618 isp_uninit(isp);
619 (void) pci_unmap_int(cfid); /* Does nothing */
620 ISP_UNLOCK(isp);
621 free(pcs, M_DEVBUF);
622 return;
623 }
624 }
625 isp_attach(isp);
626 if (isp->isp_state != ISP_RUNSTATE) {
627 /* If we're a Fibre Channel Card, we allow deferred attach */
628 if (IS_SCSI(isp)) {
629 isp_uninit(isp);
630 (void) pci_unmap_int(cfid); /* Does nothing */
631 ISP_UNLOCK(isp);
632 free(pcs, M_DEVBUF);
633 return;
634 }
635 }
636 ISP_UNLOCK(isp);
637 #ifdef __alpha__
638 /*
639 * THIS SHOULD NOT HAVE TO BE HERE
640 */
641 alpha_register_pci_scsi(cfid->bus, cfid->slot, isp->isp_sim);
642 #endif
643 }
644
645 static u_int16_t
646 isp_pci_rd_reg(struct ispsoftc *isp, int regoff)
647 {
648 u_int16_t rv;
649 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
650 int offset, oldconf = 0;
651
652 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
653 /*
654 * We will assume that someone has paused the RISC processor.
655 */
656 oldconf = isp_pci_rd_reg(isp, BIU_CONF1);
657 isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP);
658 }
659 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
660 offset += (regoff & 0xff);
661 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset);
662 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
663 isp_pci_wr_reg(isp, BIU_CONF1, oldconf);
664 }
665 return (rv);
666 }
667
668 static void
669 isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val)
670 {
671 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
672 int offset, oldconf = 0;
673
674 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
675 /*
676 * We will assume that someone has paused the RISC processor.
677 */
678 oldconf = isp_pci_rd_reg(isp, BIU_CONF1);
679 isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP);
680 }
681 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
682 offset += (regoff & 0xff);
683 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val);
684 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
685 isp_pci_wr_reg(isp, BIU_CONF1, oldconf);
686 }
687 }
688
689 #if !defined(ISP_DISABLE_1080_SUPPORT) && !defined(ISP_DISABLE_12160_SUPPORT)
690 static u_int16_t
691 isp_pci_rd_reg_1080(isp, regoff)
692 struct ispsoftc *isp;
693 int regoff;
694 {
695 u_int16_t rv, oc = 0;
696 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
697 int offset;
698
699 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
700 (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
701 u_int16_t tc;
702 /*
703 * We will assume that someone has paused the RISC processor.
704 */
705 oc = isp_pci_rd_reg(isp, BIU_CONF1);
706 tc = oc & ~BIU_PCI1080_CONF1_DMA;
707 if (regoff & SXP_BANK1_SELECT)
708 tc |= BIU_PCI1080_CONF1_SXP1;
709 else
710 tc |= BIU_PCI1080_CONF1_SXP0;
711 isp_pci_wr_reg(isp, BIU_CONF1, tc);
712 } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
713 oc = isp_pci_rd_reg(isp, BIU_CONF1);
714 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA);
715 }
716 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
717 offset += (regoff & 0xff);
718 rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset);
719 if (oc) {
720 isp_pci_wr_reg(isp, BIU_CONF1, oc);
721 }
722 return (rv);
723 }
724
725 static void
726 isp_pci_wr_reg_1080(isp, regoff, val)
727 struct ispsoftc *isp;
728 int regoff;
729 u_int16_t val;
730 {
731 struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
732 int offset, oc = 0;
733
734 if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
735 (regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
736 u_int16_t tc;
737 /*
738 * We will assume that someone has paused the RISC processor.
739 */
740 oc = isp_pci_rd_reg(isp, BIU_CONF1);
741 tc = oc & ~BIU_PCI1080_CONF1_DMA;
742 if (regoff & SXP_BANK1_SELECT)
743 tc |= BIU_PCI1080_CONF1_SXP1;
744 else
745 tc |= BIU_PCI1080_CONF1_SXP0;
746 isp_pci_wr_reg(isp, BIU_CONF1, tc);
747 } else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
748 oc = isp_pci_rd_reg(isp, BIU_CONF1);
749 isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA);
750 }
751 offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
752 offset += (regoff & 0xff);
753 bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val);
754 if (oc) {
755 isp_pci_wr_reg(isp, BIU_CONF1, oc);
756 }
757 }
758 #endif
759
760 static int
761 isp_pci_mbxdma(struct ispsoftc *isp)
762 {
763 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
764 u_int32_t len;
765 int rseg;
766
767 if (isp->isp_rquest) /* been here before? */
768 return (0);
769
770 len = sizeof (ISP_SCSI_XFER_T **) * isp->isp_maxcmds;
771 isp->isp_xflist = (ISP_SCSI_XFER_T **) malloc(len, M_DEVBUF, M_WAITOK);
772 if (isp->isp_xflist == NULL) {
773 printf("%s: can't alloc xflist array\n", isp->isp_name);
774 return (1);
775 }
776 bzero(isp->isp_xflist, len);
777
778 /*
779 * Allocate and map the request queue.
780 */
781 len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN);
782 isp->isp_rquest = malloc(len, M_DEVBUF, M_NOWAIT);
783 if (isp->isp_rquest == NULL) {
784 free(isp->isp_xflist, M_DEVBUF);
785 printf("%s: cannot malloc request queue\n", isp->isp_name);
786 return (1);
787 }
788 isp->isp_rquest_dma = vtophys(isp->isp_rquest);
789
790 #if 0
791 printf("RQUEST=0x%x (0x%x)...", isp->isp_rquest, isp->isp_rquest_dma);
792 #endif
793
794 /*
795 * Allocate and map the result queue.
796 */
797 len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN);
798 isp->isp_result = malloc(len, M_DEVBUF, M_NOWAIT);
799 if (isp->isp_result == NULL) {
800 free(isp->isp_xflist, M_DEVBUF);
801 free(isp->isp_rquest, M_DEVBUF);
802 printf("%s: cannot malloc result queue\n", isp->isp_name);
803 return (1);
804 }
805 isp->isp_result_dma = vtophys(isp->isp_result);
806 #if 0
807 printf("RESULT=0x%x (0x%x)\n", isp->isp_result, isp->isp_result_dma);
808 #endif
809 if (isp->isp_type & ISP_HA_FC) {
810 fcparam *fcp = isp->isp_param;
811 len = ISP2100_SCRLEN;
812 fcp->isp_scratch = (caddr_t)
813 malloc(ISP2100_SCRLEN, M_DEVBUF, M_NOWAIT);
814 if (fcp->isp_scratch == NULL) {
815 free(isp->isp_xflist, M_DEVBUF);
816 free(isp->isp_rquest, M_DEVBUF);
817 free(isp->isp_result, M_DEVBUF);
818 printf("%s: cannot alloc scratch\n", isp->isp_name);
819 return (1);
820 }
821 fcp->isp_scdma = vtophys(fcp->isp_scratch);
822 }
823 return (0);
824 }
825
826 static int
827 isp_pci_dmasetup(struct ispsoftc *isp, ISP_SCSI_XFER_T *xs,
828 ispreq_t *rq, u_int16_t *iptrp, u_int16_t optr)
829 {
830 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
831 ispcontreq_t *crq;
832 vm_offset_t vaddr;
833 int drq, seglim;
834 u_int32_t paddr, nextpaddr, datalen, size, *ctrp;
835
836 if (xs->datalen == 0) {
837 rq->req_seg_count = 1;
838 return (CMD_QUEUED);
839 }
840
841 if (xs->flags & SCSI_DATA_IN) {
842 drq = REQFLAG_DATA_IN;
843 } else {
844 drq = REQFLAG_DATA_OUT;
845 }
846
847 if (isp->isp_type & ISP_HA_FC) {
848 seglim = ISP_RQDSEG_T2;
849 ((ispreqt2_t *)rq)->req_totalcnt = XS_XFRLEN(xs);
850 ((ispreqt2_t *)rq)->req_flags |= drq;
851 } else {
852 rq->req_flags |= drq;
853 if (XS_CDBLEN(xs) > 12) {
854 seglim = 0;
855 } else {
856 seglim = ISP_RQDSEG;
857 }
858 }
859
860 datalen = XS_XFRLEN(xs);
861 vaddr = (vm_offset_t) xs->data;
862 paddr = vtophys(vaddr);
863
864 while (datalen != 0 && rq->req_seg_count < seglim) {
865 if (isp->isp_type & ISP_HA_FC) {
866 ispreqt2_t *rq2 = (ispreqt2_t *)rq;
867 rq2->req_dataseg[rq2->req_seg_count].ds_base = paddr;
868 ctrp = &rq2->req_dataseg[rq2->req_seg_count].ds_count;
869 } else {
870 rq->req_dataseg[rq->req_seg_count].ds_base = paddr;
871 ctrp = &rq->req_dataseg[rq->req_seg_count].ds_count;
872 }
873 nextpaddr = paddr;
874 *(ctrp) = 0;
875
876 while (datalen != 0 && paddr == nextpaddr) {
877 nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE;
878 size = nextpaddr - paddr;
879 if (size > datalen)
880 size = datalen;
881 *(ctrp) += size;
882 vaddr += size;
883 datalen -= size;
884 if (datalen != 0)
885 paddr = vtophys(vaddr);
886
887 }
888 #if 0
889 if (isp->isp_type & ISP_HA_FC) {
890 ispreqt2_t *rq2 = (ispreqt2_t *)rq;
891 printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n",
892 isp->isp_name, rq->req_seg_count,
893 rq2->req_dataseg[rq2->req_seg_count].ds_count,
894 rq2->req_dataseg[rq2->req_seg_count].ds_base);
895 } else {
896 printf("%s: seg0[%d] cnt 0x%x paddr 0x%08x\n",
897 isp->isp_name, rq->req_seg_count,
898 rq->req_dataseg[rq->req_seg_count].ds_count,
899 rq->req_dataseg[rq->req_seg_count].ds_base);
900 }
901 #endif
902 rq->req_seg_count++;
903 }
904
905
906
907 if (datalen == 0)
908 return (CMD_QUEUED);
909
910 paddr = vtophys(vaddr);
911 while (datalen > 0) {
912 crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp);
913 *iptrp = ISP_NXT_QENTRY(*iptrp, RQUEST_QUEUE_LEN);
914 if (*iptrp == optr) {
915 printf("%s: Request Queue Overflow\n", isp->isp_name);
916 XS_SETERR(xs, HBA_BOTCH);
917 return (CMD_EAGAIN);
918 }
919 rq->req_header.rqs_entry_count++;
920 bzero((void *)crq, sizeof (*crq));
921 crq->req_header.rqs_entry_count = 1;
922 crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
923
924 for (seglim = 0; datalen != 0 && seglim < ISP_CDSEG; seglim++) {
925 crq->req_dataseg[seglim].ds_base = paddr;
926 ctrp = &crq->req_dataseg[seglim].ds_count;
927 *(ctrp) = 0;
928 nextpaddr = paddr;
929 while (datalen != 0 && paddr == nextpaddr) {
930 nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE;
931 size = nextpaddr - paddr;
932 if (size > datalen)
933 size = datalen;
934 *(ctrp) += size;
935 vaddr += size;
936 datalen -= size;
937 if (datalen != 0)
938 paddr = vtophys(vaddr);
939 }
940 #if 0
941 printf("%s: seg%d[%d] cnt 0x%x paddr 0x%08x\n",
942 isp->isp_name, rq->req_header.rqs_entry_count-1,
943 seglim, crq->req_dataseg[seglim].ds_count,
944 crq->req_dataseg[seglim].ds_base);
945 #endif
946 rq->req_seg_count++;
947 }
948 }
949
950 return (CMD_QUEUED);
951 }
952
953 static void
954 isp_pci_reset1(struct ispsoftc *isp)
955 {
956 /* Make sure the BIOS is disabled */
957 isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
958 }
959
960 static void
961 isp_pci_dumpregs(struct ispsoftc *isp)
962 {
963 struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
964 printf("%s: PCI Status Command/Status=%lx\n", pci->pci_isp.isp_name,
965 pci_conf_read(pci->pci_id, PCIR_COMMAND));
966 }
Cache object: 5cff734cbab0fa9b9a6fcb26380dc68f
|