ahd_pci.c revision 1.1 1 1.1 fvdl /* $NetBSD: ahd_pci.c,v 1.1 2003/04/21 00:14:52 fvdl 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.1 fvdl * //depot/aic7xxx/aic7xxx/aic79xx_pci.c#67 $
44 1.1 fvdl *
45 1.1 fvdl * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_pci.c,v 1.9 2003/03/06 23:58:34 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.1 fvdl
51 1.1 fvdl #define AHD_PCI_IOADDR PCI_MAPREG_START /* I/O Address */
52 1.1 fvdl #define AHD_PCI_MEMADDR (PCI_MAPREG_START + 4) /* Mem I/O Address */
53 1.1 fvdl
54 1.1 fvdl #include <dev/ic/aic79xx_osm.h>
55 1.1 fvdl #include <dev/ic/aic79xx_inline.h>
56 1.1 fvdl
57 1.1 fvdl static __inline uint64_t
58 1.1 fvdl ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
59 1.1 fvdl {
60 1.1 fvdl uint64_t id;
61 1.1 fvdl
62 1.1 fvdl id = subvendor
63 1.1 fvdl | (subdevice << 16)
64 1.1 fvdl | ((uint64_t)vendor << 32)
65 1.1 fvdl | ((uint64_t)device << 48);
66 1.1 fvdl
67 1.1 fvdl return (id);
68 1.1 fvdl }
69 1.1 fvdl
70 1.1 fvdl #define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull
71 1.1 fvdl #define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull
72 1.1 fvdl #define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull
73 1.1 fvdl
74 1.1 fvdl #define ID_AIC7901 0x800F9005FFFF9005ull
75 1.1 fvdl #define ID_AIC7901A 0x801E9005FFFF9005ull
76 1.1 fvdl #define ID_AIC7901A_IROC 0x809E9005FFFF9005ull
77 1.1 fvdl #define ID_AHA_29320A 0x8000900500609005ull
78 1.1 fvdl #define ID_AHA_29320LP 0x8014900500449005ull
79 1.1 fvdl #define ID_AHA_29320LP_IROC 0x8094900500449005ull
80 1.1 fvdl
81 1.1 fvdl #define ID_AIC7902 0x801F9005FFFF9005ull
82 1.1 fvdl #define ID_AIC7902_IROC 0x809F9005FFFF9005ull
83 1.1 fvdl #define ID_AIC7902_B 0x801D9005FFFF9005ull
84 1.1 fvdl #define ID_AIC7902_B_IROC 0x809D9005FFFF9005ull
85 1.1 fvdl #define ID_AHA_39320 0x8010900500409005ull
86 1.1 fvdl #define ID_AHA_39320A 0x8016900500409005ull
87 1.1 fvdl #define ID_AHA_39320D 0x8011900500419005ull
88 1.1 fvdl #define ID_AHA_39320D_B 0x801C900500419005ull
89 1.1 fvdl #define ID_AHA_39320D_HP 0x8011900500AC0E11ull
90 1.1 fvdl #define ID_AHA_39320D_B_HP 0x801C900500AC0E11ull
91 1.1 fvdl #define ID_AHA_29320 0x8012900500429005ull
92 1.1 fvdl #define ID_AHA_29320B 0x8013900500439005ull
93 1.1 fvdl #define ID_AIC7902_PCI_REV_A4 0x3
94 1.1 fvdl #define ID_AIC7902_PCI_REV_B0 0x10
95 1.1 fvdl #define SUBID_HP 0x0E11
96 1.1 fvdl
97 1.1 fvdl #define DEVID_9005_TYPE(id) ((id) & 0xF)
98 1.1 fvdl #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */
99 1.1 fvdl #define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */
100 1.1 fvdl #define DEVID_9005_TYPE_IROC 0x8 /* Raid(0,1,10) Card */
101 1.1 fvdl #define DEVID_9005_TYPE_MB 0xF /* On Motherboard */
102 1.1 fvdl
103 1.1 fvdl #define DEVID_9005_MFUNC(id) ((id) & 0x10)
104 1.1 fvdl
105 1.1 fvdl #define DEVID_9005_PACKETIZED(id) ((id) & 0x8000)
106 1.1 fvdl
107 1.1 fvdl #define SUBID_9005_TYPE(id) ((id) & 0xF)
108 1.1 fvdl #define SUBID_9005_TYPE_HBA 0x0 /* Standard Card */
109 1.1 fvdl #define SUBID_9005_TYPE_MB 0xF /* On Motherboard */
110 1.1 fvdl
111 1.1 fvdl #define SUBID_9005_AUTOTERM(id) (((id) & 0x10) == 0)
112 1.1 fvdl
113 1.1 fvdl #define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20)
114 1.1 fvdl
115 1.1 fvdl #define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6)
116 1.1 fvdl #define SUBID_9005_SEEPTYPE_NONE 0x0
117 1.1 fvdl #define SUBID_9005_SEEPTYPE_4K 0x1
118 1.1 fvdl
119 1.1 fvdl static ahd_device_setup_t ahd_aic7901A_setup;
120 1.1 fvdl static ahd_device_setup_t ahd_aic7902_setup;
121 1.1 fvdl
122 1.1 fvdl struct ahd_pci_identity ahd_pci_ident_table [] =
123 1.1 fvdl {
124 1.1 fvdl /* aic7901A based controllers */
125 1.1 fvdl {
126 1.1 fvdl ID_AHA_29320LP,
127 1.1 fvdl ID_ALL_MASK,
128 1.1 fvdl "Adaptec 29320LP Ultra320 SCSI adapter",
129 1.1 fvdl ahd_aic7901A_setup
130 1.1 fvdl },
131 1.1 fvdl {
132 1.1 fvdl ID_AHA_29320A,
133 1.1 fvdl ID_ALL_MASK,
134 1.1 fvdl "Adaptec 29320A Ultra320 SCSI adapter",
135 1.1 fvdl ahd_aic7901A_setup
136 1.1 fvdl },
137 1.1 fvdl /* aic7902 based controllers */
138 1.1 fvdl {
139 1.1 fvdl ID_AHA_39320,
140 1.1 fvdl ID_ALL_MASK,
141 1.1 fvdl "Adaptec 39320 Ultra320 SCSI adapter",
142 1.1 fvdl ahd_aic7902_setup
143 1.1 fvdl },
144 1.1 fvdl {
145 1.1 fvdl ID_AHA_39320A,
146 1.1 fvdl ID_ALL_MASK,
147 1.1 fvdl "Adaptec 39320A Ultra320 SCSI adapter",
148 1.1 fvdl ahd_aic7902_setup
149 1.1 fvdl },
150 1.1 fvdl {
151 1.1 fvdl ID_AHA_39320D,
152 1.1 fvdl ID_ALL_MASK,
153 1.1 fvdl "Adaptec 39320D Ultra320 SCSI adapter",
154 1.1 fvdl ahd_aic7902_setup
155 1.1 fvdl },
156 1.1 fvdl {
157 1.1 fvdl ID_AHA_39320D_HP,
158 1.1 fvdl ID_ALL_MASK,
159 1.1 fvdl "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",
160 1.1 fvdl ahd_aic7902_setup
161 1.1 fvdl },
162 1.1 fvdl {
163 1.1 fvdl ID_AHA_39320D_B,
164 1.1 fvdl ID_ALL_MASK,
165 1.1 fvdl "Adaptec 39320D Ultra320 SCSI adapter",
166 1.1 fvdl ahd_aic7902_setup
167 1.1 fvdl },
168 1.1 fvdl {
169 1.1 fvdl ID_AHA_39320D_B_HP,
170 1.1 fvdl ID_ALL_MASK,
171 1.1 fvdl "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",
172 1.1 fvdl ahd_aic7902_setup
173 1.1 fvdl },
174 1.1 fvdl {
175 1.1 fvdl ID_AHA_29320,
176 1.1 fvdl ID_ALL_MASK,
177 1.1 fvdl "Adaptec 29320 Ultra320 SCSI adapter",
178 1.1 fvdl ahd_aic7902_setup
179 1.1 fvdl },
180 1.1 fvdl {
181 1.1 fvdl ID_AHA_29320B,
182 1.1 fvdl ID_ALL_MASK,
183 1.1 fvdl "Adaptec 29320B Ultra320 SCSI adapter",
184 1.1 fvdl ahd_aic7902_setup
185 1.1 fvdl },
186 1.1 fvdl /* Generic chip probes for devices we don't know 'exactly' */
187 1.1 fvdl {
188 1.1 fvdl ID_AIC7901A & ID_DEV_VENDOR_MASK,
189 1.1 fvdl ID_DEV_VENDOR_MASK,
190 1.1 fvdl "Adaptec AIC7901A Ultra320 SCSI adapter",
191 1.1 fvdl ahd_aic7901A_setup
192 1.1 fvdl },
193 1.1 fvdl {
194 1.1 fvdl ID_AIC7902 & ID_9005_GENERIC_MASK,
195 1.1 fvdl ID_9005_GENERIC_MASK,
196 1.1 fvdl "Adaptec AIC7902 Ultra320 SCSI adapter",
197 1.1 fvdl ahd_aic7902_setup
198 1.1 fvdl }
199 1.1 fvdl };
200 1.1 fvdl
201 1.1 fvdl const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table);
202 1.1 fvdl
203 1.1 fvdl #define DEVCONFIG 0x40
204 1.1 fvdl #define PCIXINITPAT 0x0000E000ul
205 1.1 fvdl #define PCIXINIT_PCI33_66 0x0000E000ul
206 1.1 fvdl #define PCIXINIT_PCIX50_66 0x0000C000ul
207 1.1 fvdl #define PCIXINIT_PCIX66_100 0x0000A000ul
208 1.1 fvdl #define PCIXINIT_PCIX100_133 0x00008000ul
209 1.1 fvdl #define PCI_BUS_MODES_INDEX(devconfig) \
210 1.1 fvdl (((devconfig) & PCIXINITPAT) >> 13)
211 1.1 fvdl
212 1.1 fvdl static const char *pci_bus_modes[] =
213 1.1 fvdl {
214 1.1 fvdl "PCI bus mode unknown",
215 1.1 fvdl "PCI bus mode unknown",
216 1.1 fvdl "PCI bus mode unknown",
217 1.1 fvdl "PCI bus mode unknown",
218 1.1 fvdl "PCI-X 101-133Mhz",
219 1.1 fvdl "PCI-X 67-100Mhz",
220 1.1 fvdl "PCI-X 50-66Mhz",
221 1.1 fvdl "PCI 33 or 66Mhz"
222 1.1 fvdl };
223 1.1 fvdl
224 1.1 fvdl #define TESTMODE 0x00000800ul
225 1.1 fvdl #define IRDY_RST 0x00000200ul
226 1.1 fvdl #define FRAME_RST 0x00000100ul
227 1.1 fvdl #define PCI64BIT 0x00000080ul
228 1.1 fvdl #define MRDCEN 0x00000040ul
229 1.1 fvdl #define ENDIANSEL 0x00000020ul
230 1.1 fvdl #define MIXQWENDIANEN 0x00000008ul
231 1.1 fvdl #define DACEN 0x00000004ul
232 1.1 fvdl #define STPWLEVEL 0x00000002ul
233 1.1 fvdl #define QWENDIANSEL 0x00000001ul
234 1.1 fvdl
235 1.1 fvdl #define DEVCONFIG1 0x44
236 1.1 fvdl #define PREQDIS 0x01
237 1.1 fvdl
238 1.1 fvdl #define LATTIME 0x0000ff00ul
239 1.1 fvdl
240 1.1 fvdl int ahd_pci_probe __P((struct device *, struct cfdata *, void *));
241 1.1 fvdl void ahd_pci_attach __P((struct device *, struct device *, void *));
242 1.1 fvdl
243 1.1 fvdl CFATTACH_DECL(ahd_pci, sizeof(struct ahd_softc),
244 1.1 fvdl ahd_pci_probe, ahd_pci_attach, NULL, NULL);
245 1.1 fvdl
246 1.1 fvdl static int ahd_check_extport(struct ahd_softc *ahd);
247 1.1 fvdl static void ahd_configure_termination(struct ahd_softc *ahd,
248 1.1 fvdl u_int adapter_control);
249 1.1 fvdl static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);
250 1.1 fvdl
251 1.1 fvdl const struct ahd_pci_identity *
252 1.1 fvdl ahd_find_pci_device(id, subid)
253 1.1 fvdl pcireg_t id, subid;
254 1.1 fvdl {
255 1.1 fvdl u_int64_t full_id;
256 1.1 fvdl const struct ahd_pci_identity *entry;
257 1.1 fvdl u_int i;
258 1.1 fvdl
259 1.1 fvdl full_id = ahd_compose_id(PCI_PRODUCT(id), PCI_VENDOR(id),
260 1.1 fvdl PCI_PRODUCT(subid), PCI_VENDOR(subid));
261 1.1 fvdl
262 1.1 fvdl for (i = 0; i < ahd_num_pci_devs; i++) {
263 1.1 fvdl entry = &ahd_pci_ident_table[i];
264 1.1 fvdl if (entry->full_id == (full_id & entry->id_mask))
265 1.1 fvdl return (entry);
266 1.1 fvdl }
267 1.1 fvdl return (NULL);
268 1.1 fvdl }
269 1.1 fvdl
270 1.1 fvdl int
271 1.1 fvdl ahd_pci_probe(parent, match, aux)
272 1.1 fvdl struct device *parent;
273 1.1 fvdl struct cfdata *match;
274 1.1 fvdl void *aux;
275 1.1 fvdl {
276 1.1 fvdl struct pci_attach_args *pa = aux;
277 1.1 fvdl const struct ahd_pci_identity *entry;
278 1.1 fvdl pcireg_t subid;
279 1.1 fvdl
280 1.1 fvdl subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
281 1.1 fvdl entry = ahd_find_pci_device(pa->pa_id, subid);
282 1.1 fvdl return entry != NULL ? 1 : 0;
283 1.1 fvdl }
284 1.1 fvdl
285 1.1 fvdl void
286 1.1 fvdl ahd_pci_attach(parent, self, aux)
287 1.1 fvdl struct device *parent, *self;
288 1.1 fvdl void *aux;
289 1.1 fvdl {
290 1.1 fvdl struct pci_attach_args *pa = aux;
291 1.1 fvdl struct ahd_softc *ahd = (void *)self;
292 1.1 fvdl
293 1.1 fvdl const struct ahd_pci_identity *entry;
294 1.1 fvdl
295 1.1 fvdl uint32_t devconfig;
296 1.1 fvdl pcireg_t command;
297 1.1 fvdl int error;
298 1.1 fvdl pcireg_t subid;
299 1.1 fvdl uint16_t subvendor;
300 1.1 fvdl int pci_pwrmgmt_cap_reg;
301 1.1 fvdl int pci_pwrmgmt_csr_reg;
302 1.1 fvdl pcireg_t reg;
303 1.1 fvdl int ioh_valid, ioh2_valid, memh_valid;
304 1.1 fvdl pcireg_t memtype;
305 1.1 fvdl pci_intr_handle_t ih;
306 1.1 fvdl const char *intrstr;
307 1.1 fvdl struct ahd_pci_busdata *bd;
308 1.1 fvdl
309 1.1 fvdl ahd_set_name(ahd, ahd->sc_dev.dv_xname);
310 1.1 fvdl ahd->parent_dmat = pa->pa_dmat;
311 1.1 fvdl
312 1.1 fvdl command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
313 1.1 fvdl subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
314 1.1 fvdl entry = ahd_find_pci_device(pa->pa_id, subid);
315 1.1 fvdl if (entry == NULL)
316 1.1 fvdl return;
317 1.1 fvdl
318 1.1 fvdl /* Keep information about the PCI bus */
319 1.1 fvdl bd = malloc(sizeof (struct ahd_pci_busdata), M_DEVBUF, M_NOWAIT);
320 1.1 fvdl if (bd == NULL) {
321 1.1 fvdl printf("%s: unable to allocate bus-specific data\n", ahd_name(ahd));
322 1.1 fvdl return;
323 1.1 fvdl }
324 1.1 fvdl memset(bd, 0, sizeof(struct ahd_pci_busdata));
325 1.1 fvdl
326 1.1 fvdl bd->pc = pa->pa_pc;
327 1.1 fvdl bd->tag = pa->pa_tag;
328 1.1 fvdl bd->func = pa->pa_function;
329 1.1 fvdl bd->dev = pa->pa_device;
330 1.1 fvdl
331 1.1 fvdl ahd->bus_data = bd;
332 1.1 fvdl
333 1.1 fvdl ahd->description = entry->name;
334 1.1 fvdl
335 1.1 fvdl ahd->seep_config = malloc(sizeof(*ahd->seep_config),
336 1.1 fvdl M_DEVBUF, M_NOWAIT);
337 1.1 fvdl if (ahd->seep_config == NULL) {
338 1.1 fvdl printf("%s: cannot malloc seep_config!\n", ahd_name(ahd));
339 1.1 fvdl return;
340 1.1 fvdl }
341 1.1 fvdl memset(ahd->seep_config, 0, sizeof(*ahd->seep_config));
342 1.1 fvdl
343 1.1 fvdl LIST_INIT(&ahd->pending_scbs);
344 1.1 fvdl ahd_timer_init(&ahd->reset_timer);
345 1.1 fvdl ahd_timer_init(&ahd->stat_timer);
346 1.1 fvdl ahd->int_coalessing_timer = AHD_INT_COALESSING_TIMER_DEFAULT;
347 1.1 fvdl ahd->int_coalessing_maxcmds = AHD_INT_COALESSING_MAXCMDS_DEFAULT;
348 1.1 fvdl ahd->int_coalessing_mincmds = AHD_INT_COALESSING_MINCMDS_DEFAULT;
349 1.1 fvdl ahd->int_coalessing_threshold = AHD_INT_COALESSING_THRESHOLD_DEFAULT;
350 1.1 fvdl ahd->int_coalessing_stop_threshold = AHD_INT_COALESSING_STOP_THRESHOLD_DEFAULT;
351 1.1 fvdl
352 1.1 fvdl if (ahd_platform_alloc(ahd, NULL) != 0) {
353 1.1 fvdl ahd_free(ahd);
354 1.1 fvdl return;
355 1.1 fvdl }
356 1.1 fvdl
357 1.1 fvdl /*
358 1.1 fvdl * Record if this is an HP board.
359 1.1 fvdl */
360 1.1 fvdl subvendor = PCI_VENDOR(subid);
361 1.1 fvdl if (subvendor == SUBID_HP)
362 1.1 fvdl ahd->flags |= AHD_HP_BOARD;
363 1.1 fvdl
364 1.1 fvdl error = entry->setup(ahd, pa);
365 1.1 fvdl if (error != 0)
366 1.1 fvdl return;
367 1.1 fvdl
368 1.1 fvdl devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
369 1.1 fvdl if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66 ||
370 1.1 fvdl (devconfig & PCIXINITPAT) == PCIXINIT_PCIX66_100) {
371 1.1 fvdl ahd->chip |= AHD_PCI;
372 1.1 fvdl /* Disable PCIX workarounds when running in PCI mode. */
373 1.1 fvdl ahd->bugs &= ~AHD_PCIX_BUG_MASK;
374 1.1 fvdl } else {
375 1.1 fvdl ahd->chip |= AHD_PCIX;
376 1.1 fvdl }
377 1.1 fvdl ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)];
378 1.1 fvdl
379 1.1 fvdl memh_valid = ioh_valid = ioh2_valid = 0;
380 1.1 fvdl
381 1.1 fvdl if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIX,
382 1.1 fvdl &bd->pcix_off, NULL)) {
383 1.1 fvdl if (ahd->chip & AHD_PCIX)
384 1.1 fvdl printf("%s: warning: can't find PCI-X capability\n",
385 1.1 fvdl ahd->sc_dev.dv_xname);
386 1.1 fvdl ahd->chip &= ~AHD_PCIX;
387 1.1 fvdl ahd->chip |= AHD_PCI;
388 1.1 fvdl ahd->bugs &= ~AHD_PCIX_BUG_MASK;
389 1.1 fvdl }
390 1.1 fvdl
391 1.1 fvdl /*
392 1.1 fvdl * Map PCI Registers
393 1.1 fvdl */
394 1.1 fvdl if ((command & (PCI_COMMAND_MEM_ENABLE)) != 0) {
395 1.1 fvdl memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, AHD_PCI_MEMADDR);
396 1.1 fvdl switch (memtype) {
397 1.1 fvdl case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
398 1.1 fvdl case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
399 1.1 fvdl memh_valid = (pci_mapreg_map(pa, AHD_PCI_MEMADDR,
400 1.1 fvdl memtype, 0, &ahd->tags[0],
401 1.1 fvdl &ahd->bshs[0], NULL, NULL) == 0);
402 1.1 fvdl
403 1.1 fvdl ahd->tags[1] = ahd->tags[0];
404 1.1 fvdl
405 1.1 fvdl bus_space_subregion(ahd->tags[0], ahd->bshs[0],
406 1.1 fvdl /*offset*/0x100,
407 1.1 fvdl /*size*/0x100,
408 1.1 fvdl &ahd->bshs[1]);
409 1.1 fvdl break;
410 1.1 fvdl default:
411 1.1 fvdl printf("%s: unable to map memory registers\n", ahd_name(ahd));
412 1.1 fvdl return;
413 1.1 fvdl }
414 1.1 fvdl
415 1.1 fvdl if (memh_valid) {
416 1.1 fvdl command &= ~PCI_COMMAND_IO_ENABLE;
417 1.1 fvdl pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command);
418 1.1 fvdl }
419 1.1 fvdl #ifdef AHD_DEBUG
420 1.1 fvdl printf("%s: doing memory mapping tag0 0x%x, tag1 0x%x, shs0 0x%lx, shs1 0x%lx\n",
421 1.1 fvdl ahd_name(ahd), ahd->tags[0], ahd->tags[1], ahd->bshs[0], ahd->bshs[1]);
422 1.1 fvdl #endif
423 1.1 fvdl }
424 1.1 fvdl
425 1.1 fvdl if ((command & (PCI_COMMAND_IO_ENABLE)) != 0 &&
426 1.1 fvdl !(ahd->bugs & AHD_PCIX_MMAPIO_BUG)) {
427 1.1 fvdl memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, AHD_PCI_IOADDR);
428 1.1 fvdl
429 1.1 fvdl /* First BAR */
430 1.1 fvdl ioh_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR,
431 1.1 fvdl memtype, 0, &ahd->tags[0],
432 1.1 fvdl &ahd->bshs[0], NULL, NULL) == 0);
433 1.1 fvdl
434 1.1 fvdl memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, AHD_PCI_IOADDR1);
435 1.1 fvdl
436 1.1 fvdl /* 2nd BAR */
437 1.1 fvdl ioh2_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR1,
438 1.1 fvdl memtype, 0, &ahd->tags[1],
439 1.1 fvdl &ahd->bshs[1], NULL, NULL) == 0);
440 1.1 fvdl
441 1.1 fvdl if (ioh_valid && ioh2_valid) {
442 1.1 fvdl command &= ~PCI_COMMAND_MEM_ENABLE;
443 1.1 fvdl pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command);
444 1.1 fvdl }
445 1.1 fvdl #ifdef AHD_DEBUG
446 1.1 fvdl printf("%s: doing io mapping tag0 0x%x, tag1 0x%x, shs0 0x%lx, shs1 0x%lx\n",
447 1.1 fvdl ahd_name(ahd), ahd->tags[0], ahd->tags[1], ahd->bshs[0], ahd->bshs[1]);
448 1.1 fvdl #endif
449 1.1 fvdl
450 1.1 fvdl }
451 1.1 fvdl
452 1.1 fvdl if ((memh_valid == 0) && ((ioh_valid == 0) || (ioh2_valid == 0))) {
453 1.1 fvdl printf("%s: unable to map memory registers\n", ahd_name(ahd));
454 1.1 fvdl return;
455 1.1 fvdl }
456 1.1 fvdl
457 1.1 fvdl printf("\n");
458 1.1 fvdl
459 1.1 fvdl /*
460 1.1 fvdl * Set Power State D0.
461 1.1 fvdl */
462 1.1 fvdl if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT,
463 1.1 fvdl &pci_pwrmgmt_cap_reg, 0)) {
464 1.1 fvdl
465 1.1 fvdl pci_pwrmgmt_csr_reg = pci_pwrmgmt_cap_reg + 4;
466 1.1 fvdl reg = pci_conf_read(pa->pa_pc, pa->pa_tag,
467 1.1 fvdl pci_pwrmgmt_csr_reg);
468 1.1 fvdl if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
469 1.1 fvdl pci_conf_write(pa->pa_pc, pa->pa_tag, pci_pwrmgmt_csr_reg,
470 1.1 fvdl (reg & ~PCI_PMCSR_STATE_MASK) |
471 1.1 fvdl PCI_PMCSR_STATE_D0);
472 1.1 fvdl }
473 1.1 fvdl }
474 1.1 fvdl
475 1.1 fvdl /*
476 1.1 fvdl * Should we bother disabling 39Bit addressing
477 1.1 fvdl * based on installed memory?
478 1.1 fvdl */
479 1.1 fvdl if (sizeof(bus_addr_t) > 4)
480 1.1 fvdl ahd->flags |= AHD_39BIT_ADDRESSING;
481 1.1 fvdl
482 1.1 fvdl /*
483 1.1 fvdl * If we need to support high memory, enable dual
484 1.1 fvdl * address cycles. This bit must be set to enable
485 1.1 fvdl * high address bit generation even if we are on a
486 1.1 fvdl * 64bit bus (PCI64BIT set in devconfig).
487 1.1 fvdl */
488 1.1 fvdl if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) {
489 1.1 fvdl uint32_t devconfig;
490 1.1 fvdl
491 1.1 fvdl printf("%s: Enabling 39Bit Addressing\n", ahd_name(ahd));
492 1.1 fvdl devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
493 1.1 fvdl devconfig |= DACEN;
494 1.1 fvdl pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG, devconfig);
495 1.1 fvdl }
496 1.1 fvdl
497 1.1 fvdl /* Ensure busmastering is enabled */
498 1.1 fvdl reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
499 1.1 fvdl pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
500 1.1 fvdl reg | PCI_COMMAND_MASTER_ENABLE);
501 1.1 fvdl
502 1.1 fvdl ahd_softc_init(ahd);
503 1.1 fvdl
504 1.1 fvdl /*
505 1.1 fvdl * Map the interrupt routines
506 1.1 fvdl */
507 1.1 fvdl ahd->bus_intr = ahd_pci_intr;
508 1.1 fvdl
509 1.1 fvdl if (pci_intr_map(pa, &ih)) {
510 1.1 fvdl printf("%s: couldn't map interrupt\n", ahd_name(ahd));
511 1.1 fvdl ahd_free(ahd);
512 1.1 fvdl return;
513 1.1 fvdl }
514 1.1 fvdl intrstr = pci_intr_string(pa->pa_pc, ih);
515 1.1 fvdl ahd->ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ahd_intr, ahd);
516 1.1 fvdl if (ahd->ih == NULL) {
517 1.1 fvdl printf("%s: couldn't establish interrupt",
518 1.1 fvdl ahd_name(ahd));
519 1.1 fvdl if (intrstr != NULL)
520 1.1 fvdl printf(" at %s", intrstr);
521 1.1 fvdl printf("\n");
522 1.1 fvdl ahd_free(ahd);
523 1.1 fvdl return;
524 1.1 fvdl }
525 1.1 fvdl if (intrstr != NULL)
526 1.1 fvdl printf("%s: interrupting at %s\n", ahd_name(ahd),
527 1.1 fvdl intrstr);
528 1.1 fvdl
529 1.1 fvdl /* Get the size of the cache */
530 1.1 fvdl ahd->pci_cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
531 1.1 fvdl ahd->pci_cachesize *= 4;
532 1.1 fvdl
533 1.1 fvdl ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
534 1.1 fvdl /* See if we have a SEEPROM and perform auto-term */
535 1.1 fvdl error = ahd_check_extport(ahd);
536 1.1 fvdl if (error != 0)
537 1.1 fvdl return;
538 1.1 fvdl
539 1.1 fvdl /* Core initialization */
540 1.1 fvdl error = ahd_init(ahd);
541 1.1 fvdl if (error != 0)
542 1.1 fvdl return;
543 1.1 fvdl
544 1.1 fvdl /*
545 1.1 fvdl * Link this softc in with all other ahd instances.
546 1.1 fvdl */
547 1.1 fvdl ahd_attach(ahd);
548 1.1 fvdl
549 1.1 fvdl return;
550 1.1 fvdl }
551 1.1 fvdl
552 1.1 fvdl
553 1.1 fvdl /*
554 1.1 fvdl * Check the external port logic for a serial eeprom
555 1.1 fvdl * and termination/cable detection contrls.
556 1.1 fvdl */
557 1.1 fvdl static int
558 1.1 fvdl ahd_check_extport(struct ahd_softc *ahd)
559 1.1 fvdl {
560 1.1 fvdl struct seeprom_config *sc;
561 1.1 fvdl u_int adapter_control;
562 1.1 fvdl int have_seeprom;
563 1.1 fvdl int error;
564 1.1 fvdl
565 1.1 fvdl sc = ahd->seep_config;
566 1.1 fvdl have_seeprom = ahd_acquire_seeprom(ahd);
567 1.1 fvdl if (have_seeprom) {
568 1.1 fvdl u_int start_addr;
569 1.1 fvdl #ifdef AHD_DEBUG
570 1.1 fvdl printf("%s: Reading SEEPROM...", ahd_name(ahd));
571 1.1 fvdl #endif
572 1.1 fvdl
573 1.1 fvdl /* Address is always in units of 16bit words */
574 1.1 fvdl start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A');
575 1.1 fvdl
576 1.1 fvdl error = ahd_read_seeprom(ahd, (uint16_t *)sc,
577 1.1 fvdl start_addr, sizeof(*sc)/2);
578 1.1 fvdl
579 1.1 fvdl if (error != 0) {
580 1.1 fvdl #ifdef AHD_DEBUG
581 1.1 fvdl printf("Unable to read SEEPROM\n");
582 1.1 fvdl #endif
583 1.1 fvdl have_seeprom = 0;
584 1.1 fvdl } else {
585 1.1 fvdl have_seeprom = ahd_verify_cksum(sc);
586 1.1 fvdl #ifdef AHD_DEBUG
587 1.1 fvdl if (have_seeprom == 0)
588 1.1 fvdl printf ("checksum error\n");
589 1.1 fvdl else
590 1.1 fvdl printf ("done.\n");
591 1.1 fvdl #endif
592 1.1 fvdl }
593 1.1 fvdl ahd_release_seeprom(ahd);
594 1.1 fvdl }
595 1.1 fvdl
596 1.1 fvdl if (!have_seeprom) {
597 1.1 fvdl u_int nvram_scb;
598 1.1 fvdl
599 1.1 fvdl /*
600 1.1 fvdl * Pull scratch ram settings and treat them as
601 1.1 fvdl * if they are the contents of an seeprom if
602 1.1 fvdl * the 'ADPT', 'BIOS', or 'ASPI' signature is found
603 1.1 fvdl * in SCB 0xFF. We manually compose the data as 16bit
604 1.1 fvdl * values to avoid endian issues.
605 1.1 fvdl */
606 1.1 fvdl ahd_set_scbptr(ahd, 0xFF);
607 1.1 fvdl nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET);
608 1.1 fvdl if (nvram_scb != 0xFF
609 1.1 fvdl && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
610 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D'
611 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
612 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T')
613 1.1 fvdl || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B'
614 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I'
615 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O'
616 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S')
617 1.1 fvdl || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
618 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S'
619 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
620 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) {
621 1.1 fvdl uint16_t *sc_data;
622 1.1 fvdl int i;
623 1.1 fvdl
624 1.1 fvdl ahd_set_scbptr(ahd, nvram_scb);
625 1.1 fvdl sc_data = (uint16_t *)sc;
626 1.1 fvdl for (i = 0; i < 64; i += 2)
627 1.1 fvdl *sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i);
628 1.1 fvdl have_seeprom = ahd_verify_cksum(sc);
629 1.1 fvdl if (have_seeprom)
630 1.1 fvdl ahd->flags |= AHD_SCB_CONFIG_USED;
631 1.1 fvdl }
632 1.1 fvdl }
633 1.1 fvdl
634 1.1 fvdl #ifdef AHD_DEBUG
635 1.1 fvdl if ((have_seeprom != 0) && (ahd_debug & AHD_DUMP_SEEPROM) != 0) {
636 1.1 fvdl uint8_t *sc_data;
637 1.1 fvdl int i;
638 1.1 fvdl
639 1.1 fvdl printf("%s: Seeprom Contents:", ahd_name(ahd));
640 1.1 fvdl sc_data = (uint8_t *)sc;
641 1.1 fvdl for (i = 0; i < (sizeof(*sc)); i += 2)
642 1.1 fvdl printf("\n\t0x%.4x",
643 1.1 fvdl sc_data[i] | (sc_data[i+1] << 8));
644 1.1 fvdl printf("\n");
645 1.1 fvdl }
646 1.1 fvdl #endif
647 1.1 fvdl
648 1.1 fvdl if (!have_seeprom) {
649 1.1 fvdl printf("%s: No SEEPROM available.\n", ahd_name(ahd));
650 1.1 fvdl ahd->flags |= AHD_USEDEFAULTS;
651 1.1 fvdl error = ahd_default_config(ahd);
652 1.1 fvdl adapter_control = CFAUTOTERM|CFSEAUTOTERM;
653 1.1 fvdl free(ahd->seep_config, M_DEVBUF);
654 1.1 fvdl ahd->seep_config = NULL;
655 1.1 fvdl } else {
656 1.1 fvdl error = ahd_parse_cfgdata(ahd, sc);
657 1.1 fvdl adapter_control = sc->adapter_control;
658 1.1 fvdl }
659 1.1 fvdl if (error != 0)
660 1.1 fvdl return (error);
661 1.1 fvdl
662 1.1 fvdl ahd_configure_termination(ahd, adapter_control);
663 1.1 fvdl
664 1.1 fvdl return (0);
665 1.1 fvdl }
666 1.1 fvdl
667 1.1 fvdl static void
668 1.1 fvdl ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)
669 1.1 fvdl {
670 1.1 fvdl int error;
671 1.1 fvdl u_int sxfrctl1;
672 1.1 fvdl uint8_t termctl;
673 1.1 fvdl uint32_t devconfig;
674 1.1 fvdl struct ahd_pci_busdata *bd = ahd->bus_data;
675 1.1 fvdl
676 1.1 fvdl devconfig = pci_conf_read(bd->pc, bd->tag, DEVCONFIG);
677 1.1 fvdl devconfig &= ~STPWLEVEL;
678 1.1 fvdl if ((ahd->flags & AHD_STPWLEVEL_A) != 0)
679 1.1 fvdl devconfig |= STPWLEVEL;
680 1.1 fvdl #ifdef AHD_DEBUG
681 1.1 fvdl printf("%s: STPWLEVEL is %s\n",
682 1.1 fvdl ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off");
683 1.1 fvdl #endif
684 1.1 fvdl pci_conf_write(bd->pc, bd->tag, DEVCONFIG, devconfig);
685 1.1 fvdl
686 1.1 fvdl /* Make sure current sensing is off. */
687 1.1 fvdl if ((ahd->flags & AHD_CURRENT_SENSING) != 0) {
688 1.1 fvdl (void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);
689 1.1 fvdl }
690 1.1 fvdl
691 1.1 fvdl /*
692 1.1 fvdl * Read to sense. Write to set.
693 1.1 fvdl */
694 1.1 fvdl error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl);
695 1.1 fvdl if ((adapter_control & CFAUTOTERM) == 0) {
696 1.1 fvdl printf("%s: Manual Primary Termination\n",
697 1.1 fvdl ahd_name(ahd));
698 1.1 fvdl termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH);
699 1.1 fvdl if ((adapter_control & CFSTERM) != 0)
700 1.1 fvdl termctl |= FLX_TERMCTL_ENPRILOW;
701 1.1 fvdl if ((adapter_control & CFWSTERM) != 0)
702 1.1 fvdl termctl |= FLX_TERMCTL_ENPRIHIGH;
703 1.1 fvdl } else if (error != 0) {
704 1.1 fvdl printf("%s: Primary Auto-Term Sensing failed! "
705 1.1 fvdl "Using Defaults.\n", ahd_name(ahd));
706 1.1 fvdl termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH;
707 1.1 fvdl }
708 1.1 fvdl
709 1.1 fvdl if ((adapter_control & CFSEAUTOTERM) == 0) {
710 1.1 fvdl printf("%s: Manual Secondary Termination\n",
711 1.1 fvdl ahd_name(ahd));
712 1.1 fvdl termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH);
713 1.1 fvdl if ((adapter_control & CFSELOWTERM) != 0)
714 1.1 fvdl termctl |= FLX_TERMCTL_ENSECLOW;
715 1.1 fvdl if ((adapter_control & CFSEHIGHTERM) != 0)
716 1.1 fvdl termctl |= FLX_TERMCTL_ENSECHIGH;
717 1.1 fvdl } else if (error != 0) {
718 1.1 fvdl printf("%s: Secondary Auto-Term Sensing failed! "
719 1.1 fvdl "Using Defaults.\n", ahd_name(ahd));
720 1.1 fvdl termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH;
721 1.1 fvdl }
722 1.1 fvdl
723 1.1 fvdl /*
724 1.1 fvdl * Now set the termination based on what we found.
725 1.1 fvdl */
726 1.1 fvdl sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;
727 1.1 fvdl if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {
728 1.1 fvdl ahd->flags |= AHD_TERM_ENB_A;
729 1.1 fvdl sxfrctl1 |= STPWEN;
730 1.1 fvdl }
731 1.1 fvdl /* Must set the latch once in order to be effective. */
732 1.1 fvdl ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);
733 1.1 fvdl ahd_outb(ahd, SXFRCTL1, sxfrctl1);
734 1.1 fvdl
735 1.1 fvdl error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl);
736 1.1 fvdl if (error != 0) {
737 1.1 fvdl printf("%s: Unable to set termination settings!\n",
738 1.1 fvdl ahd_name(ahd));
739 1.1 fvdl } else {
740 1.1 fvdl printf("%s: Primary High byte termination %sabled\n",
741 1.1 fvdl ahd_name(ahd),
742 1.1 fvdl (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis");
743 1.1 fvdl
744 1.1 fvdl printf("%s: Primary Low byte termination %sabled\n",
745 1.1 fvdl ahd_name(ahd),
746 1.1 fvdl (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis");
747 1.1 fvdl
748 1.1 fvdl printf("%s: Secondary High byte termination %sabled\n",
749 1.1 fvdl ahd_name(ahd),
750 1.1 fvdl (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis");
751 1.1 fvdl
752 1.1 fvdl printf("%s: Secondary Low byte termination %sabled\n",
753 1.1 fvdl ahd_name(ahd),
754 1.1 fvdl (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis");
755 1.1 fvdl }
756 1.1 fvdl return;
757 1.1 fvdl }
758 1.1 fvdl
759 1.1 fvdl #define DPE 0x80
760 1.1 fvdl #define SSE 0x40
761 1.1 fvdl #define RMA 0x20
762 1.1 fvdl #define RTA 0x10
763 1.1 fvdl #define STA 0x08
764 1.1 fvdl #define DPR 0x01
765 1.1 fvdl
766 1.1 fvdl static const char *split_status_source[] =
767 1.1 fvdl {
768 1.1 fvdl "DFF0",
769 1.1 fvdl "DFF1",
770 1.1 fvdl "OVLY",
771 1.1 fvdl "CMC",
772 1.1 fvdl };
773 1.1 fvdl
774 1.1 fvdl static const char *pci_status_source[] =
775 1.1 fvdl {
776 1.1 fvdl "DFF0",
777 1.1 fvdl "DFF1",
778 1.1 fvdl "SG",
779 1.1 fvdl "CMC",
780 1.1 fvdl "OVLY",
781 1.1 fvdl "NONE",
782 1.1 fvdl "MSI",
783 1.1 fvdl "TARG"
784 1.1 fvdl };
785 1.1 fvdl
786 1.1 fvdl static const char *split_status_strings[] =
787 1.1 fvdl {
788 1.1 fvdl "%s: Received split response in %s.\n",
789 1.1 fvdl "%s: Received split completion error message in %s\n",
790 1.1 fvdl "%s: Receive overrun in %s\n",
791 1.1 fvdl "%s: Count not complete in %s\n",
792 1.1 fvdl "%s: Split completion data bucket in %s\n",
793 1.1 fvdl "%s: Split completion address error in %s\n",
794 1.1 fvdl "%s: Split completion byte count error in %s\n",
795 1.1 fvdl "%s: Signaled Target-abort to early terminate a split in %s\n"
796 1.1 fvdl };
797 1.1 fvdl
798 1.1 fvdl static const char *pci_status_strings[] =
799 1.1 fvdl {
800 1.1 fvdl "%s: Data Parity Error has been reported via PERR# in %s\n",
801 1.1 fvdl "%s: Target initial wait state error in %s\n",
802 1.1 fvdl "%s: Split completion read data parity error in %s\n",
803 1.1 fvdl "%s: Split completion address attribute parity error in %s\n",
804 1.1 fvdl "%s: Received a Target Abort in %s\n",
805 1.1 fvdl "%s: Received a Master Abort in %s\n",
806 1.1 fvdl "%s: Signal System Error Detected in %s\n",
807 1.1 fvdl "%s: Address or Write Phase Parity Error Detected in %s.\n"
808 1.1 fvdl };
809 1.1 fvdl
810 1.1 fvdl int
811 1.1 fvdl ahd_pci_intr(struct ahd_softc *ahd)
812 1.1 fvdl {
813 1.1 fvdl uint8_t pci_status[8];
814 1.1 fvdl ahd_mode_state saved_modes;
815 1.1 fvdl u_int pci_status1;
816 1.1 fvdl u_int intstat;
817 1.1 fvdl u_int i;
818 1.1 fvdl u_int reg;
819 1.1 fvdl struct ahd_pci_busdata *bd = ahd->bus_data;
820 1.1 fvdl
821 1.1 fvdl intstat = ahd_inb(ahd, INTSTAT);
822 1.1 fvdl
823 1.1 fvdl if ((intstat & SPLTINT) != 0)
824 1.1 fvdl ahd_pci_split_intr(ahd, intstat);
825 1.1 fvdl
826 1.1 fvdl if ((intstat & PCIINT) == 0)
827 1.1 fvdl return 0;
828 1.1 fvdl
829 1.1 fvdl printf("%s: PCI error Interrupt\n", ahd_name(ahd));
830 1.1 fvdl saved_modes = ahd_save_modes(ahd);
831 1.1 fvdl ahd_dump_card_state(ahd);
832 1.1 fvdl ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
833 1.1 fvdl for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) {
834 1.1 fvdl
835 1.1 fvdl if (i == 5)
836 1.1 fvdl continue;
837 1.1 fvdl pci_status[i] = ahd_inb(ahd, reg);
838 1.1 fvdl /* Clear latched errors. So our interrupt deasserts. */
839 1.1 fvdl ahd_outb(ahd, reg, pci_status[i]);
840 1.1 fvdl }
841 1.1 fvdl
842 1.1 fvdl for (i = 0; i < 8; i++) {
843 1.1 fvdl u_int bit;
844 1.1 fvdl
845 1.1 fvdl if (i == 5)
846 1.1 fvdl continue;
847 1.1 fvdl
848 1.1 fvdl for (bit = 0; bit < 8; bit++) {
849 1.1 fvdl
850 1.1 fvdl if ((pci_status[i] & (0x1 << bit)) != 0) {
851 1.1 fvdl static const char *s;
852 1.1 fvdl
853 1.1 fvdl s = pci_status_strings[bit];
854 1.1 fvdl if (i == 7/*TARG*/ && bit == 3)
855 1.1 fvdl s = "%s: Signaled Target Abort\n";
856 1.1 fvdl printf(s, ahd_name(ahd), pci_status_source[i]);
857 1.1 fvdl }
858 1.1 fvdl }
859 1.1 fvdl }
860 1.1 fvdl pci_status1 = pci_conf_read(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG);
861 1.1 fvdl pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG , pci_status1);
862 1.1 fvdl
863 1.1 fvdl ahd_restore_modes(ahd, saved_modes);
864 1.1 fvdl ahd_outb(ahd, CLRINT, CLRPCIINT);
865 1.1 fvdl ahd_unpause(ahd);
866 1.1 fvdl
867 1.1 fvdl return 1;
868 1.1 fvdl }
869 1.1 fvdl
870 1.1 fvdl static void
871 1.1 fvdl ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)
872 1.1 fvdl {
873 1.1 fvdl uint8_t split_status[4];
874 1.1 fvdl uint8_t split_status1[4];
875 1.1 fvdl uint8_t sg_split_status[2];
876 1.1 fvdl uint8_t sg_split_status1[2];
877 1.1 fvdl ahd_mode_state saved_modes;
878 1.1 fvdl u_int i;
879 1.1 fvdl pcireg_t pcix_status;
880 1.1 fvdl struct ahd_pci_busdata *bd = ahd->bus_data;
881 1.1 fvdl
882 1.1 fvdl /*
883 1.1 fvdl * Check for splits in all modes. Modes 0 and 1
884 1.1 fvdl * additionally have SG engine splits to look at.
885 1.1 fvdl */
886 1.1 fvdl pcix_status = pci_conf_read(bd->pc, bd->tag,
887 1.1 fvdl bd->pcix_off + PCI_PCIX_STATUS);
888 1.1 fvdl printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n",
889 1.1 fvdl ahd_name(ahd), pcix_status);
890 1.1 fvdl
891 1.1 fvdl saved_modes = ahd_save_modes(ahd);
892 1.1 fvdl for (i = 0; i < 4; i++) {
893 1.1 fvdl ahd_set_modes(ahd, i, i);
894 1.1 fvdl
895 1.1 fvdl split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0);
896 1.1 fvdl split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1);
897 1.1 fvdl /* Clear latched errors. So our interrupt deasserts. */
898 1.1 fvdl ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]);
899 1.1 fvdl ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]);
900 1.1 fvdl if (i != 0)
901 1.1 fvdl continue;
902 1.1 fvdl sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0);
903 1.1 fvdl sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1);
904 1.1 fvdl /* Clear latched errors. So our interrupt deasserts. */
905 1.1 fvdl ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]);
906 1.1 fvdl ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]);
907 1.1 fvdl }
908 1.1 fvdl
909 1.1 fvdl for (i = 0; i < 4; i++) {
910 1.1 fvdl u_int bit;
911 1.1 fvdl
912 1.1 fvdl for (bit = 0; bit < 8; bit++) {
913 1.1 fvdl
914 1.1 fvdl if ((split_status[i] & (0x1 << bit)) != 0) {
915 1.1 fvdl static const char *s;
916 1.1 fvdl
917 1.1 fvdl s = split_status_strings[bit];
918 1.1 fvdl printf(s, ahd_name(ahd),
919 1.1 fvdl split_status_source[i]);
920 1.1 fvdl }
921 1.1 fvdl
922 1.1 fvdl if (i != 0)
923 1.1 fvdl continue;
924 1.1 fvdl
925 1.1 fvdl if ((sg_split_status[i] & (0x1 << bit)) != 0) {
926 1.1 fvdl static const char *s;
927 1.1 fvdl
928 1.1 fvdl s = split_status_strings[bit];
929 1.1 fvdl printf(s, ahd_name(ahd), "SG");
930 1.1 fvdl }
931 1.1 fvdl }
932 1.1 fvdl }
933 1.1 fvdl /*
934 1.1 fvdl * Clear PCI-X status bits.
935 1.1 fvdl */
936 1.1 fvdl pci_conf_write(bd->pc, bd->tag, bd->pcix_off + PCI_PCIX_STATUS,
937 1.1 fvdl pcix_status);
938 1.1 fvdl ahd_outb(ahd, CLRINT, CLRSPLTINT);
939 1.1 fvdl ahd_restore_modes(ahd, saved_modes);
940 1.1 fvdl }
941 1.1 fvdl
942 1.1 fvdl static int
943 1.1 fvdl ahd_aic7901A_setup(struct ahd_softc *ahd, struct pci_attach_args *pa)
944 1.1 fvdl {
945 1.1 fvdl int error;
946 1.1 fvdl
947 1.1 fvdl error = ahd_aic7902_setup(ahd, pa);
948 1.1 fvdl if (error != 0)
949 1.1 fvdl return (error);
950 1.1 fvdl ahd->chip = AHD_AIC7901A;
951 1.1 fvdl return (0);
952 1.1 fvdl }
953 1.1 fvdl
954 1.1 fvdl static int
955 1.1 fvdl ahd_aic7902_setup(struct ahd_softc *ahd, struct pci_attach_args *pa)
956 1.1 fvdl {
957 1.1 fvdl u_int rev;
958 1.1 fvdl
959 1.1 fvdl rev = PCI_REVISION(pa->pa_class);
960 1.1 fvdl #ifdef AHD_DEBUG
961 1.1 fvdl printf("\n%s: aic7902 chip revision 0x%x\n", ahd_name(ahd), rev);
962 1.1 fvdl #endif
963 1.1 fvdl if (rev < ID_AIC7902_PCI_REV_A4) {
964 1.1 fvdl printf("%s: Unable to attach to unsupported chip revision %d\n",
965 1.1 fvdl ahd_name(ahd), rev);
966 1.1 fvdl pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 0);
967 1.1 fvdl return (ENXIO);
968 1.1 fvdl }
969 1.1 fvdl
970 1.1 fvdl ahd->channel = (pa->pa_function == 1) ? 'B' : 'A';
971 1.1 fvdl ahd->chip = AHD_AIC7902;
972 1.1 fvdl ahd->features = AHD_AIC7902_FE;
973 1.1 fvdl if (rev < ID_AIC7902_PCI_REV_B0) {
974 1.1 fvdl /*
975 1.1 fvdl * Enable A series workarounds.
976 1.1 fvdl */
977 1.1 fvdl ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG
978 1.1 fvdl | AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG
979 1.1 fvdl | AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG
980 1.1 fvdl | AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG
981 1.1 fvdl | AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG
982 1.1 fvdl | AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG
983 1.1 fvdl | AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG
984 1.1 fvdl | AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG
985 1.1 fvdl | AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG
986 1.1 fvdl | AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG;
987 1.1 fvdl
988 1.1 fvdl
989 1.1 fvdl /*
990 1.1 fvdl * IO Cell paramter setup.
991 1.1 fvdl */
992 1.1 fvdl AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
993 1.1 fvdl
994 1.1 fvdl if ((ahd->flags & AHD_HP_BOARD) == 0)
995 1.1 fvdl AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);
996 1.1 fvdl } else {
997 1.1 fvdl u_int devconfig1;
998 1.1 fvdl
999 1.1 fvdl ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
1000 1.1 fvdl | AHD_NEW_DFCNTRL_OPTS;
1001 1.1 fvdl ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_ABORT_LQI_BUG
1002 1.1 fvdl | AHD_INTCOLLISION_BUG|AHD_EARLY_REQ_BUG;
1003 1.1 fvdl
1004 1.1 fvdl /*
1005 1.1 fvdl * IO Cell paramter setup.
1006 1.1 fvdl */
1007 1.1 fvdl AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
1008 1.1 fvdl AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB);
1009 1.1 fvdl AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF);
1010 1.1 fvdl
1011 1.1 fvdl /*
1012 1.1 fvdl * Set the PREQDIS bit for H2B which disables some workaround
1013 1.1 fvdl * that doesn't work on regular PCI busses.
1014 1.1 fvdl * XXX - Find out exactly what this does from the hardware
1015 1.1 fvdl * folks!
1016 1.1 fvdl */
1017 1.1 fvdl devconfig1 = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG1);
1018 1.1 fvdl pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG1, devconfig1|PREQDIS);
1019 1.1 fvdl devconfig1 = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG1);
1020 1.1 fvdl }
1021 1.1 fvdl
1022 1.1 fvdl return (0);
1023 1.1 fvdl }
1024 1.1 fvdl
1025