File: | dev/pci/ahd_pci.c |
Warning: | line 683, column 4 Value stored to 'error' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ahd_pci.c,v 1.29 2022/10/21 17:45:40 kn 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 |
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_MASK0xFFFFFFFFFFFFFFFFull 0xFFFFFFFFFFFFFFFFull |
92 | #define ID_ALL_IROC_MASK0xFF7FFFFFFFFFFFFFull 0xFF7FFFFFFFFFFFFFull |
93 | #define ID_DEV_VENDOR_MASK0xFFFFFFFF00000000ull 0xFFFFFFFF00000000ull |
94 | #define ID_9005_GENERIC_MASK0xFFF0FFFF00000000ull 0xFFF0FFFF00000000ull |
95 | #define ID_9005_GENERIC_IROC_MASK0xFF70FFFF00000000ull 0xFF70FFFF00000000ull |
96 | |
97 | #define ID_AIC79010x800F9005FFFF9005ull 0x800F9005FFFF9005ull |
98 | #define ID_AHA_29320A0x8000900500609005ull 0x8000900500609005ull |
99 | #define ID_AHA_29320ALP0x8017900500449005ull 0x8017900500449005ull |
100 | #define ID_AHA_29320LPE0x8017900500459005ull 0x8017900500459005ull |
101 | |
102 | #define ID_AIC7901A0x801E9005FFFF9005ull 0x801E9005FFFF9005ull |
103 | #define ID_AHA_29320LP0x8014900500449005ull 0x8014900500449005ull |
104 | |
105 | #define ID_AIC79020x801F9005FFFF9005ull 0x801F9005FFFF9005ull |
106 | #define ID_AIC7902_B0x801D9005FFFF9005ull 0x801D9005FFFF9005ull |
107 | #define ID_AHA_393200x8010900500409005ull 0x8010900500409005ull |
108 | #define ID_AHA_293200x8012900500429005ull 0x8012900500429005ull |
109 | #define ID_AHA_29320B0x8013900500439005ull 0x8013900500439005ull |
110 | #define ID_AHA_39320_B0x8015900500409005ull 0x8015900500409005ull |
111 | #define ID_AHA_39320_B_DELL0x8015900501681028ull 0x8015900501681028ull |
112 | #define ID_AHA_39320A0x8016900500409005ull 0x8016900500409005ull |
113 | #define ID_AHA_39320D0x8011900500419005ull 0x8011900500419005ull |
114 | #define ID_AHA_39320D_B0x801C900500419005ull 0x801C900500419005ull |
115 | #define ID_AHA_39320D_HP0x8011900500AC0E11ull 0x8011900500AC0E11ull |
116 | #define ID_AHA_39320D_B_HP0x801C900500AC0E11ull 0x801C900500AC0E11ull |
117 | #define ID_AIC7902_PCI_REV_A40x3 0x3 |
118 | #define ID_AIC7902_PCI_REV_B00x10 0x10 |
119 | #define SUBID_HP0x0E11 0x0E11 |
120 | |
121 | #define DEVID_9005_HOSTRAID(id)((id) & 0x80) ((id) & 0x80) |
122 | |
123 | #define DEVID_9005_TYPE(id)((id) & 0xF) ((id) & 0xF) |
124 | #define DEVID_9005_TYPE_HBA0x0 0x0 /* Standard Card */ |
125 | #define DEVID_9005_TYPE_HBA_2EXT0x1 0x1 /* 2 External Ports */ |
126 | #define DEVID_9005_TYPE_MB0xF 0xF /* On Motherboard */ |
127 | |
128 | #define DEVID_9005_MFUNC(id)((id) & 0x10) ((id) & 0x10) |
129 | |
130 | #define DEVID_9005_PACKETIZED(id)((id) & 0x8000) ((id) & 0x8000) |
131 | |
132 | #define SUBID_9005_TYPE(id)((id) & 0xF) ((id) & 0xF) |
133 | #define SUBID_9005_TYPE_HBA0x0 0x0 /* Standard Card */ |
134 | #define SUBID_9005_TYPE_MB0xF 0xF /* On Motherboard */ |
135 | |
136 | #define SUBID_9005_AUTOTERM(id)(((id) & 0x10) == 0) (((id) & 0x10) == 0) |
137 | |
138 | #define SUBID_9005_LEGACYCONN_FUNC(id)((id) & 0x20) ((id) & 0x20) |
139 | |
140 | #define SUBID_9005_SEEPTYPE(id)((id) & 0x0C0) >> 6) ((id) & 0x0C0) >> 6) |
141 | #define SUBID_9005_SEEPTYPE_NONE0x0 0x0 |
142 | #define SUBID_9005_SEEPTYPE_4K0x1 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_29320A0x8000900500609005ull, |
154 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
155 | ahd_aic7901_setup |
156 | }, |
157 | { |
158 | ID_AHA_29320ALP0x8017900500449005ull, |
159 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
160 | ahd_aic7901_setup |
161 | }, |
162 | { |
163 | ID_AHA_29320LPE0x8017900500459005ull, |
164 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
165 | ahd_aic7901_setup |
166 | }, |
167 | /* aic7901A based controllers */ |
168 | { |
169 | ID_AHA_29320LP0x8014900500449005ull, |
170 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
171 | ahd_aic7901A_setup |
172 | }, |
173 | /* aic7902 based controllers */ |
174 | { |
175 | ID_AHA_293200x8012900500429005ull, |
176 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
177 | ahd_aic7902_setup |
178 | }, |
179 | { |
180 | ID_AHA_29320B0x8013900500439005ull, |
181 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
182 | ahd_aic7902_setup |
183 | }, |
184 | { |
185 | ID_AHA_393200x8010900500409005ull, |
186 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
187 | ahd_aic7902_setup |
188 | }, |
189 | { |
190 | ID_AHA_39320_B0x8015900500409005ull, |
191 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
192 | ahd_aic7902_setup |
193 | }, |
194 | { |
195 | ID_AHA_39320_B_DELL0x8015900501681028ull, |
196 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
197 | ahd_aic7902_setup |
198 | }, |
199 | { |
200 | ID_AHA_39320A0x8016900500409005ull, |
201 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
202 | ahd_aic7902_setup |
203 | }, |
204 | { |
205 | ID_AHA_39320D0x8011900500419005ull, |
206 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
207 | ahd_aic7902_setup |
208 | }, |
209 | { |
210 | ID_AHA_39320D_HP0x8011900500AC0E11ull, |
211 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
212 | ahd_aic7902_setup |
213 | }, |
214 | { |
215 | ID_AHA_39320D_B0x801C900500419005ull, |
216 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
217 | ahd_aic7902_setup |
218 | }, |
219 | { |
220 | ID_AHA_39320D_B_HP0x801C900500AC0E11ull, |
221 | ID_ALL_MASK0xFFFFFFFFFFFFFFFFull, |
222 | ahd_aic7902_setup |
223 | }, |
224 | /* Generic chip probes for devices we don't know 'exactly' */ |
225 | { |
226 | ID_AIC79010x800F9005FFFF9005ull & ID_9005_GENERIC_MASK0xFFF0FFFF00000000ull, |
227 | ID_9005_GENERIC_MASK0xFFF0FFFF00000000ull, |
228 | ahd_aic7901_setup |
229 | }, |
230 | { |
231 | ID_AIC7901A0x801E9005FFFF9005ull & ID_DEV_VENDOR_MASK0xFFFFFFFF00000000ull, |
232 | ID_DEV_VENDOR_MASK0xFFFFFFFF00000000ull, |
233 | ahd_aic7901A_setup |
234 | }, |
235 | { |
236 | ID_AIC79020x801F9005FFFF9005ull & ID_9005_GENERIC_MASK0xFFF0FFFF00000000ull, |
237 | ID_9005_GENERIC_MASK0xFFF0FFFF00000000ull, |
238 | ahd_aic7902_setup |
239 | } |
240 | }; |
241 | |
242 | const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table)(sizeof(ahd_pci_ident_table) / sizeof(*ahd_pci_ident_table)); |
243 | |
244 | #define DEVCONFIG0x40 0x40 |
245 | #define PCIXINITPAT0x0000E000ul 0x0000E000ul |
246 | #define PCIXINIT_PCI33_660x0000E000ul 0x0000E000ul |
247 | #define PCIXINIT_PCIX50_660x0000C000ul 0x0000C000ul |
248 | #define PCIXINIT_PCIX66_1000x0000A000ul 0x0000A000ul |
249 | #define PCIXINIT_PCIX100_1330x00008000ul 0x00008000ul |
250 | #define PCI_BUS_MODES_INDEX(devconfig)(((devconfig) & 0x0000E000ul) >> 13) \ |
251 | (((devconfig) & PCIXINITPAT0x0000E000ul) >> 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 TESTMODE0x00000800ul 0x00000800ul |
266 | #define IRDY_RST0x00000200ul 0x00000200ul |
267 | #define FRAME_RST0x00000100ul 0x00000100ul |
268 | #define PCI64BIT0x00000080ul 0x00000080ul |
269 | #define MRDCEN0x00000040ul 0x00000040ul |
270 | #define ENDIANSEL0x00000020ul 0x00000020ul |
271 | #define MIXQWENDIANEN0x00000008ul 0x00000008ul |
272 | #define DACEN0x00000004ul 0x00000004ul |
273 | #define STPWLEVEL0x00000002ul 0x00000002ul |
274 | #define QWENDIANSEL0x00000001ul 0x00000001ul |
275 | |
276 | #define DEVCONFIG10x44 0x44 |
277 | #define PREQDIS0x01 0x01 |
278 | |
279 | #define CSIZE_LATTIME0x0c 0x0c |
280 | #define CACHESIZE0x000000fful 0x000000fful |
281 | #define LATTIME0x0000ff00ul 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((void *)0), 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 * |
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)(((id) >> 16) & 0xffff), PCI_VENDOR(id)(((id) >> 0) & 0xffff), |
305 | PCI_PRODUCT(subid)(((subid) >> 16) & 0xffff), PCI_VENDOR(subid)(((subid) >> 0) & 0xffff)); |
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_MASK0xFF7FFFFFFFFFFFFFull; |
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((void *)0)); |
322 | } |
323 | |
324 | int |
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_REG0x2c); |
332 | entry = ahd_find_pci_device(pa->pa_id, subid); |
333 | return entry != NULL((void *)0) ? 1 : 0; |
334 | } |
335 | |
336 | void |
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((void *)0)) |
352 | return; |
353 | |
354 | subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG0x2c); |
355 | entry = ahd_find_pci_device(pa->pa_id, subid); |
356 | if (entry == NULL((void *)0)) |
357 | return; |
358 | |
359 | /* |
360 | * Record if this is a HostRAID board. |
361 | */ |
362 | device = PCI_PRODUCT(pa->pa_id)(((pa->pa_id) >> 16) & 0xffff); |
363 | if (DEVID_9005_HOSTRAID(device)((device) & 0x80)) |
364 | ahd->flags |= AHD_HOSTRAID_BOARD; |
365 | |
366 | /* |
367 | * Record if this is an HP board. |
368 | */ |
369 | subvendor = PCI_VENDOR(subid)(((subid) >> 0) & 0xffff); |
370 | if (subvendor == SUBID_HP0x0E11) |
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, DEVCONFIG0x40); |
379 | |
380 | if ((devconfig & PCIXINITPAT0x0000E000ul) == PCIXINIT_PCI33_660x0000E000ul) { |
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)(((devconfig) & 0x0000E000ul) >> 13)]; |
388 | |
389 | memh_valid = ioh_valid = ioh2_valid = 0; |
390 | |
391 | if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIX0x07, |
392 | &ahd->pcix_off, NULL((void *)0))) { |
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(0x10 + 4)); |
407 | switch (memtype) { |
408 | case PCI_MAPREG_TYPE_MEM0x00000000 | PCI_MAPREG_MEM_TYPE_32BIT0x00000000: |
409 | case PCI_MAPREG_TYPE_MEM0x00000000 | PCI_MAPREG_MEM_TYPE_64BIT0x00000004: |
410 | memh_valid = (pci_mapreg_map(pa, AHD_PCI_MEMADDR(0x10 + 4), |
411 | memtype, 0, &ahd->tags[0], &ahd->bshs[0], NULL((void *)0), |
412 | NULL((void *)0), 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_IOADDR0x10, |
439 | PCI_MAPREG_TYPE_IO0x00000001, 0, &ahd->tags[0], &ahd->bshs[0], NULL((void *)0), |
440 | NULL((void *)0), 0) == 0); |
441 | |
442 | /* 2nd BAR */ |
443 | ioh2_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR1(0x10 + 12), |
444 | PCI_MAPREG_TYPE_IO0x00000001, 0, &ahd->tags[1], &ahd->bshs[1], NULL((void *)0), |
445 | NULL((void *)0), 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_D00x0000); |
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 (bootverbose0) |
479 | printf("%s: Enabling 39Bit Addressing\n", |
480 | ahd_name(ahd)); |
481 | devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG0x40); |
482 | devconfig |= DACEN0x00000004ul; |
483 | pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG0x40, 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*/FALSE0); |
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_BIO0x3, |
506 | ahd_platform_intr, ahd, ahd->sc_dev.dv_xname); |
507 | if (ahd->ih == NULL((void *)0)) { |
508 | printf("%s: couldn't establish interrupt", ahd_name(ahd)); |
509 | if (intrstr != NULL((void *)0)) |
510 | printf(" at %s", intrstr); |
511 | printf("\n"); |
512 | ahd_free(ahd); |
513 | return; |
514 | } |
515 | if (intrstr != NULL((void *)0)) |
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_REG0x0c); |
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)*(&l) = splraise(0x3); |
534 | /* |
535 | * Link this softc in with all other ahd instances. |
536 | */ |
537 | ahd_softc_insert(ahd); |
538 | ahd_list_unlock(&l)spllower(*(&l)); |
539 | |
540 | /* complete the attach */ |
541 | ahd_attach(ahd); |
542 | } |
543 | |
544 | int |
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_POWERDOWN6: |
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 |
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 = EIO5; |
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_REG0x04); |
582 | pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG0x04, |
583 | cmd & ~PCI_COMMAND_SERR_ENABLE0x00000100); |
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)(((ahd)->tags[(0x05) >> 8])->read_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF))); |
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 &= ~CHIPRST0x01; |
606 | ahd_outb(ahd, HCNTRL, hcntrl|PAUSE)(((ahd)->tags[(0x05) >> 8])->write_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF), (hcntrl|0x04))); |
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)(((ahd)->tags[(0xa7) >> 8])->read_1(((ahd)->bshs [(0xa7) >> 8]), ((0xa7) & 0xFF))); |
613 | ahd_outb(ahd, TARGPCISTAT, targpcistat)(((ahd)->tags[(0xa7) >> 8])->write_1(((ahd)->bshs [(0xa7) >> 8]), ((0xa7) & 0xFF), (targpcistat))); |
614 | pci_status1 = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG0x04); |
615 | pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG0x04, pci_status1); |
616 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
617 | ahd_outb(ahd, CLRINT, CLRPCIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x10))); |
618 | |
619 | ahd_outb(ahd, SEQCTL0, PERRORDIS)(((ahd)->tags[(0xd6) >> 8])->write_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF), (0x80))); |
620 | ahd_outl(ahd, SRAM_BASE0x100, 0x5aa555aa); |
621 | if (ahd_inl(ahd, SRAM_BASE0x100) != 0x5aa555aa) |
622 | goto fail; |
623 | |
624 | if ((ahd_inb(ahd, INTSTAT)(((ahd)->tags[(0x01) >> 8])->read_1(((ahd)->bshs [(0x01) >> 8]), ((0x01) & 0xFF))) & PCIINT0x10) != 0) { |
625 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
626 | targpcistat = ahd_inb(ahd, TARGPCISTAT)(((ahd)->tags[(0xa7) >> 8])->read_1(((ahd)->bshs [(0xa7) >> 8]), ((0xa7) & 0xFF))); |
627 | if ((targpcistat & STA0x08) != 0) |
628 | goto fail; |
629 | } |
630 | |
631 | error = 0; |
632 | |
633 | fail: |
634 | if ((ahd_inb(ahd, INTSTAT)(((ahd)->tags[(0x01) >> 8])->read_1(((ahd)->bshs [(0x01) >> 8]), ((0x01) & 0xFF))) & PCIINT0x10) != 0) { |
635 | |
636 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
637 | targpcistat = ahd_inb(ahd, TARGPCISTAT)(((ahd)->tags[(0xa7) >> 8])->read_1(((ahd)->bshs [(0xa7) >> 8]), ((0xa7) & 0xFF))); |
638 | |
639 | /* Silently clear any latched errors. */ |
640 | ahd_outb(ahd, TARGPCISTAT, targpcistat)(((ahd)->tags[(0xa7) >> 8])->write_1(((ahd)->bshs [(0xa7) >> 8]), ((0xa7) & 0xFF), (targpcistat))); |
641 | pci_status1 = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG0x04); |
642 | pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG0x04, pci_status1); |
643 | ahd_outb(ahd, CLRINT, CLRPCIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x10))); |
644 | } |
645 | ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS)(((ahd)->tags[(0xd6) >> 8])->write_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF), (0x80|0x20))); |
646 | pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG0x04, cmd); |
647 | return (error); |
648 | } |
649 | |
650 | /* |
651 | * Check the external port logic for a serial eeprom |
652 | * and termination/cable detection contrls. |
653 | */ |
654 | int |
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 (bootverbose0) |
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*/TRUE1); |
682 | if (error == 0) |
683 | error = ahd_parse_vpddata(ahd, &vpd); |
Value stored to 'error' is never read | |
684 | if (bootverbose0) |
685 | printf("%s: VPD parsing %s\n", |
686 | ahd_name(ahd), |
687 | error == 0 ? "successful" : "failed"); |
688 | |
689 | if (bootverbose0) |
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*/FALSE0); |
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 (bootverbose0) { |
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_BASE0x180 + NVRAM_SCB_OFFSET0x2c); |
727 | if (nvram_scb != 0xFF |
728 | && ((ahd_inb_scbram(ahd, SCB_BASE0x180 + 0) == 'A' |
729 | && ahd_inb_scbram(ahd, SCB_BASE0x180 + 1) == 'D' |
730 | && ahd_inb_scbram(ahd, SCB_BASE0x180 + 2) == 'P' |
731 | && ahd_inb_scbram(ahd, SCB_BASE0x180 + 3) == 'T') |
732 | || (ahd_inb_scbram(ahd, SCB_BASE0x180 + 0) == 'B' |
733 | && ahd_inb_scbram(ahd, SCB_BASE0x180 + 1) == 'I' |
734 | && ahd_inb_scbram(ahd, SCB_BASE0x180 + 2) == 'O' |
735 | && ahd_inb_scbram(ahd, SCB_BASE0x180 + 3) == 'S') |
736 | || (ahd_inb_scbram(ahd, SCB_BASE0x180 + 0) == 'A' |
737 | && ahd_inb_scbram(ahd, SCB_BASE0x180 + 1) == 'S' |
738 | && ahd_inb_scbram(ahd, SCB_BASE0x180 + 2) == 'P' |
739 | && ahd_inb_scbram(ahd, SCB_BASE0x180 + 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_BASE0x180+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 (bootverbose0) |
769 | printf("%s: No SEEPROM available.\n", ahd_name(ahd)); |
770 | ahd->flags |= AHD_USEDEFAULTS; |
771 | error = ahd_default_config(ahd); |
772 | adapter_control = CFAUTOTERM0x0001|CFSEAUTOTERM0x0008; |
773 | free(ahd->seep_config, M_DEVBUF2, 0); |
774 | ahd->seep_config = NULL((void *)0); |
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 |
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, DEVCONFIG0x40); |
798 | devconfig &= ~STPWLEVEL0x00000002ul; |
799 | if ((ahd->flags & AHD_STPWLEVEL_A) != 0) |
800 | devconfig |= STPWLEVEL0x00000002ul; |
801 | if (bootverbose0) |
802 | printf("%s: STPWLEVEL is %s\n", |
803 | ahd_name(ahd), (devconfig & STPWLEVEL0x00000002ul) ? "on" : "off"); |
804 | pci_conf_write(pc, tag, DEVCONFIG0x40, 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_CURSENSECTL0x1, 0); |
809 | } |
810 | |
811 | /* |
812 | * Read to sense. Write to set. |
813 | */ |
814 | error = ahd_read_flexport(ahd, FLXADDR_TERMCTL0x0, &termctl); |
815 | if ((adapter_control & CFAUTOTERM0x0001) == 0) { |
816 | if (bootverbose0) |
817 | printf("%s: Manual Primary Termination\n", |
818 | ahd_name(ahd)); |
819 | termctl &= ~(FLX_TERMCTL_ENPRILOW0x1|FLX_TERMCTL_ENPRIHIGH0x2); |
820 | if ((adapter_control & CFSTERM0x0002) != 0) |
821 | termctl |= FLX_TERMCTL_ENPRILOW0x1; |
822 | if ((adapter_control & CFWSTERM0x0004) != 0) |
823 | termctl |= FLX_TERMCTL_ENPRIHIGH0x2; |
824 | } else if (error != 0) { |
825 | printf("%s: Primary Auto-Term Sensing failed! " |
826 | "Using Defaults.\n", ahd_name(ahd)); |
827 | termctl = FLX_TERMCTL_ENPRILOW0x1|FLX_TERMCTL_ENPRIHIGH0x2; |
828 | } |
829 | |
830 | if ((adapter_control & CFSEAUTOTERM0x0008) == 0) { |
831 | if (bootverbose0) |
832 | printf("%s: Manual Secondary Termination\n", |
833 | ahd_name(ahd)); |
834 | termctl &= ~(FLX_TERMCTL_ENSECLOW0x4|FLX_TERMCTL_ENSECHIGH0x8); |
835 | if ((adapter_control & CFSELOWTERM0x0010) != 0) |
836 | termctl |= FLX_TERMCTL_ENSECLOW0x4; |
837 | if ((adapter_control & CFSEHIGHTERM0x0020) != 0) |
838 | termctl |= FLX_TERMCTL_ENSECHIGH0x8; |
839 | } else if (error != 0) { |
840 | printf("%s: Secondary Auto-Term Sensing failed! " |
841 | "Using Defaults.\n", ahd_name(ahd)); |
842 | termctl |= FLX_TERMCTL_ENSECLOW0x4|FLX_TERMCTL_ENSECHIGH0x8; |
843 | } |
844 | |
845 | /* |
846 | * Now set the termination based on what we found. |
847 | */ |
848 | sxfrctl1 = ahd_inb(ahd, SXFRCTL1)(((ahd)->tags[(0x3d) >> 8])->read_1(((ahd)->bshs [(0x3d) >> 8]), ((0x3d) & 0xFF))) & ~STPWEN0x01; |
849 | ahd->flags &= ~AHD_TERM_ENB_A; |
850 | if ((termctl & FLX_TERMCTL_ENPRILOW0x1) != 0) { |
851 | ahd->flags |= AHD_TERM_ENB_A; |
852 | sxfrctl1 |= STPWEN0x01; |
853 | } |
854 | /* Must set the latch once in order to be effective. */ |
855 | ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN)(((ahd)->tags[(0x3d) >> 8])->write_1(((ahd)->bshs [(0x3d) >> 8]), ((0x3d) & 0xFF), (sxfrctl1|0x01))); |
856 | ahd_outb(ahd, SXFRCTL1, sxfrctl1)(((ahd)->tags[(0x3d) >> 8])->write_1(((ahd)->bshs [(0x3d) >> 8]), ((0x3d) & 0xFF), (sxfrctl1))); |
857 | |
858 | error = ahd_write_flexport(ahd, FLXADDR_TERMCTL0x0, termctl); |
859 | if (error != 0) { |
860 | printf("%s: Unable to set termination settings!\n", |
861 | ahd_name(ahd)); |
862 | } else if (bootverbose0) { |
863 | printf("%s: Primary High byte termination %sabled\n", |
864 | ahd_name(ahd), |
865 | (termctl & FLX_TERMCTL_ENPRIHIGH0x2) ? "En" : "Dis"); |
866 | |
867 | printf("%s: Primary Low byte termination %sabled\n", |
868 | ahd_name(ahd), |
869 | (termctl & FLX_TERMCTL_ENPRILOW0x1) ? "En" : "Dis"); |
870 | |
871 | printf("%s: Secondary High byte termination %sabled\n", |
872 | ahd_name(ahd), |
873 | (termctl & FLX_TERMCTL_ENSECHIGH0x8) ? "En" : "Dis"); |
874 | |
875 | printf("%s: Secondary Low byte termination %sabled\n", |
876 | ahd_name(ahd), |
877 | (termctl & FLX_TERMCTL_ENSECLOW0x4) ? "En" : "Dis"); |
878 | } |
879 | return; |
880 | } |
881 | |
882 | #define DPE0x80 0x80 |
883 | #define SSE0x40 0x40 |
884 | #define RMA0x20 0x20 |
885 | #define RTA0x10 0x10 |
886 | #define STA0x08 0x08 |
887 | #define DPR0x01 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 |
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)(((ahd)->tags[(0x01) >> 8])->read_1(((ahd)->bshs [(0x01) >> 8]), ((0x01) & 0xFF))); |
946 | |
947 | if ((intstat & SPLTINT0x01) != 0) |
948 | ahd_pci_split_intr(ahd, intstat); |
949 | |
950 | if ((intstat & PCIINT0x10) == 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 = DF0PCISTAT0xa0; i < 8; i++, reg++) { |
958 | |
959 | if (i == 5) |
960 | continue; |
961 | pci_status[i] = ahd_inb(ahd, reg)(((ahd)->tags[(reg) >> 8])->read_1(((ahd)->bshs [(reg) >> 8]), ((reg) & 0xFF))); |
962 | /* Clear latched errors. So our interrupt deasserts. */ |
963 | ahd_outb(ahd, reg, pci_status[i])(((ahd)->tags[(reg) >> 8])->write_1(((ahd)->bshs [(reg) >> 8]), ((reg) & 0xFF), (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_REG0x04); |
986 | pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG0x04 , pci_status1); |
987 | |
988 | ahd_restore_modes(ahd, saved_modes); |
989 | ahd_outb(ahd, CLRINT, CLRPCIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x10))); |
990 | ahd_unpause(ahd); |
991 | |
992 | return; |
993 | } |
994 | |
995 | void |
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)(((ahd)->tags[(0x96) >> 8])->read_1(((ahd)->bshs [(0x96) >> 8]), ((0x96) & 0xFF))); |
1021 | split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1)(((ahd)->tags[(0x97) >> 8])->read_1(((ahd)->bshs [(0x97) >> 8]), ((0x97) & 0xFF))); |
1022 | /* Clear latched errors. So our interrupt deasserts. */ |
1023 | ahd_outb(ahd, DCHSPLTSTAT0, split_status[i])(((ahd)->tags[(0x96) >> 8])->write_1(((ahd)->bshs [(0x96) >> 8]), ((0x96) & 0xFF), (split_status[i])) ); |
1024 | ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i])(((ahd)->tags[(0x97) >> 8])->write_1(((ahd)->bshs [(0x97) >> 8]), ((0x97) & 0xFF), (split_status1[i]) )); |
1025 | if (i > 1) |
1026 | continue; |
1027 | sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0)(((ahd)->tags[(0x9e) >> 8])->read_1(((ahd)->bshs [(0x9e) >> 8]), ((0x9e) & 0xFF))); |
1028 | sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1)(((ahd)->tags[(0x9f) >> 8])->read_1(((ahd)->bshs [(0x9f) >> 8]), ((0x9f) & 0xFF))); |
1029 | /* Clear latched errors. So our interrupt deasserts. */ |
1030 | ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i])(((ahd)->tags[(0x9e) >> 8])->write_1(((ahd)->bshs [(0x9e) >> 8]), ((0x9e) & 0xFF), (sg_split_status[i ]))); |
1031 | ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i])(((ahd)->tags[(0x9f) >> 8])->write_1(((ahd)->bshs [(0x9f) >> 8]), ((0x9f) & 0xFF), (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)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x01))); |
1059 | ahd_restore_modes(ahd, saved_modes); |
1060 | } |
1061 | |
1062 | int |
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 |
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 |
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 |
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)(((pa->pa_class) >> 0) & 0xff); |
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_A40x3) { |
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_REG0x04, 0); |
1101 | return (ENXIO6); |
1102 | } |
1103 | |
1104 | ahd->channel = (pa->pa_function == 1) ? 'B' : 'A'; |
1105 | if (rev < ID_AIC7902_PCI_REV_B00x10) { |
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)do { (ahd)->iocell_opts[(0x04 - 0x04)] &= ~0x07; (ahd) ->iocell_opts[(0x04 - 0x04)] |= (((0x06) << 0x00) & 0x07); } while (0); |
1125 | |
1126 | if ((ahd->flags & AHD_HP_BOARD) == 0) |
1127 | AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA)do { (ahd)->iocell_opts[(0x04 - 0x04)] &= ~0x78; (ahd) ->iocell_opts[(0x04 - 0x04)] |= (((0x08) << 0x03) & 0x78); } while (0); |
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)do { (ahd)->iocell_opts[(0x04 - 0x04)] &= ~0x07; (ahd) ->iocell_opts[(0x04 - 0x04)] |= (((0x06) << 0x00) & 0x07); } while (0); |
1146 | AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB)do { (ahd)->iocell_opts[(0x04 - 0x04)] &= ~0x78; (ahd) ->iocell_opts[(0x04 - 0x04)] |= (((0x08) << 0x03) & 0x78); } while (0); |
1147 | AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF)do { (ahd)->iocell_opts[(0x06 - 0x04)] &= ~0x07; (ahd) ->iocell_opts[(0x06 - 0x04)] |= (((0x07) << 0x00) & 0x07); } while (0); |
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, DEVCONFIG10x44); |
1156 | pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG10x44, devconfig1|PREQDIS0x01); |
1157 | devconfig1 = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG10x44); |
1158 | } |
1159 | |
1160 | return (0); |
1161 | } |