1 /* $NetBSD: aac_pci.c,v 1.42 2022/09/25 17:52:25 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*-
33 * Copyright (c) 2000 Michael Smith
34 * Copyright (c) 2000 BSDi
35 * Copyright (c) 2000 Niklas Hallqvist
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 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 *
59 * from FreeBSD: aac_pci.c,v 1.1 2000/09/13 03:20:34 msmith Exp
60 * via OpenBSD: aac_pci.c,v 1.7 2002/03/14 01:26:58 millert Exp
61 */
62
63 /*
64 * PCI front-end for the `aac' driver.
65 */
66
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: aac_pci.c,v 1.42 2022/09/25 17:52:25 thorpej Exp $");
69
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/device.h>
73 #include <sys/kernel.h>
74 #include <sys/queue.h>
75
76 #include <sys/bus.h>
77 #include <machine/endian.h>
78 #include <sys/intr.h>
79
80 #include <dev/pci/pcidevs.h>
81 #include <dev/pci/pcireg.h>
82 #include <dev/pci/pcivar.h>
83
84 #include <dev/ic/aacreg.h>
85 #include <dev/ic/aacvar.h>
86
87 struct aac_pci_softc {
88 struct aac_softc sc_aac;
89 pci_chipset_tag_t sc_pc;
90 pci_intr_handle_t sc_ih;
91 };
92
93 /* i960Rx interface */
94 static int aac_rx_get_fwstatus(struct aac_softc *);
95 static void aac_rx_qnotify(struct aac_softc *, int);
96 static int aac_rx_get_istatus(struct aac_softc *);
97 static void aac_rx_clear_istatus(struct aac_softc *, int);
98 static void aac_rx_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
99 u_int32_t, u_int32_t, u_int32_t);
100 static uint32_t aac_rx_get_mailbox(struct aac_softc *, int);
101 static void aac_rx_set_interrupts(struct aac_softc *, int);
102 static int aac_rx_send_command(struct aac_softc *, struct aac_ccb *);
103 static int aac_rx_get_outb_queue(struct aac_softc *);
104 static void aac_rx_set_outb_queue(struct aac_softc *, int);
105
106 /* StrongARM interface */
107 static int aac_sa_get_fwstatus(struct aac_softc *);
108 static void aac_sa_qnotify(struct aac_softc *, int);
109 static int aac_sa_get_istatus(struct aac_softc *);
110 static void aac_sa_clear_istatus(struct aac_softc *, int);
111 static void aac_sa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
112 u_int32_t, u_int32_t, u_int32_t);
113 static uint32_t aac_sa_get_mailbox(struct aac_softc *, int);
114 static void aac_sa_set_interrupts(struct aac_softc *, int);
115
116 /* Rocket/MIPS interface */
117 static int aac_rkt_get_fwstatus(struct aac_softc *);
118 static void aac_rkt_qnotify(struct aac_softc *, int);
119 static int aac_rkt_get_istatus(struct aac_softc *);
120 static void aac_rkt_clear_istatus(struct aac_softc *, int);
121 static void aac_rkt_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
122 u_int32_t, u_int32_t, u_int32_t);
123 static uint32_t aac_rkt_get_mailbox(struct aac_softc *, int);
124 static void aac_rkt_set_interrupts(struct aac_softc *, int);
125 static int aac_rkt_send_command(struct aac_softc *, struct aac_ccb *);
126 static int aac_rkt_get_outb_queue(struct aac_softc *);
127 static void aac_rkt_set_outb_queue(struct aac_softc *, int);
128
129 static const struct aac_interface aac_rx_interface = {
130 aac_rx_get_fwstatus,
131 aac_rx_qnotify,
132 aac_rx_get_istatus,
133 aac_rx_clear_istatus,
134 aac_rx_set_mailbox,
135 aac_rx_get_mailbox,
136 aac_rx_set_interrupts,
137 aac_rx_send_command,
138 aac_rx_get_outb_queue,
139 aac_rx_set_outb_queue
140 };
141
142 static const struct aac_interface aac_sa_interface = {
143 aac_sa_get_fwstatus,
144 aac_sa_qnotify,
145 aac_sa_get_istatus,
146 aac_sa_clear_istatus,
147 aac_sa_set_mailbox,
148 aac_sa_get_mailbox,
149 aac_sa_set_interrupts,
150 NULL, NULL, NULL
151 };
152
153 static const struct aac_interface aac_rkt_interface = {
154 aac_rkt_get_fwstatus,
155 aac_rkt_qnotify,
156 aac_rkt_get_istatus,
157 aac_rkt_clear_istatus,
158 aac_rkt_set_mailbox,
159 aac_rkt_get_mailbox,
160 aac_rkt_set_interrupts,
161 aac_rkt_send_command,
162 aac_rkt_get_outb_queue,
163 aac_rkt_set_outb_queue
164 };
165
166 static struct aac_ident {
167 u_short vendor;
168 u_short device;
169 u_short subvendor;
170 u_short subdevice;
171 u_short hwif;
172 u_short quirks;
173 const char *prodstr;
174 } const aac_ident[] = {
175 {
176 PCI_VENDOR_DELL,
177 PCI_PRODUCT_DELL_PERC_2SI,
178 PCI_VENDOR_DELL,
179 PCI_PRODUCT_DELL_PERC_2SI,
180 AAC_HWIF_I960RX,
181 0,
182 "Dell PERC 2/Si"
183 },
184 {
185 PCI_VENDOR_DELL,
186 PCI_PRODUCT_DELL_PERC_3DI,
187 PCI_VENDOR_DELL,
188 PCI_PRODUCT_DELL_PERC_3DI,
189 AAC_HWIF_I960RX,
190 0,
191 "Dell PERC 3/Di"
192 },
193 {
194 PCI_VENDOR_DELL,
195 PCI_PRODUCT_DELL_PERC_3DI,
196 PCI_VENDOR_DELL,
197 PCI_PRODUCT_DELL_PERC_3DI_SUB2,
198 AAC_HWIF_I960RX,
199 0,
200 "Dell PERC 3/Di"
201 },
202 {
203 PCI_VENDOR_DELL,
204 PCI_PRODUCT_DELL_PERC_3DI,
205 PCI_VENDOR_DELL,
206 PCI_PRODUCT_DELL_PERC_3DI_SUB3,
207 AAC_HWIF_I960RX,
208 0,
209 "Dell PERC 3/Di"
210 },
211 {
212 PCI_VENDOR_DELL,
213 PCI_PRODUCT_DELL_PERC_3DI_2,
214 PCI_VENDOR_DELL,
215 PCI_PRODUCT_DELL_PERC_3DI_2_SUB,
216 AAC_HWIF_I960RX,
217 0,
218 "Dell PERC 3/Di"
219 },
220 {
221 PCI_VENDOR_DELL,
222 PCI_PRODUCT_DELL_PERC_3DI_3,
223 PCI_VENDOR_DELL,
224 PCI_PRODUCT_DELL_PERC_3DI_3_SUB,
225 AAC_HWIF_I960RX,
226 0,
227 "Dell PERC 3/Di"
228 },
229 {
230 PCI_VENDOR_DELL,
231 PCI_PRODUCT_DELL_PERC_3DI_3,
232 PCI_VENDOR_DELL,
233 PCI_PRODUCT_DELL_PERC_3DI_3_SUB2,
234 AAC_HWIF_I960RX,
235 0,
236 "Dell PERC 3/Di"
237 },
238 {
239 PCI_VENDOR_DELL,
240 PCI_PRODUCT_DELL_PERC_3DI_3,
241 PCI_VENDOR_DELL,
242 PCI_PRODUCT_DELL_PERC_3DI_3_SUB3,
243 AAC_HWIF_I960RX,
244 0,
245 "Dell PERC 3/Di"
246 },
247 {
248 PCI_VENDOR_DELL,
249 PCI_PRODUCT_DELL_PERC_3SI,
250 PCI_VENDOR_DELL,
251 PCI_PRODUCT_DELL_PERC_3SI,
252 AAC_HWIF_I960RX,
253 0,
254 "Dell PERC 3/Si"
255 },
256 {
257 PCI_VENDOR_DELL,
258 PCI_PRODUCT_DELL_PERC_3SI_2,
259 PCI_VENDOR_DELL,
260 PCI_PRODUCT_DELL_PERC_3SI_2_SUB,
261 AAC_HWIF_I960RX,
262 0,
263 "Dell PERC 3/Si"
264 },
265 {
266 PCI_VENDOR_ADP2,
267 PCI_PRODUCT_ADP2_ASR2200S,
268 PCI_VENDOR_DELL,
269 PCI_PRODUCT_DELL_CERC_1_5,
270 AAC_HWIF_I960RX,
271 AAC_QUIRK_NO4GB,
272 "Dell CERC SATA RAID 1.5/6ch"
273 },
274 {
275 PCI_VENDOR_ADP2,
276 PCI_PRODUCT_ADP2_AAC2622,
277 PCI_VENDOR_ADP2,
278 PCI_PRODUCT_ADP2_AAC2622,
279 AAC_HWIF_I960RX,
280 0,
281 "Adaptec ADP-2622"
282 },
283 {
284 PCI_VENDOR_ADP2,
285 PCI_PRODUCT_ADP2_ASR2200S,
286 PCI_VENDOR_ADP2,
287 PCI_PRODUCT_ADP2_ASR2200S_SUB2M,
288 AAC_HWIF_I960RX,
289 AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS,
290 "Adaptec ASR-2200S"
291 },
292 {
293 PCI_VENDOR_ADP2,
294 PCI_PRODUCT_ADP2_ASR2200S,
295 PCI_VENDOR_DELL,
296 PCI_PRODUCT_ADP2_ASR2200S_SUB2M,
297 AAC_HWIF_I960RX,
298 AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS,
299 "Dell PERC 320/DC"
300 },
301 {
302 PCI_VENDOR_ADP2,
303 PCI_PRODUCT_ADP2_ASR2200S,
304 PCI_VENDOR_ADP2,
305 PCI_PRODUCT_ADP2_ASR2200S,
306 AAC_HWIF_I960RX,
307 AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS,
308 "Adaptec ASR-2200S"
309 },
310 {
311 PCI_VENDOR_ADP2,
312 PCI_PRODUCT_ADP2_ASR2200S,
313 PCI_VENDOR_ADP2,
314 PCI_PRODUCT_ADP2_AAR2810SA,
315 AAC_HWIF_I960RX,
316 AAC_QUIRK_NO4GB,
317 "Adaptec AAR-2810SA"
318 },
319 {
320 PCI_VENDOR_ADP2,
321 PCI_PRODUCT_ADP2_ASR2200S,
322 PCI_VENDOR_ADP2,
323 PCI_PRODUCT_ADP2_ASR2120S,
324 AAC_HWIF_I960RX,
325 AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS,
326 "Adaptec ASR-2120S"
327 },
328 {
329 PCI_VENDOR_ADP2,
330 PCI_PRODUCT_ADP2_ASR2200S,
331 PCI_VENDOR_ADP2,
332 PCI_PRODUCT_ADP2_ASR2410SA,
333 AAC_HWIF_I960RX,
334 AAC_QUIRK_NO4GB,
335 "Adaptec ASR-2410SA"
336 },
337 {
338 PCI_VENDOR_ADP2,
339 PCI_PRODUCT_ADP2_ASR2200S,
340 PCI_VENDOR_HP,
341 PCI_PRODUCT_ADP2_HP_M110_G2,
342 AAC_HWIF_I960RX,
343 AAC_QUIRK_NO4GB,
344 "HP ML110 G2 (Adaptec ASR-2610SA)"
345 },
346 {
347 PCI_VENDOR_ADP2,
348 PCI_PRODUCT_ADP2_ASR2120S,
349 PCI_VENDOR_IBM,
350 PCI_PRODUCT_IBM_SERVERAID8K,
351 AAC_HWIF_RKT,
352 0,
353 "IBM ServeRAID 8k"
354 },
355 { PCI_VENDOR_ADP2,
356 PCI_PRODUCT_ADP2_ASR2200S,
357 PCI_VENDOR_ADP2,
358 PCI_PRODUCT_ADP2_2405,
359 AAC_HWIF_I960RX,
360 0,
361 "Adaptec RAID 2405"
362 },
363 { PCI_VENDOR_ADP2,
364 PCI_PRODUCT_ADP2_ASR2200S,
365 PCI_VENDOR_ADP2,
366 PCI_PRODUCT_ADP2_2445,
367 AAC_HWIF_I960RX,
368 0,
369 "Adaptec RAID 2445"
370 },
371 { PCI_VENDOR_ADP2,
372 PCI_PRODUCT_ADP2_ASR2200S,
373 PCI_VENDOR_ADP2,
374 PCI_PRODUCT_ADP2_2805,
375 AAC_HWIF_I960RX,
376 0,
377 "Adaptec RAID 2805"
378 },
379 { PCI_VENDOR_ADP2,
380 PCI_PRODUCT_ADP2_ASR2200S,
381 PCI_VENDOR_ADP2,
382 PCI_PRODUCT_ADP2_3405,
383 AAC_HWIF_I960RX,
384 0,
385 "Adaptec RAID 3405"
386 },
387 { PCI_VENDOR_ADP2,
388 PCI_PRODUCT_ADP2_ASR2200S,
389 PCI_VENDOR_ADP2,
390 PCI_PRODUCT_ADP2_3805,
391 AAC_HWIF_I960RX,
392 0,
393 "Adaptec RAID 3805"
394 },
395 {
396 PCI_VENDOR_DEC,
397 PCI_PRODUCT_DEC_21554,
398 PCI_VENDOR_ADP2,
399 PCI_PRODUCT_ADP2_AAC364,
400 AAC_HWIF_STRONGARM,
401 0,
402 "Adaptec AAC-364"
403 },
404 {
405 PCI_VENDOR_DEC,
406 PCI_PRODUCT_DEC_21554,
407 PCI_VENDOR_ADP2,
408 PCI_PRODUCT_ADP2_ASR5400S,
409 AAC_HWIF_STRONGARM,
410 AAC_QUIRK_BROKEN_MMAP,
411 "Adaptec ASR-5400S"
412 },
413 {
414 PCI_VENDOR_DEC,
415 PCI_PRODUCT_DEC_21554,
416 PCI_VENDOR_ADP2,
417 PCI_PRODUCT_ADP2_PERC_2QC,
418 AAC_HWIF_STRONGARM,
419 AAC_QUIRK_PERC2QC,
420 "Dell PERC 2/QC"
421 },
422 {
423 PCI_VENDOR_DEC,
424 PCI_PRODUCT_DEC_21554,
425 PCI_VENDOR_ADP2,
426 PCI_PRODUCT_ADP2_PERC_3QC,
427 AAC_HWIF_STRONGARM,
428 0,
429 "Dell PERC 3/QC"
430 },
431 {
432 PCI_VENDOR_DEC,
433 PCI_PRODUCT_DEC_21554,
434 PCI_VENDOR_HP,
435 PCI_PRODUCT_HP_NETRAID_4M,
436 AAC_HWIF_STRONGARM,
437 0,
438 "HP NetRAID-4M"
439 },
440 {
441 PCI_VENDOR_ADP2,
442 PCI_PRODUCT_ADP2_ASR2200S,
443 PCI_VENDOR_SUN,
444 PCI_PRODUCT_ADP2_ASR2120S,
445 AAC_HWIF_I960RX,
446 0,
447 "SG-XPCIESAS-R-IN"
448 },
449 };
450
451 static const struct aac_ident *
aac_find_ident(struct pci_attach_args * pa)452 aac_find_ident(struct pci_attach_args *pa)
453 {
454 const struct aac_ident *m, *mm;
455 u_int32_t subsysid;
456
457 m = aac_ident;
458 mm = aac_ident + (sizeof(aac_ident) / sizeof(aac_ident[0]));
459
460 while (m < mm) {
461 if (m->vendor == PCI_VENDOR(pa->pa_id) &&
462 m->device == PCI_PRODUCT(pa->pa_id)) {
463 subsysid = pci_conf_read(pa->pa_pc, pa->pa_tag,
464 PCI_SUBSYS_ID_REG);
465 if (m->subvendor == PCI_VENDOR(subsysid) &&
466 m->subdevice == PCI_PRODUCT(subsysid))
467 return (m);
468 }
469 m++;
470 }
471
472 return (NULL);
473 }
474
475 static int
aac_pci_intr_set(struct aac_softc * sc,int (* hand)(void *),void * arg)476 aac_pci_intr_set(struct aac_softc *sc, int (*hand)(void*), void *arg)
477 {
478 struct aac_pci_softc *pcisc;
479
480 pcisc = (struct aac_pci_softc *) sc;
481
482 pci_intr_disestablish(pcisc->sc_pc, sc->sc_ih);
483 sc->sc_ih = pci_intr_establish_xname(pcisc->sc_pc, pcisc->sc_ih,
484 IPL_BIO, hand, arg, device_xname(sc->sc_dv));
485 if (sc->sc_ih == NULL) {
486 return ENXIO;
487 }
488 return 0;
489 }
490
491 static int
aac_pci_match(device_t parent,cfdata_t match,void * aux)492 aac_pci_match(device_t parent, cfdata_t match, void *aux)
493 {
494 struct pci_attach_args *pa;
495
496 pa = aux;
497
498 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_I2O)
499 return (0);
500
501 return (aac_find_ident(pa) != NULL);
502 }
503
504 static void
aac_pci_attach(device_t parent,device_t self,void * aux)505 aac_pci_attach(device_t parent, device_t self, void *aux)
506 {
507 struct pci_attach_args *pa;
508 pci_chipset_tag_t pc;
509 struct aac_pci_softc *pcisc;
510 struct aac_softc *sc;
511 u_int16_t command;
512 bus_addr_t membase;
513 bus_size_t memsize;
514 const char *intrstr;
515 int state;
516 const struct aac_ident *m;
517 char intrbuf[PCI_INTRSTR_LEN];
518
519 pa = aux;
520 pc = pa->pa_pc;
521 pcisc = device_private(self);
522 pcisc->sc_pc = pc;
523 sc = &pcisc->sc_aac;
524 sc->sc_dv = self;
525 state = 0;
526
527 aprint_naive(": RAID controller\n");
528 aprint_normal(": ");
529
530 /*
531 * Verify that the adapter is correctly set up in PCI space.
532 */
533 command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
534 command |= PCI_COMMAND_MASTER_ENABLE;
535 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command);
536 command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
537 AAC_DPRINTF(AAC_D_MISC, ("pci command status reg 0x08x "));
538
539 if ((command & PCI_COMMAND_MASTER_ENABLE) == 0) {
540 aprint_error("can't enable bus-master feature\n");
541 goto bail_out;
542 }
543
544 if ((command & PCI_COMMAND_MEM_ENABLE) == 0) {
545 aprint_error("memory window not available\n");
546 goto bail_out;
547 }
548
549 /*
550 * Map control/status registers.
551 */
552 if (pci_mapreg_map(pa, PCI_MAPREG_START,
553 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_memt,
554 &sc->sc_memh, &membase, &memsize)) {
555 aprint_error("can't find mem space\n");
556 goto bail_out;
557 }
558 state++;
559
560 if (pci_intr_map(pa, &pcisc->sc_ih)) {
561 aprint_error("couldn't map interrupt\n");
562 goto bail_out;
563 }
564 intrstr = pci_intr_string(pc, pcisc->sc_ih, intrbuf, sizeof(intrbuf));
565 sc->sc_ih = pci_intr_establish_xname(pc, pcisc->sc_ih, IPL_BIO,
566 aac_intr, sc, device_xname(self));
567 if (sc->sc_ih == NULL) {
568 aprint_error("couldn't establish interrupt");
569 if (intrstr != NULL)
570 aprint_error(" at %s", intrstr);
571 aprint_error("\n");
572 goto bail_out;
573 }
574 state++;
575
576 sc->sc_dmat = pa->pa_dmat;
577
578 m = aac_find_ident(pa);
579 aprint_normal("%s\n", m->prodstr);
580 if (intrstr != NULL)
581 aprint_normal_dev(self, "interrupting at %s\n", intrstr);
582
583 sc->sc_hwif = m->hwif;
584 sc->sc_quirks = m->quirks;
585 switch (sc->sc_hwif) {
586 case AAC_HWIF_I960RX:
587 AAC_DPRINTF(AAC_D_MISC,
588 ("set hardware up for i960Rx"));
589 sc->sc_if = aac_rx_interface;
590 break;
591
592 case AAC_HWIF_STRONGARM:
593 AAC_DPRINTF(AAC_D_MISC,
594 ("set hardware up for StrongARM"));
595 sc->sc_if = aac_sa_interface;
596 break;
597
598 case AAC_HWIF_RKT:
599 AAC_DPRINTF(AAC_D_MISC,
600 ("set hardware up for MIPS/Rocket"));
601 sc->sc_if = aac_rkt_interface;
602 break;
603 }
604 sc->sc_regsize = memsize;
605 sc->sc_intr_set = aac_pci_intr_set;
606
607 if (!aac_attach(sc))
608 return;
609
610 bail_out:
611 if (state > 1)
612 pci_intr_disestablish(pc, sc->sc_ih);
613 if (state > 0)
614 bus_space_unmap(sc->sc_memt, sc->sc_memh, memsize);
615 }
616
617 /* ARGSUSED */
618 static int
aac_pci_rescan(device_t self,const char * ifattr,const int * locs)619 aac_pci_rescan(device_t self, const char *ifattr, const int *locs)
620 {
621
622 return aac_devscan(device_private(self));
623 }
624
625 CFATTACH_DECL3_NEW(aac_pci, sizeof(struct aac_pci_softc),
626 aac_pci_match, aac_pci_attach, NULL, NULL, aac_pci_rescan, NULL, 0);
627
628 /*
629 * Read the current firmware status word.
630 */
631 static int
aac_sa_get_fwstatus(struct aac_softc * sc)632 aac_sa_get_fwstatus(struct aac_softc *sc)
633 {
634
635 return (AAC_GETREG4(sc, AAC_SA_FWSTATUS));
636 }
637
638 static int
aac_rx_get_fwstatus(struct aac_softc * sc)639 aac_rx_get_fwstatus(struct aac_softc *sc)
640 {
641
642 return (AAC_GETREG4(sc, AAC_RX_FWSTATUS));
643 }
644
645 static int
aac_rkt_get_fwstatus(struct aac_softc * sc)646 aac_rkt_get_fwstatus(struct aac_softc *sc)
647 {
648
649 return (AAC_GETREG4(sc, AAC_RKT_FWSTATUS));
650 }
651
652 /*
653 * Notify the controller of a change in a given queue
654 */
655
656 static void
aac_sa_qnotify(struct aac_softc * sc,int qbit)657 aac_sa_qnotify(struct aac_softc *sc, int qbit)
658 {
659
660 AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit);
661 }
662
663 static void
aac_rx_qnotify(struct aac_softc * sc,int qbit)664 aac_rx_qnotify(struct aac_softc *sc, int qbit)
665 {
666
667 AAC_SETREG4(sc, AAC_RX_IDBR, qbit);
668 }
669
670 static void
aac_rkt_qnotify(struct aac_softc * sc,int qbit)671 aac_rkt_qnotify(struct aac_softc *sc, int qbit)
672 {
673
674 AAC_SETREG4(sc, AAC_RKT_IDBR, qbit);
675 }
676
677 /*
678 * Get the interrupt reason bits
679 */
680 static int
aac_sa_get_istatus(struct aac_softc * sc)681 aac_sa_get_istatus(struct aac_softc *sc)
682 {
683
684 return (AAC_GETREG2(sc, AAC_SA_DOORBELL0));
685 }
686
687 static int
aac_rx_get_istatus(struct aac_softc * sc)688 aac_rx_get_istatus(struct aac_softc *sc)
689 {
690
691 return (AAC_GETREG4(sc, AAC_RX_ODBR));
692 }
693
694 static int
aac_rkt_get_istatus(struct aac_softc * sc)695 aac_rkt_get_istatus(struct aac_softc *sc)
696 {
697
698 return (AAC_GETREG4(sc, AAC_RKT_ODBR));
699 }
700
701 /*
702 * Clear some interrupt reason bits
703 */
704 static void
aac_sa_clear_istatus(struct aac_softc * sc,int mask)705 aac_sa_clear_istatus(struct aac_softc *sc, int mask)
706 {
707
708 AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask);
709 }
710
711 static void
aac_rx_clear_istatus(struct aac_softc * sc,int mask)712 aac_rx_clear_istatus(struct aac_softc *sc, int mask)
713 {
714
715 AAC_SETREG4(sc, AAC_RX_ODBR, mask);
716 }
717
718 static void
aac_rkt_clear_istatus(struct aac_softc * sc,int mask)719 aac_rkt_clear_istatus(struct aac_softc *sc, int mask)
720 {
721
722 AAC_SETREG4(sc, AAC_RKT_ODBR, mask);
723 }
724
725 /*
726 * Populate the mailbox and set the command word
727 */
728 static void
aac_sa_set_mailbox(struct aac_softc * sc,u_int32_t command,u_int32_t arg0,u_int32_t arg1,u_int32_t arg2,u_int32_t arg3)729 aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
730 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
731 u_int32_t arg3)
732 {
733
734 AAC_SETREG4(sc, AAC_SA_MAILBOX, command);
735 AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0);
736 AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1);
737 AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2);
738 AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3);
739 }
740
741 static void
aac_rx_set_mailbox(struct aac_softc * sc,u_int32_t command,u_int32_t arg0,u_int32_t arg1,u_int32_t arg2,u_int32_t arg3)742 aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command,
743 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
744 u_int32_t arg3)
745 {
746
747 AAC_SETREG4(sc, AAC_RX_MAILBOX, command);
748 AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0);
749 AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1);
750 AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2);
751 AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3);
752 }
753
754 static void
aac_rkt_set_mailbox(struct aac_softc * sc,u_int32_t command,u_int32_t arg0,u_int32_t arg1,u_int32_t arg2,u_int32_t arg3)755 aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command,
756 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2,
757 u_int32_t arg3)
758 {
759
760 AAC_SETREG4(sc, AAC_RKT_MAILBOX, command);
761 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0);
762 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1);
763 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2);
764 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3);
765 }
766
767 /*
768 * Fetch the specified mailbox
769 */
770 static uint32_t
aac_sa_get_mailbox(struct aac_softc * sc,int mb)771 aac_sa_get_mailbox(struct aac_softc *sc, int mb)
772 {
773
774 return (AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4)));
775 }
776
777 static uint32_t
aac_rx_get_mailbox(struct aac_softc * sc,int mb)778 aac_rx_get_mailbox(struct aac_softc *sc, int mb)
779 {
780
781 return (AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4)));
782 }
783
784 static uint32_t
aac_rkt_get_mailbox(struct aac_softc * sc,int mb)785 aac_rkt_get_mailbox(struct aac_softc *sc, int mb)
786 {
787
788 return (AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4)));
789 }
790
791 /*
792 * Set/clear interrupt masks
793 */
794 static void
aac_sa_set_interrupts(struct aac_softc * sc,int enable)795 aac_sa_set_interrupts(struct aac_softc *sc, int enable)
796 {
797
798 if (enable)
799 AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
800 else
801 AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0);
802 }
803
804 static void
aac_rx_set_interrupts(struct aac_softc * sc,int enable)805 aac_rx_set_interrupts(struct aac_softc *sc, int enable)
806 {
807
808 if (enable) {
809 if (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
810 AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INT_NEW_COMM);
811 else
812 AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
813 } else {
814 AAC_SETREG4(sc, AAC_RX_OIMR, ~0);
815 }
816 }
817
818 static void
aac_rkt_set_interrupts(struct aac_softc * sc,int enable)819 aac_rkt_set_interrupts(struct aac_softc *sc, int enable)
820 {
821
822 if (enable) {
823 if (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
824 AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INT_NEW_COMM);
825 else
826 AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS);
827 } else {
828 AAC_SETREG4(sc, AAC_RKT_OIMR, ~0);
829 }
830 }
831
832 /*
833 * New comm. interface: Send command functions
834 */
835 static int
aac_rx_send_command(struct aac_softc * sc,struct aac_ccb * ac)836 aac_rx_send_command(struct aac_softc *sc, struct aac_ccb *ac)
837 {
838 u_int32_t index, device;
839
840 index = AAC_GETREG4(sc, AAC_RX_IQUE);
841 if (index == 0xffffffffL)
842 index = AAC_GETREG4(sc, AAC_RX_IQUE);
843 if (index == 0xffffffffL)
844 return index;
845 #ifdef notyet
846 aac_enqueue_busy(ac);
847 #endif
848 device = index;
849 AAC_SETREG4(sc, device,
850 htole32((u_int32_t)(ac->ac_fibphys & 0xffffffffUL)));
851 device += 4;
852 if (sizeof(bus_addr_t) > 4) {
853 AAC_SETREG4(sc, device,
854 htole32((u_int32_t)((u_int64_t)ac->ac_fibphys >> 32)));
855 } else {
856 AAC_SETREG4(sc, device, 0);
857 }
858 device += 4;
859 AAC_SETREG4(sc, device, ac->ac_fib->Header.Size);
860 AAC_SETREG4(sc, AAC_RX_IQUE, index);
861 return 0;
862 }
863
864 static int
aac_rkt_send_command(struct aac_softc * sc,struct aac_ccb * ac)865 aac_rkt_send_command(struct aac_softc *sc, struct aac_ccb *ac)
866 {
867 u_int32_t index, device;
868
869 index = AAC_GETREG4(sc, AAC_RKT_IQUE);
870 if (index == 0xffffffffL)
871 index = AAC_GETREG4(sc, AAC_RKT_IQUE);
872 if (index == 0xffffffffL)
873 return index;
874 #ifdef notyet
875 aac_enqueue_busy(ac);
876 #endif
877 device = index;
878 AAC_SETREG4(sc, device,
879 htole32((u_int32_t)(ac->ac_fibphys & 0xffffffffUL)));
880 device += 4;
881 if (sizeof(bus_addr_t) > 4) {
882 AAC_SETREG4(sc, device,
883 htole32((u_int32_t)((u_int64_t)ac->ac_fibphys >> 32)));
884 } else {
885 AAC_SETREG4(sc, device, 0);
886 }
887 device += 4;
888 AAC_SETREG4(sc, device, ac->ac_fib->Header.Size);
889 AAC_SETREG4(sc, AAC_RKT_IQUE, index);
890 return 0;
891 }
892
893 /*
894 * New comm. interface: get, set outbound queue index
895 */
896 static int
aac_rx_get_outb_queue(struct aac_softc * sc)897 aac_rx_get_outb_queue(struct aac_softc *sc)
898 {
899
900 return AAC_GETREG4(sc, AAC_RX_OQUE);
901 }
902
903 static int
aac_rkt_get_outb_queue(struct aac_softc * sc)904 aac_rkt_get_outb_queue(struct aac_softc *sc)
905 {
906
907 return AAC_GETREG4(sc, AAC_RKT_OQUE);
908 }
909
910 static void
aac_rx_set_outb_queue(struct aac_softc * sc,int index)911 aac_rx_set_outb_queue(struct aac_softc *sc, int index)
912 {
913
914 AAC_SETREG4(sc, AAC_RX_OQUE, index);
915 }
916
917 static void
aac_rkt_set_outb_queue(struct aac_softc * sc,int index)918 aac_rkt_set_outb_queue(struct aac_softc *sc, int index)
919 {
920
921 AAC_SETREG4(sc, AAC_RKT_OQUE, index);
922 }
923