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