1 /* $OpenBSD: ahd_pci.c,v 1.30 2024/09/01 03:08:56 jsg Exp $ */
2
3 /*
4 * Copyright (c) 2004 Milos Urbanek, Kenneth R. Westerback & Marco Peereboom
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30 /*
31 * Product specific probe and attach routines for:
32 * aic7901 and aic7902 SCSI controllers
33 *
34 * Copyright (c) 1994-2001 Justin T. Gibbs.
35 * Copyright (c) 2000-2002 Adaptec Inc.
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions, and the following disclaimer,
43 * without modification.
44 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
45 * substantially similar to the "NO WARRANTY" disclaimer below
46 * ("Disclaimer") and any redistribution must be conditioned upon
47 * including a substantially similar Disclaimer requirement for further
48 * binary redistribution.
49 * 3. Neither the names of the above-listed copyright holders nor the names
50 * of any contributors may be used to endorse or promote products derived
51 * from this software without specific prior written permission.
52 *
53 * Alternatively, this software may be distributed under the terms of the
54 * GNU General Public License ("GPL") version 2 as published by the Free
55 * Software Foundation.
56 *
57 * NO WARRANTY
58 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
59 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
60 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
61 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
62 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
66 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
67 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68 * POSSIBILITY OF SUCH DAMAGES.
69 *
70 */
71
72 #include <dev/ic/aic79xx_openbsd.h>
73 #include <dev/ic/aic79xx_inline.h>
74 #include <dev/ic/aic79xx.h>
75
76 #include <dev/pci/pcivar.h>
77
78 static inline uint64_t
ahd_compose_id(u_int device,u_int vendor,u_int subdevice,u_int subvendor)79 ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
80 {
81 uint64_t id;
82
83 id = subvendor
84 | (subdevice << 16)
85 | ((uint64_t)vendor << 32)
86 | ((uint64_t)device << 48);
87
88 return (id);
89 }
90
91 #define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull
92 #define ID_ALL_IROC_MASK 0xFF7FFFFFFFFFFFFFull
93 #define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull
94 #define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull
95 #define ID_9005_GENERIC_IROC_MASK 0xFF70FFFF00000000ull
96
97 #define ID_AIC7901 0x800F9005FFFF9005ull
98 #define ID_AHA_29320A 0x8000900500609005ull
99 #define ID_AHA_29320ALP 0x8017900500449005ull
100 #define ID_AHA_29320LPE 0x8017900500459005ull
101
102 #define ID_AIC7901A 0x801E9005FFFF9005ull
103 #define ID_AHA_29320LP 0x8014900500449005ull
104
105 #define ID_AIC7902 0x801F9005FFFF9005ull
106 #define ID_AIC7902_B 0x801D9005FFFF9005ull
107 #define ID_AHA_39320 0x8010900500409005ull
108 #define ID_AHA_29320 0x8012900500429005ull
109 #define ID_AHA_29320B 0x8013900500439005ull
110 #define ID_AHA_39320_B 0x8015900500409005ull
111 #define ID_AHA_39320_B_DELL 0x8015900501681028ull
112 #define ID_AHA_39320A 0x8016900500409005ull
113 #define ID_AHA_39320D 0x8011900500419005ull
114 #define ID_AHA_39320D_B 0x801C900500419005ull
115 #define ID_AHA_39320D_HP 0x8011900500AC0E11ull
116 #define ID_AHA_39320D_B_HP 0x801C900500AC0E11ull
117 #define ID_AIC7902_PCI_REV_A4 0x3
118 #define ID_AIC7902_PCI_REV_B0 0x10
119 #define SUBID_HP 0x0E11
120
121 #define DEVID_9005_HOSTRAID(id) ((id) & 0x80)
122
123 #define DEVID_9005_TYPE(id) ((id) & 0xF)
124 #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */
125 #define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */
126 #define DEVID_9005_TYPE_MB 0xF /* On Motherboard */
127
128 #define DEVID_9005_MFUNC(id) ((id) & 0x10)
129
130 #define DEVID_9005_PACKETIZED(id) ((id) & 0x8000)
131
132 #define SUBID_9005_TYPE(id) ((id) & 0xF)
133 #define SUBID_9005_TYPE_HBA 0x0 /* Standard Card */
134 #define SUBID_9005_TYPE_MB 0xF /* On Motherboard */
135
136 #define SUBID_9005_AUTOTERM(id) (((id) & 0x10) == 0)
137
138 #define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20)
139
140 #define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6)
141 #define SUBID_9005_SEEPTYPE_NONE 0x0
142 #define SUBID_9005_SEEPTYPE_4K 0x1
143
144 ahd_device_setup_t ahd_aic7901_setup;
145 ahd_device_setup_t ahd_aic7901A_setup;
146 ahd_device_setup_t ahd_aic7902_setup;
147 ahd_device_setup_t ahd_aic790X_setup;
148
149 const struct ahd_pci_identity ahd_pci_ident_table[] =
150 {
151 /* aic7901 based controllers */
152 {
153 ID_AHA_29320A,
154 ID_ALL_MASK,
155 ahd_aic7901_setup
156 },
157 {
158 ID_AHA_29320ALP,
159 ID_ALL_MASK,
160 ahd_aic7901_setup
161 },
162 {
163 ID_AHA_29320LPE,
164 ID_ALL_MASK,
165 ahd_aic7901_setup
166 },
167 /* aic7901A based controllers */
168 {
169 ID_AHA_29320LP,
170 ID_ALL_MASK,
171 ahd_aic7901A_setup
172 },
173 /* aic7902 based controllers */
174 {
175 ID_AHA_29320,
176 ID_ALL_MASK,
177 ahd_aic7902_setup
178 },
179 {
180 ID_AHA_29320B,
181 ID_ALL_MASK,
182 ahd_aic7902_setup
183 },
184 {
185 ID_AHA_39320,
186 ID_ALL_MASK,
187 ahd_aic7902_setup
188 },
189 {
190 ID_AHA_39320_B,
191 ID_ALL_MASK,
192 ahd_aic7902_setup
193 },
194 {
195 ID_AHA_39320_B_DELL,
196 ID_ALL_MASK,
197 ahd_aic7902_setup
198 },
199 {
200 ID_AHA_39320A,
201 ID_ALL_MASK,
202 ahd_aic7902_setup
203 },
204 {
205 ID_AHA_39320D,
206 ID_ALL_MASK,
207 ahd_aic7902_setup
208 },
209 {
210 ID_AHA_39320D_HP,
211 ID_ALL_MASK,
212 ahd_aic7902_setup
213 },
214 {
215 ID_AHA_39320D_B,
216 ID_ALL_MASK,
217 ahd_aic7902_setup
218 },
219 {
220 ID_AHA_39320D_B_HP,
221 ID_ALL_MASK,
222 ahd_aic7902_setup
223 },
224 /* Generic chip probes for devices we don't know 'exactly' */
225 {
226 ID_AIC7901 & ID_9005_GENERIC_MASK,
227 ID_9005_GENERIC_MASK,
228 ahd_aic7901_setup
229 },
230 {
231 ID_AIC7901A & ID_DEV_VENDOR_MASK,
232 ID_DEV_VENDOR_MASK,
233 ahd_aic7901A_setup
234 },
235 {
236 ID_AIC7902 & ID_9005_GENERIC_MASK,
237 ID_9005_GENERIC_MASK,
238 ahd_aic7902_setup
239 }
240 };
241
242 const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table);
243
244 #define DEVCONFIG 0x40
245 #define PCIXINITPAT 0x0000E000ul
246 #define PCIXINIT_PCI33_66 0x0000E000ul
247 #define PCIXINIT_PCIX50_66 0x0000C000ul
248 #define PCIXINIT_PCIX66_100 0x0000A000ul
249 #define PCIXINIT_PCIX100_133 0x00008000ul
250 #define PCI_BUS_MODES_INDEX(devconfig) \
251 (((devconfig) & PCIXINITPAT) >> 13)
252
253 static const char *pci_bus_modes[] =
254 {
255 "PCI bus mode unknown",
256 "PCI bus mode unknown",
257 "PCI bus mode unknown",
258 "PCI bus mode unknown",
259 "PCI-X 101-133MHz",
260 "PCI-X 67-100MHz",
261 "PCI-X 50-66MHz",
262 "PCI 33 or 66MHz"
263 };
264
265 #define TESTMODE 0x00000800ul
266 #define IRDY_RST 0x00000200ul
267 #define FRAME_RST 0x00000100ul
268 #define PCI64BIT 0x00000080ul
269 #define MRDCEN 0x00000040ul
270 #define ENDIANSEL 0x00000020ul
271 #define MIXQWENDIANEN 0x00000008ul
272 #define DACEN 0x00000004ul
273 #define STPWLEVEL 0x00000002ul
274 #define QWENDIANSEL 0x00000001ul
275
276 #define DEVCONFIG1 0x44
277 #define PREQDIS 0x01
278
279 #define CSIZE_LATTIME 0x0c
280 #define CACHESIZE 0x000000fful
281 #define LATTIME 0x0000ff00ul
282
283 int ahd_pci_probe(struct device *, void *, void *);
284 void ahd_pci_attach(struct device *, struct device *, void *);
285 int ahd_activate(struct device *, int);
286
287 const struct cfattach ahd_pci_ca = {
288 sizeof(struct ahd_softc), ahd_pci_probe, ahd_pci_attach,
289 NULL, ahd_activate
290 };
291
292 int ahd_check_extport(struct ahd_softc *ahd);
293 void ahd_configure_termination(struct ahd_softc *ahd,
294 u_int adapter_control);
295 void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);
296
297 const struct ahd_pci_identity *
ahd_find_pci_device(pcireg_t id,pcireg_t subid)298 ahd_find_pci_device(pcireg_t id, pcireg_t subid)
299 {
300 const struct ahd_pci_identity *entry;
301 u_int64_t full_id;
302 u_int i;
303
304 full_id = ahd_compose_id(PCI_PRODUCT(id), PCI_VENDOR(id),
305 PCI_PRODUCT(subid), PCI_VENDOR(subid));
306
307 /*
308 * If we are configured to attach to HostRAID
309 * controllers, mask out the IROC/HostRAID bit
310 * in the
311 */
312 if (ahd_attach_to_HostRAID_controllers)
313 full_id &= ID_ALL_IROC_MASK;
314
315 for (i = 0; i < ahd_num_pci_devs; i++) {
316 entry = &ahd_pci_ident_table[i];
317 if (entry->full_id == (full_id & entry->id_mask)) {
318 return (entry);
319 }
320 }
321 return (NULL);
322 }
323
324 int
ahd_pci_probe(struct device * parent,void * match,void * aux)325 ahd_pci_probe(struct device *parent, void *match, void *aux)
326 {
327 const struct ahd_pci_identity *entry;
328 struct pci_attach_args *pa = aux;
329 pcireg_t subid;
330
331 subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
332 entry = ahd_find_pci_device(pa->pa_id, subid);
333 return entry != NULL ? 1 : 0;
334 }
335
336 void
ahd_pci_attach(struct device * parent,struct device * self,void * aux)337 ahd_pci_attach(struct device *parent, struct device *self, void *aux)
338 {
339 const struct ahd_pci_identity *entry;
340 struct pci_attach_args *pa = aux;
341 struct ahd_softc *ahd = (void *)self;
342 pci_intr_handle_t ih;
343 const char *intrstr;
344 pcireg_t devconfig, memtype, subid;
345 uint16_t device, subvendor;
346 int error, ioh_valid, ioh2_valid, l, memh_valid;
347
348 ahd->dev_softc = pa;
349 ahd->parent_dmat = pa->pa_dmat;
350
351 if (ahd_alloc(ahd, ahd->sc_dev.dv_xname) == NULL)
352 return;
353
354 subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
355 entry = ahd_find_pci_device(pa->pa_id, subid);
356 if (entry == NULL)
357 return;
358
359 /*
360 * Record if this is a HostRAID board.
361 */
362 device = PCI_PRODUCT(pa->pa_id);
363 if (DEVID_9005_HOSTRAID(device))
364 ahd->flags |= AHD_HOSTRAID_BOARD;
365
366 /*
367 * Record if this is an HP board.
368 */
369 subvendor = PCI_VENDOR(subid);
370 if (subvendor == SUBID_HP)
371 ahd->flags |= AHD_HP_BOARD;
372
373 error = entry->setup(ahd, pa);
374 if (error != 0)
375 return;
376
377 /* XXX ahc on sparc64 needs this twice */
378 devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
379
380 if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) {
381 ahd->chip |= AHD_PCI;
382 /* Disable PCIX workarounds when running in PCI mode. */
383 ahd->bugs &= ~AHD_PCIX_BUG_MASK;
384 } else {
385 ahd->chip |= AHD_PCIX;
386 }
387 ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)];
388
389 memh_valid = ioh_valid = ioh2_valid = 0;
390
391 if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIX,
392 &ahd->pcix_off, NULL)) {
393 if (ahd->chip & AHD_PCIX)
394 printf("%s: warning: can't find PCI-X capability\n",
395 ahd_name(ahd));
396 ahd->chip &= ~AHD_PCIX;
397 ahd->chip |= AHD_PCI;
398 ahd->bugs &= ~AHD_PCIX_BUG_MASK;
399 }
400
401 /*
402 * Map PCI registers
403 */
404 if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) == 0) {
405 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag,
406 AHD_PCI_MEMADDR);
407 switch (memtype) {
408 case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
409 case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
410 memh_valid = (pci_mapreg_map(pa, AHD_PCI_MEMADDR,
411 memtype, 0, &ahd->tags[0], &ahd->bshs[0], NULL,
412 NULL, 0) == 0);
413 if (memh_valid) {
414 ahd->tags[1] = ahd->tags[0];
415 bus_space_subregion(ahd->tags[0], ahd->bshs[0],
416 /*offset*/0x100, /*size*/0x100,
417 &ahd->bshs[1]);
418 if (ahd_pci_test_register_access(ahd) != 0)
419 memh_valid = 0;
420 }
421 break;
422 default:
423 memh_valid = 0;
424 printf("%s: unknown memory type: 0x%x\n",
425 ahd_name(ahd), memtype);
426 break;
427 }
428
429 #ifdef AHD_DEBUG
430 printf("%s: doing memory mapping tag0 %p, tag1 %p, shs0 "
431 "0x%lx, shs1 0x%lx\n", ahd_name(ahd), ahd->tags[0],
432 ahd->tags[1], ahd->bshs[0], ahd->bshs[1]);
433 #endif
434 }
435
436 if (!memh_valid) {
437 /* First BAR */
438 ioh_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR,
439 PCI_MAPREG_TYPE_IO, 0, &ahd->tags[0], &ahd->bshs[0], NULL,
440 NULL, 0) == 0);
441
442 /* 2nd BAR */
443 ioh2_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR1,
444 PCI_MAPREG_TYPE_IO, 0, &ahd->tags[1], &ahd->bshs[1], NULL,
445 NULL, 0) == 0);
446
447 #ifdef AHD_DEBUG
448 printf("%s: doing io mapping tag0 %p, tag1 %p, shs0 0x%lx, "
449 "shs1 0x%lx\n", ahd_name(ahd), ahd->tags[0], ahd->tags[1],
450 ahd->bshs[0], ahd->bshs[1]);
451 #endif
452 }
453
454 if (memh_valid == 0 && (ioh_valid == 0 || ioh2_valid == 0)) {
455 printf("%s: unable to map registers\n", ahd_name(ahd));
456 return;
457 }
458
459 /*
460 * Set Power State D0.
461 */
462 pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
463
464 /*
465 * Should we bother disabling 39Bit addressing
466 * based on installed memory?
467 */
468 if (sizeof(bus_addr_t) > 4)
469 ahd->flags |= AHD_39BIT_ADDRESSING;
470
471 /*
472 * If we need to support high memory, enable dual
473 * address cycles. This bit must be set to enable
474 * high address bit generation even if we are on a
475 * 64bit bus (PCI64BIT set in devconfig).
476 */
477 if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) {
478 if (bootverbose)
479 printf("%s: Enabling 39Bit Addressing\n",
480 ahd_name(ahd));
481 devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
482 devconfig |= DACEN;
483 pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG, devconfig);
484 }
485
486 ahd_softc_init(ahd);
487
488 /*
489 * Map the interrupts routines
490 */
491 ahd->bus_intr = ahd_pci_intr;
492
493 error = ahd_reset(ahd, /*reinit*/FALSE);
494 if (error != 0) {
495 ahd_free(ahd);
496 return;
497 }
498
499 if (pci_intr_map(pa, &ih)) {
500 printf("%s: couldn't map interrupt\n", ahd_name(ahd));
501 ahd_free(ahd);
502 return;
503 }
504 intrstr = pci_intr_string(pa->pa_pc, ih);
505 ahd->ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
506 ahd_platform_intr, ahd, ahd->sc_dev.dv_xname);
507 if (ahd->ih == NULL) {
508 printf("%s: couldn't establish interrupt", ahd_name(ahd));
509 if (intrstr != NULL)
510 printf(" at %s", intrstr);
511 printf("\n");
512 ahd_free(ahd);
513 return;
514 }
515 if (intrstr != NULL)
516 printf(": %s\n", intrstr);
517
518 /* Get the size of the cache */
519 ahd->pci_cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
520 ahd->pci_cachesize *= 4;
521
522 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
523 /* See if we have a SEEPROM and perform auto-term */
524 error = ahd_check_extport(ahd);
525 if (error != 0)
526 return;
527
528 /* Core initialization */
529 error = ahd_init(ahd);
530 if (error != 0)
531 return;
532
533 ahd_list_lock(&l);
534 /*
535 * Link this softc in with all other ahd instances.
536 */
537 ahd_softc_insert(ahd);
538 ahd_list_unlock(&l);
539
540 /* complete the attach */
541 ahd_attach(ahd);
542 }
543
544 int
ahd_activate(struct device * self,int act)545 ahd_activate(struct device *self, int act)
546 {
547 int ret = 0;
548
549 ret = config_activate_children(self, act);
550
551 switch (act) {
552 case DVACT_POWERDOWN:
553 ahd_shutdown(self);
554 break;
555 }
556
557 return (ret);
558 }
559
560 /*
561 * Perform some simple tests that should catch situations where
562 * our registers are invalidly mapped.
563 */
564 int
ahd_pci_test_register_access(struct ahd_softc * ahd)565 ahd_pci_test_register_access(struct ahd_softc *ahd)
566 {
567 const pci_chipset_tag_t pc = ahd->dev_softc->pa_pc;
568 const pcitag_t tag = ahd->dev_softc->pa_tag;
569 pcireg_t cmd;
570 u_int targpcistat;
571 pcireg_t pci_status1;
572 int error;
573 uint8_t hcntrl;
574
575 error = EIO;
576
577 /*
578 * Enable PCI error interrupt status, but suppress NMIs
579 * generated by SERR raised due to target aborts.
580 */
581 cmd = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
582 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
583 cmd & ~PCI_COMMAND_SERR_ENABLE);
584
585 /*
586 * First a simple test to see if any
587 * registers can be read. Reading
588 * HCNTRL has no side effects and has
589 * at least one bit that is guaranteed to
590 * be zero so it is a good register to
591 * use for this test.
592 */
593 hcntrl = ahd_inb(ahd, HCNTRL);
594 if (hcntrl == 0xFF)
595 goto fail;
596
597 /*
598 * Next create a situation where write combining
599 * or read prefetching could be initiated by the
600 * CPU or host bridge. Our device does not support
601 * either, so look for data corruption and/or flagged
602 * PCI errors. First pause without causing another
603 * chip reset.
604 */
605 hcntrl &= ~CHIPRST;
606 ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
607 while (ahd_is_paused(ahd) == 0)
608 ;
609
610 /* Clear any PCI errors that occurred before our driver attached. */
611 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
612 targpcistat = ahd_inb(ahd, TARGPCISTAT);
613 ahd_outb(ahd, TARGPCISTAT, targpcistat);
614 pci_status1 = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
615 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, pci_status1);
616 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
617 ahd_outb(ahd, CLRINT, CLRPCIINT);
618
619 ahd_outb(ahd, SEQCTL0, PERRORDIS);
620 ahd_outl(ahd, SRAM_BASE, 0x5aa555aa);
621 if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa)
622 goto fail;
623
624 if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
625 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
626 targpcistat = ahd_inb(ahd, TARGPCISTAT);
627 if ((targpcistat & STA) != 0)
628 goto fail;
629 }
630
631 error = 0;
632
633 fail:
634 if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
635
636 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
637 targpcistat = ahd_inb(ahd, TARGPCISTAT);
638
639 /* Silently clear any latched errors. */
640 ahd_outb(ahd, TARGPCISTAT, targpcistat);
641 pci_status1 = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
642 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, pci_status1);
643 ahd_outb(ahd, CLRINT, CLRPCIINT);
644 }
645 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS);
646 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, cmd);
647 return (error);
648 }
649
650 /*
651 * Check the external port logic for a serial eeprom
652 * and termination/cable detection controls.
653 */
654 int
ahd_check_extport(struct ahd_softc * ahd)655 ahd_check_extport(struct ahd_softc *ahd)
656 {
657 struct vpd_config vpd;
658 struct seeprom_config *sc;
659 u_int adapter_control;
660 int have_seeprom;
661 int error;
662
663 sc = ahd->seep_config;
664 have_seeprom = ahd_acquire_seeprom(ahd);
665 if (have_seeprom) {
666 u_int start_addr;
667
668 /*
669 * Fetch VPD for this function and parse it.
670 */
671 if (bootverbose)
672 printf("%s: Reading VPD from SEEPROM...",
673 ahd_name(ahd));
674
675 /* Address is always in units of 16bit words */
676 start_addr = ((2 * sizeof(*sc))
677 + (sizeof(vpd) * (ahd->channel - 'A'))) / 2;
678
679 error = ahd_read_seeprom(ahd, (uint16_t *)&vpd,
680 start_addr, sizeof(vpd)/2,
681 /*bytestream*/TRUE);
682 if (error == 0)
683 error = ahd_parse_vpddata(ahd, &vpd);
684 if (bootverbose)
685 printf("%s: VPD parsing %s\n",
686 ahd_name(ahd),
687 error == 0 ? "successful" : "failed");
688
689 if (bootverbose)
690 printf("%s: Reading SEEPROM...", ahd_name(ahd));
691
692 /* Address is always in units of 16bit words */
693 start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A');
694
695 error = ahd_read_seeprom(ahd, (uint16_t *)sc,
696 start_addr, sizeof(*sc)/2,
697 /*bytestream*/FALSE);
698
699 if (error != 0) {
700 printf("Unable to read SEEPROM\n");
701 have_seeprom = 0;
702 } else {
703 have_seeprom = ahd_verify_cksum(sc);
704
705 if (bootverbose) {
706 if (have_seeprom == 0)
707 printf ("checksum error\n");
708 else
709 printf ("done.\n");
710 }
711 }
712 ahd_release_seeprom(ahd);
713 }
714
715 if (!have_seeprom) {
716 u_int nvram_scb;
717
718 /*
719 * Pull scratch ram settings and treat them as
720 * if they are the contents of an seeprom if
721 * the 'ADPT', 'BIOS', or 'ASPI' signature is found
722 * in SCB 0xFF. We manually compose the data as 16bit
723 * values to avoid endian issues.
724 */
725 ahd_set_scbptr(ahd, 0xFF);
726 nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET);
727 if (nvram_scb != 0xFF
728 && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
729 && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D'
730 && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
731 && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T')
732 || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B'
733 && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I'
734 && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O'
735 && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S')
736 || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
737 && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S'
738 && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
739 && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) {
740 uint16_t *sc_data;
741 int i;
742
743 ahd_set_scbptr(ahd, nvram_scb);
744 sc_data = (uint16_t *)sc;
745 for (i = 0; i < 64; i += 2)
746 *sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i);
747 have_seeprom = ahd_verify_cksum(sc);
748 if (have_seeprom)
749 ahd->flags |= AHD_SCB_CONFIG_USED;
750 }
751 }
752
753 #ifdef AHD_DEBUG
754 if (have_seeprom != 0
755 && (ahd_debug & AHD_DUMP_SEEPROM) != 0) {
756 uint16_t *sc_data;
757 int i;
758
759 printf("%s: Seeprom Contents:", ahd_name(ahd));
760 sc_data = (uint16_t *)sc;
761 for (i = 0; i < (sizeof(*sc)); i += 2)
762 printf("\n\t0x%.4x", sc_data[i]);
763 printf("\n");
764 }
765 #endif
766
767 if (!have_seeprom) {
768 if (bootverbose)
769 printf("%s: No SEEPROM available.\n", ahd_name(ahd));
770 ahd->flags |= AHD_USEDEFAULTS;
771 error = ahd_default_config(ahd);
772 adapter_control = CFAUTOTERM|CFSEAUTOTERM;
773 free(ahd->seep_config, M_DEVBUF, 0);
774 ahd->seep_config = NULL;
775 } else {
776 error = ahd_parse_cfgdata(ahd, sc);
777 adapter_control = sc->adapter_control;
778 }
779 if (error != 0)
780 return (error);
781
782 ahd_configure_termination(ahd, adapter_control);
783
784 return (0);
785 }
786
787 void
ahd_configure_termination(struct ahd_softc * ahd,u_int adapter_control)788 ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)
789 {
790 const pci_chipset_tag_t pc = ahd->dev_softc->pa_pc;
791 const pcitag_t tag = ahd->dev_softc->pa_tag;
792 int error;
793 u_int sxfrctl1;
794 uint8_t termctl;
795 pcireg_t devconfig;
796
797 devconfig = pci_conf_read(pc, tag, DEVCONFIG);
798 devconfig &= ~STPWLEVEL;
799 if ((ahd->flags & AHD_STPWLEVEL_A) != 0)
800 devconfig |= STPWLEVEL;
801 if (bootverbose)
802 printf("%s: STPWLEVEL is %s\n",
803 ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off");
804 pci_conf_write(pc, tag, DEVCONFIG, devconfig);
805
806 /* Make sure current sensing is off. */
807 if ((ahd->flags & AHD_CURRENT_SENSING) != 0) {
808 (void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);
809 }
810
811 /*
812 * Read to sense. Write to set.
813 */
814 error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl);
815 if ((adapter_control & CFAUTOTERM) == 0) {
816 if (bootverbose)
817 printf("%s: Manual Primary Termination\n",
818 ahd_name(ahd));
819 termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH);
820 if ((adapter_control & CFSTERM) != 0)
821 termctl |= FLX_TERMCTL_ENPRILOW;
822 if ((adapter_control & CFWSTERM) != 0)
823 termctl |= FLX_TERMCTL_ENPRIHIGH;
824 } else if (error != 0) {
825 printf("%s: Primary Auto-Term Sensing failed! "
826 "Using Defaults.\n", ahd_name(ahd));
827 termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH;
828 }
829
830 if ((adapter_control & CFSEAUTOTERM) == 0) {
831 if (bootverbose)
832 printf("%s: Manual Secondary Termination\n",
833 ahd_name(ahd));
834 termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH);
835 if ((adapter_control & CFSELOWTERM) != 0)
836 termctl |= FLX_TERMCTL_ENSECLOW;
837 if ((adapter_control & CFSEHIGHTERM) != 0)
838 termctl |= FLX_TERMCTL_ENSECHIGH;
839 } else if (error != 0) {
840 printf("%s: Secondary Auto-Term Sensing failed! "
841 "Using Defaults.\n", ahd_name(ahd));
842 termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH;
843 }
844
845 /*
846 * Now set the termination based on what we found.
847 */
848 sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;
849 ahd->flags &= ~AHD_TERM_ENB_A;
850 if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {
851 ahd->flags |= AHD_TERM_ENB_A;
852 sxfrctl1 |= STPWEN;
853 }
854 /* Must set the latch once in order to be effective. */
855 ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);
856 ahd_outb(ahd, SXFRCTL1, sxfrctl1);
857
858 error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl);
859 if (error != 0) {
860 printf("%s: Unable to set termination settings!\n",
861 ahd_name(ahd));
862 } else if (bootverbose) {
863 printf("%s: Primary High byte termination %sabled\n",
864 ahd_name(ahd),
865 (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis");
866
867 printf("%s: Primary Low byte termination %sabled\n",
868 ahd_name(ahd),
869 (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis");
870
871 printf("%s: Secondary High byte termination %sabled\n",
872 ahd_name(ahd),
873 (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis");
874
875 printf("%s: Secondary Low byte termination %sabled\n",
876 ahd_name(ahd),
877 (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis");
878 }
879 return;
880 }
881
882 #define DPE 0x80
883 #define SSE 0x40
884 #define RMA 0x20
885 #define RTA 0x10
886 #define STA 0x08
887 #define DPR 0x01
888
889 static const char *split_status_source[] =
890 {
891 "DFF0",
892 "DFF1",
893 "OVLY",
894 "CMC",
895 };
896
897 static const char *pci_status_source[] =
898 {
899 "DFF0",
900 "DFF1",
901 "SG",
902 "CMC",
903 "OVLY",
904 "NONE",
905 "MSI",
906 "TARG"
907 };
908
909 static const char *split_status_strings[] =
910 {
911 "Received split response",
912 "Received split completion error message",
913 "Receive overrun",
914 "Count not complete",
915 "Split completion data bucket",
916 "Split completion address error",
917 "Split completion byte count error",
918 "Signaled Target-abort to early terminate a split"
919 };
920
921 static const char *pci_status_strings[] =
922 {
923 "Data Parity Error has been reported via PERR#",
924 "Target initial wait state error",
925 "Split completion read data parity error",
926 "Split completion address attribute parity error",
927 "Received a Target Abort",
928 "Received a Master Abort",
929 "Signal System Error Detected",
930 "Address or Write Phase Parity Error Detected"
931 };
932
933 void
ahd_pci_intr(struct ahd_softc * ahd)934 ahd_pci_intr(struct ahd_softc *ahd)
935 {
936 const pci_chipset_tag_t pc = ahd->dev_softc->pa_pc;
937 const pcitag_t tag = ahd->dev_softc->pa_tag;
938 uint8_t pci_status[8];
939 ahd_mode_state saved_modes;
940 pcireg_t pci_status1;
941 u_int intstat;
942 u_int i;
943 u_int reg;
944
945 intstat = ahd_inb(ahd, INTSTAT);
946
947 if ((intstat & SPLTINT) != 0)
948 ahd_pci_split_intr(ahd, intstat);
949
950 if ((intstat & PCIINT) == 0)
951 return;
952
953 printf("%s: PCI error Interrupt\n", ahd_name(ahd));
954 saved_modes = ahd_save_modes(ahd);
955 ahd_dump_card_state(ahd);
956 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
957 for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) {
958
959 if (i == 5)
960 continue;
961 pci_status[i] = ahd_inb(ahd, reg);
962 /* Clear latched errors. So our interrupt deasserts. */
963 ahd_outb(ahd, reg, pci_status[i]);
964 }
965
966 for (i = 0; i < 8; i++) {
967 u_int bit;
968
969 if (i == 5)
970 continue;
971
972 for (bit = 0; bit < 8; bit++) {
973
974 if ((pci_status[i] & (0x1 << bit)) != 0) {
975 if (i == 7/*TARG*/ && bit == 3)
976 printf("%s: Signaled Target Abort\n",
977 ahd_name(ahd));
978 else
979 printf("%s: %s in %s\n", ahd_name(ahd),
980 pci_status_strings[bit],
981 pci_status_source[i]);
982 }
983 }
984 }
985 pci_status1 = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
986 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG , pci_status1);
987
988 ahd_restore_modes(ahd, saved_modes);
989 ahd_outb(ahd, CLRINT, CLRPCIINT);
990 ahd_unpause(ahd);
991
992 return;
993 }
994
995 void
ahd_pci_split_intr(struct ahd_softc * ahd,u_int intstat)996 ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)
997 {
998 const pci_chipset_tag_t pc = ahd->dev_softc->pa_pc;
999 const pcitag_t tag = ahd->dev_softc->pa_tag;
1000 uint8_t split_status[4];
1001 uint8_t split_status1[4];
1002 uint8_t sg_split_status[2];
1003 uint8_t sg_split_status1[2];
1004 ahd_mode_state saved_modes;
1005 u_int i;
1006 pcireg_t pcix_status;
1007
1008 /*
1009 * Check for splits in all modes. Modes 0 and 1
1010 * additionally have SG engine splits to look at.
1011 */
1012 pcix_status = pci_conf_read(pc, tag, ahd->pcix_off + 0x04);
1013 printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n",
1014 ahd_name(ahd), pcix_status);
1015
1016 saved_modes = ahd_save_modes(ahd);
1017 for (i = 0; i < 4; i++) {
1018 ahd_set_modes(ahd, i, i);
1019
1020 split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0);
1021 split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1);
1022 /* Clear latched errors. So our interrupt deasserts. */
1023 ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]);
1024 ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]);
1025 if (i > 1)
1026 continue;
1027 sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0);
1028 sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1);
1029 /* Clear latched errors. So our interrupt deasserts. */
1030 ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]);
1031 ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]);
1032 }
1033
1034 for (i = 0; i < 4; i++) {
1035 u_int bit;
1036
1037 for (bit = 0; bit < 8; bit++) {
1038
1039 if ((split_status[i] & (0x1 << bit)) != 0) {
1040 printf("%s: %s in %s\n", ahd_name(ahd),
1041 split_status_strings[bit],
1042 split_status_source[i]);
1043 }
1044
1045 if (i > 1)
1046 continue;
1047
1048 if ((sg_split_status[i] & (0x1 << bit)) != 0) {
1049 printf("%s: %s in %s\n", ahd_name(ahd),
1050 split_status_strings[bit], "SG");
1051 }
1052 }
1053 }
1054 /*
1055 * Clear PCI-X status bits.
1056 */
1057 pci_conf_write(pc, tag, ahd->pcix_off + 0x04, pcix_status);
1058 ahd_outb(ahd, CLRINT, CLRSPLTINT);
1059 ahd_restore_modes(ahd, saved_modes);
1060 }
1061
1062 int
ahd_aic7901_setup(struct ahd_softc * ahd,struct pci_attach_args * pa)1063 ahd_aic7901_setup(struct ahd_softc *ahd, struct pci_attach_args *pa)
1064 {
1065
1066 ahd->chip = AHD_AIC7901;
1067 ahd->features = AHD_AIC7901_FE;
1068 return (ahd_aic790X_setup(ahd, pa));
1069 }
1070
1071 int
ahd_aic7901A_setup(struct ahd_softc * ahd,struct pci_attach_args * pa)1072 ahd_aic7901A_setup(struct ahd_softc *ahd, struct pci_attach_args *pa)
1073 {
1074
1075 ahd->chip = AHD_AIC7901A;
1076 ahd->features = AHD_AIC7901A_FE;
1077 return (ahd_aic790X_setup(ahd, pa));
1078 }
1079
1080 int
ahd_aic7902_setup(struct ahd_softc * ahd,struct pci_attach_args * pa)1081 ahd_aic7902_setup(struct ahd_softc *ahd, struct pci_attach_args *pa)
1082 {
1083 ahd->chip = AHD_AIC7902;
1084 ahd->features = AHD_AIC7902_FE;
1085 return (ahd_aic790X_setup(ahd, pa));
1086 }
1087
1088 int
ahd_aic790X_setup(struct ahd_softc * ahd,struct pci_attach_args * pa)1089 ahd_aic790X_setup(struct ahd_softc *ahd, struct pci_attach_args *pa)
1090 {
1091 u_int rev;
1092
1093 rev = PCI_REVISION(pa->pa_class);
1094 #ifdef AHD_DEBUG
1095 printf("\n%s: aic7902 chip revision 0x%x\n", ahd_name(ahd), rev);
1096 #endif
1097 if (rev < ID_AIC7902_PCI_REV_A4) {
1098 printf("%s: Unable to attach to unsupported chip revision %d\n",
1099 ahd_name(ahd), rev);
1100 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 0);
1101 return (ENXIO);
1102 }
1103
1104 ahd->channel = (pa->pa_function == 1) ? 'B' : 'A';
1105 if (rev < ID_AIC7902_PCI_REV_B0) {
1106 /*
1107 * Enable A series workarounds.
1108 */
1109 ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG
1110 | AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG
1111 | AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG
1112 | AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG
1113 | AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG
1114 | AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG
1115 | AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG
1116 | AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG
1117 | AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG
1118 | AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG
1119 | AHD_FAINT_LED_BUG;
1120
1121 /*
1122 * IO Cell parameter setup.
1123 */
1124 AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
1125
1126 if ((ahd->flags & AHD_HP_BOARD) == 0)
1127 AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);
1128 } else {
1129 pcireg_t devconfig1;
1130
1131 ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
1132 | AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY;
1133 ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG
1134 | AHD_BUSFREEREV_BUG;
1135
1136 /*
1137 * Some issues have been resolved in the 7901B.
1138 */
1139 if ((ahd->features & AHD_MULTI_FUNC) != 0)
1140 ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG;
1141
1142 /*
1143 * IO Cell parameter setup.
1144 */
1145 AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
1146 AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB);
1147 AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF);
1148
1149 /*
1150 * Set the PREQDIS bit for H2B which disables some workaround
1151 * that doesn't work on regular PCI busses.
1152 * XXX - Find out exactly what this does from the hardware
1153 * folks!
1154 */
1155 devconfig1 = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG1);
1156 pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG1, devconfig1|PREQDIS);
1157 devconfig1 = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG1);
1158 }
1159
1160 return (0);
1161 }
1162