1 /* $NetBSD: aac_pci.c,v 1.43 2025/11/07 18:29:57 riz 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.43 2025/11/07 18:29:57 riz 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 { PCI_VENDOR_ADP2, 396 PCI_PRODUCT_ADP2_ASR2200S, 397 PCI_VENDOR_ADP2, 398 PCI_PRODUCT_ADP2_5445, 399 AAC_HWIF_I960RX, 400 0, 401 "Adaptec RAID 5445" 402 }, 403 { PCI_VENDOR_ADP2, 404 PCI_PRODUCT_ADP2_ASR2200S, 405 PCI_VENDOR_ADP2, 406 PCI_PRODUCT_ADP2_5805, 407 AAC_HWIF_I960RX, 408 0, 409 "Adaptec RAID 5805" 410 }, 411 { PCI_VENDOR_ADP2, 412 PCI_PRODUCT_ADP2_ASR2200S, 413 PCI_VENDOR_ADP2, 414 PCI_PRODUCT_ADP2_5085, 415 AAC_HWIF_I960RX, 416 0, 417 "Adaptec RAID 5085" 418 }, 419 { 420 PCI_VENDOR_DEC, 421 PCI_PRODUCT_DEC_21554, 422 PCI_VENDOR_ADP2, 423 PCI_PRODUCT_ADP2_AAC364, 424 AAC_HWIF_STRONGARM, 425 0, 426 "Adaptec AAC-364" 427 }, 428 { 429 PCI_VENDOR_DEC, 430 PCI_PRODUCT_DEC_21554, 431 PCI_VENDOR_ADP2, 432 PCI_PRODUCT_ADP2_ASR5400S, 433 AAC_HWIF_STRONGARM, 434 AAC_QUIRK_BROKEN_MMAP, 435 "Adaptec ASR-5400S" 436 }, 437 { 438 PCI_VENDOR_DEC, 439 PCI_PRODUCT_DEC_21554, 440 PCI_VENDOR_ADP2, 441 PCI_PRODUCT_ADP2_PERC_2QC, 442 AAC_HWIF_STRONGARM, 443 AAC_QUIRK_PERC2QC, 444 "Dell PERC 2/QC" 445 }, 446 { 447 PCI_VENDOR_DEC, 448 PCI_PRODUCT_DEC_21554, 449 PCI_VENDOR_ADP2, 450 PCI_PRODUCT_ADP2_PERC_3QC, 451 AAC_HWIF_STRONGARM, 452 0, 453 "Dell PERC 3/QC" 454 }, 455 { 456 PCI_VENDOR_DEC, 457 PCI_PRODUCT_DEC_21554, 458 PCI_VENDOR_HP, 459 PCI_PRODUCT_HP_NETRAID_4M, 460 AAC_HWIF_STRONGARM, 461 0, 462 "HP NetRAID-4M" 463 }, 464 { 465 PCI_VENDOR_ADP2, 466 PCI_PRODUCT_ADP2_ASR2200S, 467 PCI_VENDOR_SUN, 468 PCI_PRODUCT_ADP2_ASR2120S, 469 AAC_HWIF_I960RX, 470 0, 471 "SG-XPCIESAS-R-IN" 472 }, 473 }; 474 475 static const struct aac_ident * 476 aac_find_ident(struct pci_attach_args *pa) 477 { 478 const struct aac_ident *m, *mm; 479 u_int32_t subsysid; 480 481 m = aac_ident; 482 mm = aac_ident + (sizeof(aac_ident) / sizeof(aac_ident[0])); 483 484 while (m < mm) { 485 if (m->vendor == PCI_VENDOR(pa->pa_id) && 486 m->device == PCI_PRODUCT(pa->pa_id)) { 487 subsysid = pci_conf_read(pa->pa_pc, pa->pa_tag, 488 PCI_SUBSYS_ID_REG); 489 if (m->subvendor == PCI_VENDOR(subsysid) && 490 m->subdevice == PCI_PRODUCT(subsysid)) 491 return (m); 492 } 493 m++; 494 } 495 496 return (NULL); 497 } 498 499 static int 500 aac_pci_intr_set(struct aac_softc *sc, int (*hand)(void*), void *arg) 501 { 502 struct aac_pci_softc *pcisc; 503 504 pcisc = (struct aac_pci_softc *) sc; 505 506 pci_intr_disestablish(pcisc->sc_pc, sc->sc_ih); 507 sc->sc_ih = pci_intr_establish_xname(pcisc->sc_pc, pcisc->sc_ih, 508 IPL_BIO, hand, arg, device_xname(sc->sc_dv)); 509 if (sc->sc_ih == NULL) { 510 return ENXIO; 511 } 512 return 0; 513 } 514 515 static int 516 aac_pci_match(device_t parent, cfdata_t match, void *aux) 517 { 518 struct pci_attach_args *pa; 519 520 pa = aux; 521 522 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_I2O) 523 return (0); 524 525 return (aac_find_ident(pa) != NULL); 526 } 527 528 static void 529 aac_pci_attach(device_t parent, device_t self, void *aux) 530 { 531 struct pci_attach_args *pa; 532 pci_chipset_tag_t pc; 533 struct aac_pci_softc *pcisc; 534 struct aac_softc *sc; 535 u_int16_t command; 536 bus_addr_t membase; 537 bus_size_t memsize; 538 const char *intrstr; 539 int state; 540 const struct aac_ident *m; 541 char intrbuf[PCI_INTRSTR_LEN]; 542 543 pa = aux; 544 pc = pa->pa_pc; 545 pcisc = device_private(self); 546 pcisc->sc_pc = pc; 547 sc = &pcisc->sc_aac; 548 sc->sc_dv = self; 549 state = 0; 550 551 aprint_naive(": RAID controller\n"); 552 aprint_normal(": "); 553 554 /* 555 * Verify that the adapter is correctly set up in PCI space. 556 */ 557 command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 558 command |= PCI_COMMAND_MASTER_ENABLE; 559 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); 560 command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 561 AAC_DPRINTF(AAC_D_MISC, ("pci command status reg 0x08x ")); 562 563 if ((command & PCI_COMMAND_MASTER_ENABLE) == 0) { 564 aprint_error("can't enable bus-master feature\n"); 565 goto bail_out; 566 } 567 568 if ((command & PCI_COMMAND_MEM_ENABLE) == 0) { 569 aprint_error("memory window not available\n"); 570 goto bail_out; 571 } 572 573 /* 574 * Map control/status registers. 575 */ 576 if (pci_mapreg_map(pa, PCI_MAPREG_START, 577 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_memt, 578 &sc->sc_memh, &membase, &memsize)) { 579 aprint_error("can't find mem space\n"); 580 goto bail_out; 581 } 582 state++; 583 584 if (pci_intr_map(pa, &pcisc->sc_ih)) { 585 aprint_error("couldn't map interrupt\n"); 586 goto bail_out; 587 } 588 intrstr = pci_intr_string(pc, pcisc->sc_ih, intrbuf, sizeof(intrbuf)); 589 sc->sc_ih = pci_intr_establish_xname(pc, pcisc->sc_ih, IPL_BIO, 590 aac_intr, sc, device_xname(self)); 591 if (sc->sc_ih == NULL) { 592 aprint_error("couldn't establish interrupt"); 593 if (intrstr != NULL) 594 aprint_error(" at %s", intrstr); 595 aprint_error("\n"); 596 goto bail_out; 597 } 598 state++; 599 600 sc->sc_dmat = pa->pa_dmat; 601 602 m = aac_find_ident(pa); 603 aprint_normal("%s\n", m->prodstr); 604 if (intrstr != NULL) 605 aprint_normal_dev(self, "interrupting at %s\n", intrstr); 606 607 sc->sc_hwif = m->hwif; 608 sc->sc_quirks = m->quirks; 609 switch (sc->sc_hwif) { 610 case AAC_HWIF_I960RX: 611 AAC_DPRINTF(AAC_D_MISC, 612 ("set hardware up for i960Rx")); 613 sc->sc_if = aac_rx_interface; 614 break; 615 616 case AAC_HWIF_STRONGARM: 617 AAC_DPRINTF(AAC_D_MISC, 618 ("set hardware up for StrongARM")); 619 sc->sc_if = aac_sa_interface; 620 break; 621 622 case AAC_HWIF_RKT: 623 AAC_DPRINTF(AAC_D_MISC, 624 ("set hardware up for MIPS/Rocket")); 625 sc->sc_if = aac_rkt_interface; 626 break; 627 } 628 sc->sc_regsize = memsize; 629 sc->sc_intr_set = aac_pci_intr_set; 630 631 if (!aac_attach(sc)) 632 return; 633 634 bail_out: 635 if (state > 1) 636 pci_intr_disestablish(pc, sc->sc_ih); 637 if (state > 0) 638 bus_space_unmap(sc->sc_memt, sc->sc_memh, memsize); 639 } 640 641 /* ARGSUSED */ 642 static int 643 aac_pci_rescan(device_t self, const char *ifattr, const int *locs) 644 { 645 646 return aac_devscan(device_private(self)); 647 } 648 649 CFATTACH_DECL3_NEW(aac_pci, sizeof(struct aac_pci_softc), 650 aac_pci_match, aac_pci_attach, NULL, NULL, aac_pci_rescan, NULL, 0); 651 652 /* 653 * Read the current firmware status word. 654 */ 655 static int 656 aac_sa_get_fwstatus(struct aac_softc *sc) 657 { 658 659 return (AAC_GETREG4(sc, AAC_SA_FWSTATUS)); 660 } 661 662 static int 663 aac_rx_get_fwstatus(struct aac_softc *sc) 664 { 665 666 return (AAC_GETREG4(sc, AAC_RX_FWSTATUS)); 667 } 668 669 static int 670 aac_rkt_get_fwstatus(struct aac_softc *sc) 671 { 672 673 return (AAC_GETREG4(sc, AAC_RKT_FWSTATUS)); 674 } 675 676 /* 677 * Notify the controller of a change in a given queue 678 */ 679 680 static void 681 aac_sa_qnotify(struct aac_softc *sc, int qbit) 682 { 683 684 AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit); 685 } 686 687 static void 688 aac_rx_qnotify(struct aac_softc *sc, int qbit) 689 { 690 691 AAC_SETREG4(sc, AAC_RX_IDBR, qbit); 692 } 693 694 static void 695 aac_rkt_qnotify(struct aac_softc *sc, int qbit) 696 { 697 698 AAC_SETREG4(sc, AAC_RKT_IDBR, qbit); 699 } 700 701 /* 702 * Get the interrupt reason bits 703 */ 704 static int 705 aac_sa_get_istatus(struct aac_softc *sc) 706 { 707 708 return (AAC_GETREG2(sc, AAC_SA_DOORBELL0)); 709 } 710 711 static int 712 aac_rx_get_istatus(struct aac_softc *sc) 713 { 714 715 return (AAC_GETREG4(sc, AAC_RX_ODBR)); 716 } 717 718 static int 719 aac_rkt_get_istatus(struct aac_softc *sc) 720 { 721 722 return (AAC_GETREG4(sc, AAC_RKT_ODBR)); 723 } 724 725 /* 726 * Clear some interrupt reason bits 727 */ 728 static void 729 aac_sa_clear_istatus(struct aac_softc *sc, int mask) 730 { 731 732 AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask); 733 } 734 735 static void 736 aac_rx_clear_istatus(struct aac_softc *sc, int mask) 737 { 738 739 AAC_SETREG4(sc, AAC_RX_ODBR, mask); 740 } 741 742 static void 743 aac_rkt_clear_istatus(struct aac_softc *sc, int mask) 744 { 745 746 AAC_SETREG4(sc, AAC_RKT_ODBR, mask); 747 } 748 749 /* 750 * Populate the mailbox and set the command word 751 */ 752 static void 753 aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command, 754 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, 755 u_int32_t arg3) 756 { 757 758 AAC_SETREG4(sc, AAC_SA_MAILBOX, command); 759 AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0); 760 AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1); 761 AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2); 762 AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3); 763 } 764 765 static void 766 aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command, 767 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, 768 u_int32_t arg3) 769 { 770 771 AAC_SETREG4(sc, AAC_RX_MAILBOX, command); 772 AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0); 773 AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1); 774 AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2); 775 AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3); 776 } 777 778 static void 779 aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, 780 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, 781 u_int32_t arg3) 782 { 783 784 AAC_SETREG4(sc, AAC_RKT_MAILBOX, command); 785 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0); 786 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1); 787 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2); 788 AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3); 789 } 790 791 /* 792 * Fetch the specified mailbox 793 */ 794 static uint32_t 795 aac_sa_get_mailbox(struct aac_softc *sc, int mb) 796 { 797 798 return (AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4))); 799 } 800 801 static uint32_t 802 aac_rx_get_mailbox(struct aac_softc *sc, int mb) 803 { 804 805 return (AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4))); 806 } 807 808 static uint32_t 809 aac_rkt_get_mailbox(struct aac_softc *sc, int mb) 810 { 811 812 return (AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4))); 813 } 814 815 /* 816 * Set/clear interrupt masks 817 */ 818 static void 819 aac_sa_set_interrupts(struct aac_softc *sc, int enable) 820 { 821 822 if (enable) 823 AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS); 824 else 825 AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0); 826 } 827 828 static void 829 aac_rx_set_interrupts(struct aac_softc *sc, int enable) 830 { 831 832 if (enable) { 833 if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) 834 AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INT_NEW_COMM); 835 else 836 AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS); 837 } else { 838 AAC_SETREG4(sc, AAC_RX_OIMR, ~0); 839 } 840 } 841 842 static void 843 aac_rkt_set_interrupts(struct aac_softc *sc, int enable) 844 { 845 846 if (enable) { 847 if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) 848 AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INT_NEW_COMM); 849 else 850 AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS); 851 } else { 852 AAC_SETREG4(sc, AAC_RKT_OIMR, ~0); 853 } 854 } 855 856 /* 857 * New comm. interface: Send command functions 858 */ 859 static int 860 aac_rx_send_command(struct aac_softc *sc, struct aac_ccb *ac) 861 { 862 u_int32_t index, device; 863 864 index = AAC_GETREG4(sc, AAC_RX_IQUE); 865 if (index == 0xffffffffL) 866 index = AAC_GETREG4(sc, AAC_RX_IQUE); 867 if (index == 0xffffffffL) 868 return index; 869 #ifdef notyet 870 aac_enqueue_busy(ac); 871 #endif 872 device = index; 873 AAC_SETREG4(sc, device, 874 htole32((u_int32_t)(ac->ac_fibphys & 0xffffffffUL))); 875 device += 4; 876 if (sizeof(bus_addr_t) > 4) { 877 AAC_SETREG4(sc, device, 878 htole32((u_int32_t)((u_int64_t)ac->ac_fibphys >> 32))); 879 } else { 880 AAC_SETREG4(sc, device, 0); 881 } 882 device += 4; 883 AAC_SETREG4(sc, device, ac->ac_fib->Header.Size); 884 AAC_SETREG4(sc, AAC_RX_IQUE, index); 885 return 0; 886 } 887 888 static int 889 aac_rkt_send_command(struct aac_softc *sc, struct aac_ccb *ac) 890 { 891 u_int32_t index, device; 892 893 index = AAC_GETREG4(sc, AAC_RKT_IQUE); 894 if (index == 0xffffffffL) 895 index = AAC_GETREG4(sc, AAC_RKT_IQUE); 896 if (index == 0xffffffffL) 897 return index; 898 #ifdef notyet 899 aac_enqueue_busy(ac); 900 #endif 901 device = index; 902 AAC_SETREG4(sc, device, 903 htole32((u_int32_t)(ac->ac_fibphys & 0xffffffffUL))); 904 device += 4; 905 if (sizeof(bus_addr_t) > 4) { 906 AAC_SETREG4(sc, device, 907 htole32((u_int32_t)((u_int64_t)ac->ac_fibphys >> 32))); 908 } else { 909 AAC_SETREG4(sc, device, 0); 910 } 911 device += 4; 912 AAC_SETREG4(sc, device, ac->ac_fib->Header.Size); 913 AAC_SETREG4(sc, AAC_RKT_IQUE, index); 914 return 0; 915 } 916 917 /* 918 * New comm. interface: get, set outbound queue index 919 */ 920 static int 921 aac_rx_get_outb_queue(struct aac_softc *sc) 922 { 923 924 return AAC_GETREG4(sc, AAC_RX_OQUE); 925 } 926 927 static int 928 aac_rkt_get_outb_queue(struct aac_softc *sc) 929 { 930 931 return AAC_GETREG4(sc, AAC_RKT_OQUE); 932 } 933 934 static void 935 aac_rx_set_outb_queue(struct aac_softc *sc, int index) 936 { 937 938 AAC_SETREG4(sc, AAC_RX_OQUE, index); 939 } 940 941 static void 942 aac_rkt_set_outb_queue(struct aac_softc *sc, int index) 943 { 944 945 AAC_SETREG4(sc, AAC_RKT_OQUE, index); 946 } 947