diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/scsi/aic7xxx/aic79xx_pci.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_pci.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_pci.c | 987 |
1 files changed, 987 insertions, 0 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c new file mode 100644 index 000000000000..4c3bb7bb8420 --- /dev/null +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c | |||
@@ -0,0 +1,987 @@ | |||
1 | /* | ||
2 | * Product specific probe and attach routines for: | ||
3 | * aic7901 and aic7902 SCSI controllers | ||
4 | * | ||
5 | * Copyright (c) 1994-2001 Justin T. Gibbs. | ||
6 | * Copyright (c) 2000-2002 Adaptec Inc. | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * Redistribution and use in source and binary forms, with or without | ||
10 | * modification, are permitted provided that the following conditions | ||
11 | * are met: | ||
12 | * 1. Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions, and the following disclaimer, | ||
14 | * without modification. | ||
15 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
16 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
17 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
18 | * including a substantially similar Disclaimer requirement for further | ||
19 | * binary redistribution. | ||
20 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
21 | * of any contributors may be used to endorse or promote products derived | ||
22 | * from this software without specific prior written permission. | ||
23 | * | ||
24 | * Alternatively, this software may be distributed under the terms of the | ||
25 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
26 | * Software Foundation. | ||
27 | * | ||
28 | * NO WARRANTY | ||
29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
30 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
31 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
32 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
33 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
34 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
35 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
36 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
37 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
38 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
39 | * POSSIBILITY OF SUCH DAMAGES. | ||
40 | * | ||
41 | * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#77 $ | ||
42 | * | ||
43 | * $FreeBSD$ | ||
44 | */ | ||
45 | |||
46 | #ifdef __linux__ | ||
47 | #include "aic79xx_osm.h" | ||
48 | #include "aic79xx_inline.h" | ||
49 | #else | ||
50 | #include <dev/aic7xxx/aic79xx_osm.h> | ||
51 | #include <dev/aic7xxx/aic79xx_inline.h> | ||
52 | #endif | ||
53 | |||
54 | #include "aic79xx_pci.h" | ||
55 | |||
56 | static __inline uint64_t | ||
57 | ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) | ||
58 | { | ||
59 | uint64_t id; | ||
60 | |||
61 | id = subvendor | ||
62 | | (subdevice << 16) | ||
63 | | ((uint64_t)vendor << 32) | ||
64 | | ((uint64_t)device << 48); | ||
65 | |||
66 | return (id); | ||
67 | } | ||
68 | |||
69 | #define ID_AIC7902_PCI_REV_A4 0x3 | ||
70 | #define ID_AIC7902_PCI_REV_B0 0x10 | ||
71 | #define SUBID_HP 0x0E11 | ||
72 | |||
73 | #define DEVID_9005_HOSTRAID(id) ((id) & 0x80) | ||
74 | |||
75 | #define DEVID_9005_TYPE(id) ((id) & 0xF) | ||
76 | #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ | ||
77 | #define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */ | ||
78 | #define DEVID_9005_TYPE_IROC 0x8 /* Raid(0,1,10) Card */ | ||
79 | #define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ | ||
80 | |||
81 | #define DEVID_9005_MFUNC(id) ((id) & 0x10) | ||
82 | |||
83 | #define DEVID_9005_PACKETIZED(id) ((id) & 0x8000) | ||
84 | |||
85 | #define SUBID_9005_TYPE(id) ((id) & 0xF) | ||
86 | #define SUBID_9005_TYPE_HBA 0x0 /* Standard Card */ | ||
87 | #define SUBID_9005_TYPE_MB 0xF /* On Motherboard */ | ||
88 | |||
89 | #define SUBID_9005_AUTOTERM(id) (((id) & 0x10) == 0) | ||
90 | |||
91 | #define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20) | ||
92 | |||
93 | #define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6) | ||
94 | #define SUBID_9005_SEEPTYPE_NONE 0x0 | ||
95 | #define SUBID_9005_SEEPTYPE_4K 0x1 | ||
96 | |||
97 | static ahd_device_setup_t ahd_aic7901_setup; | ||
98 | static ahd_device_setup_t ahd_aic7901A_setup; | ||
99 | static ahd_device_setup_t ahd_aic7902_setup; | ||
100 | static ahd_device_setup_t ahd_aic790X_setup; | ||
101 | |||
102 | struct ahd_pci_identity ahd_pci_ident_table [] = | ||
103 | { | ||
104 | /* aic7901 based controllers */ | ||
105 | { | ||
106 | ID_AHA_29320A, | ||
107 | ID_ALL_MASK, | ||
108 | "Adaptec 29320A Ultra320 SCSI adapter", | ||
109 | ahd_aic7901_setup | ||
110 | }, | ||
111 | { | ||
112 | ID_AHA_29320ALP, | ||
113 | ID_ALL_MASK, | ||
114 | "Adaptec 29320ALP Ultra320 SCSI adapter", | ||
115 | ahd_aic7901_setup | ||
116 | }, | ||
117 | /* aic7902 based controllers */ | ||
118 | { | ||
119 | ID_AHA_29320, | ||
120 | ID_ALL_MASK, | ||
121 | "Adaptec 29320 Ultra320 SCSI adapter", | ||
122 | ahd_aic7902_setup | ||
123 | }, | ||
124 | { | ||
125 | ID_AHA_29320B, | ||
126 | ID_ALL_MASK, | ||
127 | "Adaptec 29320B Ultra320 SCSI adapter", | ||
128 | ahd_aic7902_setup | ||
129 | }, | ||
130 | { | ||
131 | ID_AHA_29320LP, | ||
132 | ID_ALL_MASK, | ||
133 | "Adaptec 29320LP Ultra320 SCSI adapter", | ||
134 | ahd_aic7901A_setup | ||
135 | }, | ||
136 | { | ||
137 | ID_AHA_39320, | ||
138 | ID_ALL_MASK, | ||
139 | "Adaptec 39320 Ultra320 SCSI adapter", | ||
140 | ahd_aic7902_setup | ||
141 | }, | ||
142 | { | ||
143 | ID_AHA_39320_B, | ||
144 | ID_ALL_MASK, | ||
145 | "Adaptec 39320 Ultra320 SCSI adapter", | ||
146 | ahd_aic7902_setup | ||
147 | }, | ||
148 | { | ||
149 | ID_AHA_39320A, | ||
150 | ID_ALL_MASK, | ||
151 | "Adaptec 39320A Ultra320 SCSI adapter", | ||
152 | ahd_aic7902_setup | ||
153 | }, | ||
154 | { | ||
155 | ID_AHA_39320D, | ||
156 | ID_ALL_MASK, | ||
157 | "Adaptec 39320D Ultra320 SCSI adapter", | ||
158 | ahd_aic7902_setup | ||
159 | }, | ||
160 | { | ||
161 | ID_AHA_39320D_HP, | ||
162 | ID_ALL_MASK, | ||
163 | "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter", | ||
164 | ahd_aic7902_setup | ||
165 | }, | ||
166 | { | ||
167 | ID_AHA_39320D_B, | ||
168 | ID_ALL_MASK, | ||
169 | "Adaptec 39320D Ultra320 SCSI adapter", | ||
170 | ahd_aic7902_setup | ||
171 | }, | ||
172 | { | ||
173 | ID_AHA_39320D_B_HP, | ||
174 | ID_ALL_MASK, | ||
175 | "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter", | ||
176 | ahd_aic7902_setup | ||
177 | }, | ||
178 | /* Generic chip probes for devices we don't know 'exactly' */ | ||
179 | { | ||
180 | ID_AIC7901 & ID_9005_GENERIC_MASK, | ||
181 | ID_9005_GENERIC_MASK, | ||
182 | "Adaptec AIC7901 Ultra320 SCSI adapter", | ||
183 | ahd_aic7901_setup | ||
184 | }, | ||
185 | { | ||
186 | ID_AIC7901A & ID_DEV_VENDOR_MASK, | ||
187 | ID_DEV_VENDOR_MASK, | ||
188 | "Adaptec AIC7901A Ultra320 SCSI adapter", | ||
189 | ahd_aic7901A_setup | ||
190 | }, | ||
191 | { | ||
192 | ID_AIC7902 & ID_9005_GENERIC_MASK, | ||
193 | ID_9005_GENERIC_MASK, | ||
194 | "Adaptec AIC7902 Ultra320 SCSI adapter", | ||
195 | ahd_aic7902_setup | ||
196 | } | ||
197 | }; | ||
198 | |||
199 | const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table); | ||
200 | |||
201 | #define DEVCONFIG 0x40 | ||
202 | #define PCIXINITPAT 0x0000E000ul | ||
203 | #define PCIXINIT_PCI33_66 0x0000E000ul | ||
204 | #define PCIXINIT_PCIX50_66 0x0000C000ul | ||
205 | #define PCIXINIT_PCIX66_100 0x0000A000ul | ||
206 | #define PCIXINIT_PCIX100_133 0x00008000ul | ||
207 | #define PCI_BUS_MODES_INDEX(devconfig) \ | ||
208 | (((devconfig) & PCIXINITPAT) >> 13) | ||
209 | static const char *pci_bus_modes[] = | ||
210 | { | ||
211 | "PCI bus mode unknown", | ||
212 | "PCI bus mode unknown", | ||
213 | "PCI bus mode unknown", | ||
214 | "PCI bus mode unknown", | ||
215 | "PCI-X 101-133Mhz", | ||
216 | "PCI-X 67-100Mhz", | ||
217 | "PCI-X 50-66Mhz", | ||
218 | "PCI 33 or 66Mhz" | ||
219 | }; | ||
220 | |||
221 | #define TESTMODE 0x00000800ul | ||
222 | #define IRDY_RST 0x00000200ul | ||
223 | #define FRAME_RST 0x00000100ul | ||
224 | #define PCI64BIT 0x00000080ul | ||
225 | #define MRDCEN 0x00000040ul | ||
226 | #define ENDIANSEL 0x00000020ul | ||
227 | #define MIXQWENDIANEN 0x00000008ul | ||
228 | #define DACEN 0x00000004ul | ||
229 | #define STPWLEVEL 0x00000002ul | ||
230 | #define QWENDIANSEL 0x00000001ul | ||
231 | |||
232 | #define DEVCONFIG1 0x44 | ||
233 | #define PREQDIS 0x01 | ||
234 | |||
235 | #define CSIZE_LATTIME 0x0c | ||
236 | #define CACHESIZE 0x000000fful | ||
237 | #define LATTIME 0x0000ff00ul | ||
238 | |||
239 | static int ahd_check_extport(struct ahd_softc *ahd); | ||
240 | static void ahd_configure_termination(struct ahd_softc *ahd, | ||
241 | u_int adapter_control); | ||
242 | static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat); | ||
243 | |||
244 | struct ahd_pci_identity * | ||
245 | ahd_find_pci_device(ahd_dev_softc_t pci) | ||
246 | { | ||
247 | uint64_t full_id; | ||
248 | uint16_t device; | ||
249 | uint16_t vendor; | ||
250 | uint16_t subdevice; | ||
251 | uint16_t subvendor; | ||
252 | struct ahd_pci_identity *entry; | ||
253 | u_int i; | ||
254 | |||
255 | vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); | ||
256 | device = ahd_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); | ||
257 | subvendor = ahd_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); | ||
258 | subdevice = ahd_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); | ||
259 | full_id = ahd_compose_id(device, | ||
260 | vendor, | ||
261 | subdevice, | ||
262 | subvendor); | ||
263 | |||
264 | /* | ||
265 | * Controllers, mask out the IROC/HostRAID bit | ||
266 | */ | ||
267 | |||
268 | full_id &= ID_ALL_IROC_MASK; | ||
269 | |||
270 | for (i = 0; i < ahd_num_pci_devs; i++) { | ||
271 | entry = &ahd_pci_ident_table[i]; | ||
272 | if (entry->full_id == (full_id & entry->id_mask)) { | ||
273 | /* Honor exclusion entries. */ | ||
274 | if (entry->name == NULL) | ||
275 | return (NULL); | ||
276 | return (entry); | ||
277 | } | ||
278 | } | ||
279 | return (NULL); | ||
280 | } | ||
281 | |||
282 | int | ||
283 | ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) | ||
284 | { | ||
285 | struct scb_data *shared_scb_data; | ||
286 | u_long l; | ||
287 | u_int command; | ||
288 | uint32_t devconfig; | ||
289 | uint16_t subvendor; | ||
290 | int error; | ||
291 | |||
292 | shared_scb_data = NULL; | ||
293 | ahd->description = entry->name; | ||
294 | /* | ||
295 | * Record if this is an HP board. | ||
296 | */ | ||
297 | subvendor = ahd_pci_read_config(ahd->dev_softc, | ||
298 | PCIR_SUBVEND_0, /*bytes*/2); | ||
299 | if (subvendor == SUBID_HP) | ||
300 | ahd->flags |= AHD_HP_BOARD; | ||
301 | |||
302 | error = entry->setup(ahd); | ||
303 | if (error != 0) | ||
304 | return (error); | ||
305 | |||
306 | devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); | ||
307 | if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { | ||
308 | ahd->chip |= AHD_PCI; | ||
309 | /* Disable PCIX workarounds when running in PCI mode. */ | ||
310 | ahd->bugs &= ~AHD_PCIX_BUG_MASK; | ||
311 | } else { | ||
312 | ahd->chip |= AHD_PCIX; | ||
313 | } | ||
314 | ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; | ||
315 | |||
316 | ahd_power_state_change(ahd, AHD_POWER_STATE_D0); | ||
317 | |||
318 | error = ahd_pci_map_registers(ahd); | ||
319 | if (error != 0) | ||
320 | return (error); | ||
321 | |||
322 | /* | ||
323 | * If we need to support high memory, enable dual | ||
324 | * address cycles. This bit must be set to enable | ||
325 | * high address bit generation even if we are on a | ||
326 | * 64bit bus (PCI64BIT set in devconfig). | ||
327 | */ | ||
328 | if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) { | ||
329 | uint32_t devconfig; | ||
330 | |||
331 | if (bootverbose) | ||
332 | printf("%s: Enabling 39Bit Addressing\n", | ||
333 | ahd_name(ahd)); | ||
334 | devconfig = ahd_pci_read_config(ahd->dev_softc, | ||
335 | DEVCONFIG, /*bytes*/4); | ||
336 | devconfig |= DACEN; | ||
337 | ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, | ||
338 | devconfig, /*bytes*/4); | ||
339 | } | ||
340 | |||
341 | /* Ensure busmastering is enabled */ | ||
342 | command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); | ||
343 | command |= PCIM_CMD_BUSMASTEREN; | ||
344 | ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2); | ||
345 | |||
346 | error = ahd_softc_init(ahd); | ||
347 | if (error != 0) | ||
348 | return (error); | ||
349 | |||
350 | ahd->bus_intr = ahd_pci_intr; | ||
351 | |||
352 | error = ahd_reset(ahd, /*reinit*/FALSE); | ||
353 | if (error != 0) | ||
354 | return (ENXIO); | ||
355 | |||
356 | ahd->pci_cachesize = | ||
357 | ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, | ||
358 | /*bytes*/1) & CACHESIZE; | ||
359 | ahd->pci_cachesize *= 4; | ||
360 | |||
361 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | ||
362 | /* See if we have a SEEPROM and perform auto-term */ | ||
363 | error = ahd_check_extport(ahd); | ||
364 | if (error != 0) | ||
365 | return (error); | ||
366 | |||
367 | /* Core initialization */ | ||
368 | error = ahd_init(ahd); | ||
369 | if (error != 0) | ||
370 | return (error); | ||
371 | |||
372 | /* | ||
373 | * Allow interrupts now that we are completely setup. | ||
374 | */ | ||
375 | error = ahd_pci_map_int(ahd); | ||
376 | if (error != 0) | ||
377 | return (error); | ||
378 | |||
379 | ahd_list_lock(&l); | ||
380 | /* | ||
381 | * Link this softc in with all other ahd instances. | ||
382 | */ | ||
383 | ahd_softc_insert(ahd); | ||
384 | ahd_list_unlock(&l); | ||
385 | return (0); | ||
386 | } | ||
387 | |||
388 | /* | ||
389 | * Perform some simple tests that should catch situations where | ||
390 | * our registers are invalidly mapped. | ||
391 | */ | ||
392 | int | ||
393 | ahd_pci_test_register_access(struct ahd_softc *ahd) | ||
394 | { | ||
395 | uint32_t cmd; | ||
396 | u_int targpcistat; | ||
397 | u_int pci_status1; | ||
398 | int error; | ||
399 | uint8_t hcntrl; | ||
400 | |||
401 | error = EIO; | ||
402 | |||
403 | /* | ||
404 | * Enable PCI error interrupt status, but suppress NMIs | ||
405 | * generated by SERR raised due to target aborts. | ||
406 | */ | ||
407 | cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); | ||
408 | ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, | ||
409 | cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); | ||
410 | |||
411 | /* | ||
412 | * First a simple test to see if any | ||
413 | * registers can be read. Reading | ||
414 | * HCNTRL has no side effects and has | ||
415 | * at least one bit that is guaranteed to | ||
416 | * be zero so it is a good register to | ||
417 | * use for this test. | ||
418 | */ | ||
419 | hcntrl = ahd_inb(ahd, HCNTRL); | ||
420 | if (hcntrl == 0xFF) | ||
421 | goto fail; | ||
422 | |||
423 | /* | ||
424 | * Next create a situation where write combining | ||
425 | * or read prefetching could be initiated by the | ||
426 | * CPU or host bridge. Our device does not support | ||
427 | * either, so look for data corruption and/or flaged | ||
428 | * PCI errors. First pause without causing another | ||
429 | * chip reset. | ||
430 | */ | ||
431 | hcntrl &= ~CHIPRST; | ||
432 | ahd_outb(ahd, HCNTRL, hcntrl|PAUSE); | ||
433 | while (ahd_is_paused(ahd) == 0) | ||
434 | ; | ||
435 | |||
436 | /* Clear any PCI errors that occurred before our driver attached. */ | ||
437 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); | ||
438 | targpcistat = ahd_inb(ahd, TARGPCISTAT); | ||
439 | ahd_outb(ahd, TARGPCISTAT, targpcistat); | ||
440 | pci_status1 = ahd_pci_read_config(ahd->dev_softc, | ||
441 | PCIR_STATUS + 1, /*bytes*/1); | ||
442 | ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, | ||
443 | pci_status1, /*bytes*/1); | ||
444 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | ||
445 | ahd_outb(ahd, CLRINT, CLRPCIINT); | ||
446 | |||
447 | ahd_outb(ahd, SEQCTL0, PERRORDIS); | ||
448 | ahd_outl(ahd, SRAM_BASE, 0x5aa555aa); | ||
449 | if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa) | ||
450 | goto fail; | ||
451 | |||
452 | if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) { | ||
453 | u_int targpcistat; | ||
454 | |||
455 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); | ||
456 | targpcistat = ahd_inb(ahd, TARGPCISTAT); | ||
457 | if ((targpcistat & STA) != 0) | ||
458 | goto fail; | ||
459 | } | ||
460 | |||
461 | error = 0; | ||
462 | |||
463 | fail: | ||
464 | if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) { | ||
465 | |||
466 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); | ||
467 | targpcistat = ahd_inb(ahd, TARGPCISTAT); | ||
468 | |||
469 | /* Silently clear any latched errors. */ | ||
470 | ahd_outb(ahd, TARGPCISTAT, targpcistat); | ||
471 | pci_status1 = ahd_pci_read_config(ahd->dev_softc, | ||
472 | PCIR_STATUS + 1, /*bytes*/1); | ||
473 | ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, | ||
474 | pci_status1, /*bytes*/1); | ||
475 | ahd_outb(ahd, CLRINT, CLRPCIINT); | ||
476 | } | ||
477 | ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS); | ||
478 | ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); | ||
479 | return (error); | ||
480 | } | ||
481 | |||
482 | /* | ||
483 | * Check the external port logic for a serial eeprom | ||
484 | * and termination/cable detection contrls. | ||
485 | */ | ||
486 | static int | ||
487 | ahd_check_extport(struct ahd_softc *ahd) | ||
488 | { | ||
489 | struct vpd_config vpd; | ||
490 | struct seeprom_config *sc; | ||
491 | u_int adapter_control; | ||
492 | int have_seeprom; | ||
493 | int error; | ||
494 | |||
495 | sc = ahd->seep_config; | ||
496 | have_seeprom = ahd_acquire_seeprom(ahd); | ||
497 | if (have_seeprom) { | ||
498 | u_int start_addr; | ||
499 | |||
500 | /* | ||
501 | * Fetch VPD for this function and parse it. | ||
502 | */ | ||
503 | if (bootverbose) | ||
504 | printf("%s: Reading VPD from SEEPROM...", | ||
505 | ahd_name(ahd)); | ||
506 | |||
507 | /* Address is always in units of 16bit words */ | ||
508 | start_addr = ((2 * sizeof(*sc)) | ||
509 | + (sizeof(vpd) * (ahd->channel - 'A'))) / 2; | ||
510 | |||
511 | error = ahd_read_seeprom(ahd, (uint16_t *)&vpd, | ||
512 | start_addr, sizeof(vpd)/2, | ||
513 | /*bytestream*/TRUE); | ||
514 | if (error == 0) | ||
515 | error = ahd_parse_vpddata(ahd, &vpd); | ||
516 | if (bootverbose) | ||
517 | printf("%s: VPD parsing %s\n", | ||
518 | ahd_name(ahd), | ||
519 | error == 0 ? "successful" : "failed"); | ||
520 | |||
521 | if (bootverbose) | ||
522 | printf("%s: Reading SEEPROM...", ahd_name(ahd)); | ||
523 | |||
524 | /* Address is always in units of 16bit words */ | ||
525 | start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A'); | ||
526 | |||
527 | error = ahd_read_seeprom(ahd, (uint16_t *)sc, | ||
528 | start_addr, sizeof(*sc)/2, | ||
529 | /*bytestream*/FALSE); | ||
530 | |||
531 | if (error != 0) { | ||
532 | printf("Unable to read SEEPROM\n"); | ||
533 | have_seeprom = 0; | ||
534 | } else { | ||
535 | have_seeprom = ahd_verify_cksum(sc); | ||
536 | |||
537 | if (bootverbose) { | ||
538 | if (have_seeprom == 0) | ||
539 | printf ("checksum error\n"); | ||
540 | else | ||
541 | printf ("done.\n"); | ||
542 | } | ||
543 | } | ||
544 | ahd_release_seeprom(ahd); | ||
545 | } | ||
546 | |||
547 | if (!have_seeprom) { | ||
548 | u_int nvram_scb; | ||
549 | |||
550 | /* | ||
551 | * Pull scratch ram settings and treat them as | ||
552 | * if they are the contents of an seeprom if | ||
553 | * the 'ADPT', 'BIOS', or 'ASPI' signature is found | ||
554 | * in SCB 0xFF. We manually compose the data as 16bit | ||
555 | * values to avoid endian issues. | ||
556 | */ | ||
557 | ahd_set_scbptr(ahd, 0xFF); | ||
558 | nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET); | ||
559 | if (nvram_scb != 0xFF | ||
560 | && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A' | ||
561 | && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D' | ||
562 | && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P' | ||
563 | && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T') | ||
564 | || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B' | ||
565 | && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I' | ||
566 | && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O' | ||
567 | && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S') | ||
568 | || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A' | ||
569 | && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S' | ||
570 | && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P' | ||
571 | && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) { | ||
572 | uint16_t *sc_data; | ||
573 | int i; | ||
574 | |||
575 | ahd_set_scbptr(ahd, nvram_scb); | ||
576 | sc_data = (uint16_t *)sc; | ||
577 | for (i = 0; i < 64; i += 2) | ||
578 | *sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i); | ||
579 | have_seeprom = ahd_verify_cksum(sc); | ||
580 | if (have_seeprom) | ||
581 | ahd->flags |= AHD_SCB_CONFIG_USED; | ||
582 | } | ||
583 | } | ||
584 | |||
585 | #if AHD_DEBUG | ||
586 | if (have_seeprom != 0 | ||
587 | && (ahd_debug & AHD_DUMP_SEEPROM) != 0) { | ||
588 | uint16_t *sc_data; | ||
589 | int i; | ||
590 | |||
591 | printf("%s: Seeprom Contents:", ahd_name(ahd)); | ||
592 | sc_data = (uint16_t *)sc; | ||
593 | for (i = 0; i < (sizeof(*sc)); i += 2) | ||
594 | printf("\n\t0x%.4x", sc_data[i]); | ||
595 | printf("\n"); | ||
596 | } | ||
597 | #endif | ||
598 | |||
599 | if (!have_seeprom) { | ||
600 | if (bootverbose) | ||
601 | printf("%s: No SEEPROM available.\n", ahd_name(ahd)); | ||
602 | ahd->flags |= AHD_USEDEFAULTS; | ||
603 | error = ahd_default_config(ahd); | ||
604 | adapter_control = CFAUTOTERM|CFSEAUTOTERM; | ||
605 | free(ahd->seep_config, M_DEVBUF); | ||
606 | ahd->seep_config = NULL; | ||
607 | } else { | ||
608 | error = ahd_parse_cfgdata(ahd, sc); | ||
609 | adapter_control = sc->adapter_control; | ||
610 | } | ||
611 | if (error != 0) | ||
612 | return (error); | ||
613 | |||
614 | ahd_configure_termination(ahd, adapter_control); | ||
615 | |||
616 | return (0); | ||
617 | } | ||
618 | |||
619 | static void | ||
620 | ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) | ||
621 | { | ||
622 | int error; | ||
623 | u_int sxfrctl1; | ||
624 | uint8_t termctl; | ||
625 | uint32_t devconfig; | ||
626 | |||
627 | devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); | ||
628 | devconfig &= ~STPWLEVEL; | ||
629 | if ((ahd->flags & AHD_STPWLEVEL_A) != 0) | ||
630 | devconfig |= STPWLEVEL; | ||
631 | if (bootverbose) | ||
632 | printf("%s: STPWLEVEL is %s\n", | ||
633 | ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off"); | ||
634 | ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); | ||
635 | |||
636 | /* Make sure current sensing is off. */ | ||
637 | if ((ahd->flags & AHD_CURRENT_SENSING) != 0) { | ||
638 | (void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0); | ||
639 | } | ||
640 | |||
641 | /* | ||
642 | * Read to sense. Write to set. | ||
643 | */ | ||
644 | error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl); | ||
645 | if ((adapter_control & CFAUTOTERM) == 0) { | ||
646 | if (bootverbose) | ||
647 | printf("%s: Manual Primary Termination\n", | ||
648 | ahd_name(ahd)); | ||
649 | termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH); | ||
650 | if ((adapter_control & CFSTERM) != 0) | ||
651 | termctl |= FLX_TERMCTL_ENPRILOW; | ||
652 | if ((adapter_control & CFWSTERM) != 0) | ||
653 | termctl |= FLX_TERMCTL_ENPRIHIGH; | ||
654 | } else if (error != 0) { | ||
655 | printf("%s: Primary Auto-Term Sensing failed! " | ||
656 | "Using Defaults.\n", ahd_name(ahd)); | ||
657 | termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH; | ||
658 | } | ||
659 | |||
660 | if ((adapter_control & CFSEAUTOTERM) == 0) { | ||
661 | if (bootverbose) | ||
662 | printf("%s: Manual Secondary Termination\n", | ||
663 | ahd_name(ahd)); | ||
664 | termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH); | ||
665 | if ((adapter_control & CFSELOWTERM) != 0) | ||
666 | termctl |= FLX_TERMCTL_ENSECLOW; | ||
667 | if ((adapter_control & CFSEHIGHTERM) != 0) | ||
668 | termctl |= FLX_TERMCTL_ENSECHIGH; | ||
669 | } else if (error != 0) { | ||
670 | printf("%s: Secondary Auto-Term Sensing failed! " | ||
671 | "Using Defaults.\n", ahd_name(ahd)); | ||
672 | termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH; | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * Now set the termination based on what we found. | ||
677 | */ | ||
678 | sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; | ||
679 | if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { | ||
680 | ahd->flags |= AHD_TERM_ENB_A; | ||
681 | sxfrctl1 |= STPWEN; | ||
682 | } | ||
683 | /* Must set the latch once in order to be effective. */ | ||
684 | ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN); | ||
685 | ahd_outb(ahd, SXFRCTL1, sxfrctl1); | ||
686 | |||
687 | error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl); | ||
688 | if (error != 0) { | ||
689 | printf("%s: Unable to set termination settings!\n", | ||
690 | ahd_name(ahd)); | ||
691 | } else if (bootverbose) { | ||
692 | printf("%s: Primary High byte termination %sabled\n", | ||
693 | ahd_name(ahd), | ||
694 | (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis"); | ||
695 | |||
696 | printf("%s: Primary Low byte termination %sabled\n", | ||
697 | ahd_name(ahd), | ||
698 | (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis"); | ||
699 | |||
700 | printf("%s: Secondary High byte termination %sabled\n", | ||
701 | ahd_name(ahd), | ||
702 | (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis"); | ||
703 | |||
704 | printf("%s: Secondary Low byte termination %sabled\n", | ||
705 | ahd_name(ahd), | ||
706 | (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis"); | ||
707 | } | ||
708 | return; | ||
709 | } | ||
710 | |||
711 | #define DPE 0x80 | ||
712 | #define SSE 0x40 | ||
713 | #define RMA 0x20 | ||
714 | #define RTA 0x10 | ||
715 | #define STA 0x08 | ||
716 | #define DPR 0x01 | ||
717 | |||
718 | static const char *split_status_source[] = | ||
719 | { | ||
720 | "DFF0", | ||
721 | "DFF1", | ||
722 | "OVLY", | ||
723 | "CMC", | ||
724 | }; | ||
725 | |||
726 | static const char *pci_status_source[] = | ||
727 | { | ||
728 | "DFF0", | ||
729 | "DFF1", | ||
730 | "SG", | ||
731 | "CMC", | ||
732 | "OVLY", | ||
733 | "NONE", | ||
734 | "MSI", | ||
735 | "TARG" | ||
736 | }; | ||
737 | |||
738 | static const char *split_status_strings[] = | ||
739 | { | ||
740 | "%s: Received split response in %s.\n", | ||
741 | "%s: Received split completion error message in %s\n", | ||
742 | "%s: Receive overrun in %s\n", | ||
743 | "%s: Count not complete in %s\n", | ||
744 | "%s: Split completion data bucket in %s\n", | ||
745 | "%s: Split completion address error in %s\n", | ||
746 | "%s: Split completion byte count error in %s\n", | ||
747 | "%s: Signaled Target-abort to early terminate a split in %s\n" | ||
748 | }; | ||
749 | |||
750 | static const char *pci_status_strings[] = | ||
751 | { | ||
752 | "%s: Data Parity Error has been reported via PERR# in %s\n", | ||
753 | "%s: Target initial wait state error in %s\n", | ||
754 | "%s: Split completion read data parity error in %s\n", | ||
755 | "%s: Split completion address attribute parity error in %s\n", | ||
756 | "%s: Received a Target Abort in %s\n", | ||
757 | "%s: Received a Master Abort in %s\n", | ||
758 | "%s: Signal System Error Detected in %s\n", | ||
759 | "%s: Address or Write Phase Parity Error Detected in %s.\n" | ||
760 | }; | ||
761 | |||
762 | void | ||
763 | ahd_pci_intr(struct ahd_softc *ahd) | ||
764 | { | ||
765 | uint8_t pci_status[8]; | ||
766 | ahd_mode_state saved_modes; | ||
767 | u_int pci_status1; | ||
768 | u_int intstat; | ||
769 | u_int i; | ||
770 | u_int reg; | ||
771 | |||
772 | intstat = ahd_inb(ahd, INTSTAT); | ||
773 | |||
774 | if ((intstat & SPLTINT) != 0) | ||
775 | ahd_pci_split_intr(ahd, intstat); | ||
776 | |||
777 | if ((intstat & PCIINT) == 0) | ||
778 | return; | ||
779 | |||
780 | printf("%s: PCI error Interrupt\n", ahd_name(ahd)); | ||
781 | saved_modes = ahd_save_modes(ahd); | ||
782 | ahd_dump_card_state(ahd); | ||
783 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); | ||
784 | for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) { | ||
785 | |||
786 | if (i == 5) | ||
787 | continue; | ||
788 | pci_status[i] = ahd_inb(ahd, reg); | ||
789 | /* Clear latched errors. So our interrupt deasserts. */ | ||
790 | ahd_outb(ahd, reg, pci_status[i]); | ||
791 | } | ||
792 | |||
793 | for (i = 0; i < 8; i++) { | ||
794 | u_int bit; | ||
795 | |||
796 | if (i == 5) | ||
797 | continue; | ||
798 | |||
799 | for (bit = 0; bit < 8; bit++) { | ||
800 | |||
801 | if ((pci_status[i] & (0x1 << bit)) != 0) { | ||
802 | static const char *s; | ||
803 | |||
804 | s = pci_status_strings[bit]; | ||
805 | if (i == 7/*TARG*/ && bit == 3) | ||
806 | s = "%s: Signaled Target Abort\n"; | ||
807 | printf(s, ahd_name(ahd), pci_status_source[i]); | ||
808 | } | ||
809 | } | ||
810 | } | ||
811 | pci_status1 = ahd_pci_read_config(ahd->dev_softc, | ||
812 | PCIR_STATUS + 1, /*bytes*/1); | ||
813 | ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, | ||
814 | pci_status1, /*bytes*/1); | ||
815 | ahd_restore_modes(ahd, saved_modes); | ||
816 | ahd_outb(ahd, CLRINT, CLRPCIINT); | ||
817 | ahd_unpause(ahd); | ||
818 | } | ||
819 | |||
820 | static void | ||
821 | ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat) | ||
822 | { | ||
823 | uint8_t split_status[4]; | ||
824 | uint8_t split_status1[4]; | ||
825 | uint8_t sg_split_status[2]; | ||
826 | uint8_t sg_split_status1[2]; | ||
827 | ahd_mode_state saved_modes; | ||
828 | u_int i; | ||
829 | uint16_t pcix_status; | ||
830 | |||
831 | /* | ||
832 | * Check for splits in all modes. Modes 0 and 1 | ||
833 | * additionally have SG engine splits to look at. | ||
834 | */ | ||
835 | pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS, | ||
836 | /*bytes*/2); | ||
837 | printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n", | ||
838 | ahd_name(ahd), pcix_status); | ||
839 | saved_modes = ahd_save_modes(ahd); | ||
840 | for (i = 0; i < 4; i++) { | ||
841 | ahd_set_modes(ahd, i, i); | ||
842 | |||
843 | split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0); | ||
844 | split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1); | ||
845 | /* Clear latched errors. So our interrupt deasserts. */ | ||
846 | ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]); | ||
847 | ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]); | ||
848 | if (i > 1) | ||
849 | continue; | ||
850 | sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0); | ||
851 | sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1); | ||
852 | /* Clear latched errors. So our interrupt deasserts. */ | ||
853 | ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]); | ||
854 | ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]); | ||
855 | } | ||
856 | |||
857 | for (i = 0; i < 4; i++) { | ||
858 | u_int bit; | ||
859 | |||
860 | for (bit = 0; bit < 8; bit++) { | ||
861 | |||
862 | if ((split_status[i] & (0x1 << bit)) != 0) { | ||
863 | static const char *s; | ||
864 | |||
865 | s = split_status_strings[bit]; | ||
866 | printf(s, ahd_name(ahd), | ||
867 | split_status_source[i]); | ||
868 | } | ||
869 | |||
870 | if (i > 1) | ||
871 | continue; | ||
872 | |||
873 | if ((sg_split_status[i] & (0x1 << bit)) != 0) { | ||
874 | static const char *s; | ||
875 | |||
876 | s = split_status_strings[bit]; | ||
877 | printf(s, ahd_name(ahd), "SG"); | ||
878 | } | ||
879 | } | ||
880 | } | ||
881 | /* | ||
882 | * Clear PCI-X status bits. | ||
883 | */ | ||
884 | ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS, | ||
885 | pcix_status, /*bytes*/2); | ||
886 | ahd_outb(ahd, CLRINT, CLRSPLTINT); | ||
887 | ahd_restore_modes(ahd, saved_modes); | ||
888 | } | ||
889 | |||
890 | static int | ||
891 | ahd_aic7901_setup(struct ahd_softc *ahd) | ||
892 | { | ||
893 | |||
894 | ahd->chip = AHD_AIC7901; | ||
895 | ahd->features = AHD_AIC7901_FE; | ||
896 | return (ahd_aic790X_setup(ahd)); | ||
897 | } | ||
898 | |||
899 | static int | ||
900 | ahd_aic7901A_setup(struct ahd_softc *ahd) | ||
901 | { | ||
902 | |||
903 | ahd->chip = AHD_AIC7901A; | ||
904 | ahd->features = AHD_AIC7901A_FE; | ||
905 | return (ahd_aic790X_setup(ahd)); | ||
906 | } | ||
907 | |||
908 | static int | ||
909 | ahd_aic7902_setup(struct ahd_softc *ahd) | ||
910 | { | ||
911 | ahd->chip = AHD_AIC7902; | ||
912 | ahd->features = AHD_AIC7902_FE; | ||
913 | return (ahd_aic790X_setup(ahd)); | ||
914 | } | ||
915 | |||
916 | static int | ||
917 | ahd_aic790X_setup(struct ahd_softc *ahd) | ||
918 | { | ||
919 | ahd_dev_softc_t pci; | ||
920 | u_int rev; | ||
921 | |||
922 | pci = ahd->dev_softc; | ||
923 | rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1); | ||
924 | if (rev < ID_AIC7902_PCI_REV_A4) { | ||
925 | printf("%s: Unable to attach to unsupported chip revision %d\n", | ||
926 | ahd_name(ahd), rev); | ||
927 | ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2); | ||
928 | return (ENXIO); | ||
929 | } | ||
930 | ahd->channel = ahd_get_pci_function(pci) + 'A'; | ||
931 | if (rev < ID_AIC7902_PCI_REV_B0) { | ||
932 | /* | ||
933 | * Enable A series workarounds. | ||
934 | */ | ||
935 | ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG | ||
936 | | AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG | ||
937 | | AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG | ||
938 | | AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG | ||
939 | | AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG | ||
940 | | AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG | ||
941 | | AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG | ||
942 | | AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG | ||
943 | | AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG | ||
944 | | AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG | ||
945 | | AHD_FAINT_LED_BUG; | ||
946 | |||
947 | /* | ||
948 | * IO Cell paramter setup. | ||
949 | */ | ||
950 | AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29); | ||
951 | |||
952 | if ((ahd->flags & AHD_HP_BOARD) == 0) | ||
953 | AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA); | ||
954 | } else { | ||
955 | u_int devconfig1; | ||
956 | |||
957 | ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS | ||
958 | | AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY; | ||
959 | ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG; | ||
960 | |||
961 | /* | ||
962 | * Some issues have been resolved in the 7901B. | ||
963 | */ | ||
964 | if ((ahd->features & AHD_MULTI_FUNC) != 0) | ||
965 | ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG; | ||
966 | |||
967 | /* | ||
968 | * IO Cell paramter setup. | ||
969 | */ | ||
970 | AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29); | ||
971 | AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB); | ||
972 | AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF); | ||
973 | |||
974 | /* | ||
975 | * Set the PREQDIS bit for H2B which disables some workaround | ||
976 | * that doesn't work on regular PCI busses. | ||
977 | * XXX - Find out exactly what this does from the hardware | ||
978 | * folks! | ||
979 | */ | ||
980 | devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); | ||
981 | ahd_pci_write_config(pci, DEVCONFIG1, | ||
982 | devconfig1|PREQDIS, /*bytes*/1); | ||
983 | devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); | ||
984 | } | ||
985 | |||
986 | return (0); | ||
987 | } | ||