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 * 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 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 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 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 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 632 aac_sa_get_fwstatus(struct aac_softc *sc) 633 { 634 635 return (AAC_GETREG4(sc, AAC_SA_FWSTATUS)); 636 } 637 638 static int 639 aac_rx_get_fwstatus(struct aac_softc *sc) 640 { 641 642 return (AAC_GETREG4(sc, AAC_RX_FWSTATUS)); 643 } 644 645 static int 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 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 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 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 681 aac_sa_get_istatus(struct aac_softc *sc) 682 { 683 684 return (AAC_GETREG2(sc, AAC_SA_DOORBELL0)); 685 } 686 687 static int 688 aac_rx_get_istatus(struct aac_softc *sc) 689 { 690 691 return (AAC_GETREG4(sc, AAC_RX_ODBR)); 692 } 693 694 static int 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 918 aac_rkt_set_outb_queue(struct aac_softc *sc, int index) 919 { 920 921 AAC_SETREG4(sc, AAC_RKT_OQUE, index); 922 } 923