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