1/*- 2 * Copyright (c) 1999,2000 Michael Smith 3 * Copyright (c) 2000 BSDi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27/*- 28 * Copyright (c) 2002 Eric Moore 29 * Copyright (c) 2002, 2004 LSI Logic Corporation 30 * All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 3. The party using or redistributing the source code and binary forms 41 * agrees to the disclaimer below and the terms and conditions set forth 42 * herein. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 */ 56 57#include <sys/cdefs.h> 58__FBSDID("$FreeBSD$"); 59 60#include <sys/param.h> 61#include <sys/systm.h> 62#include <sys/kernel.h> 63#include <sys/module.h> 64#include <sys/sysctl.h> 65 66#include <sys/bio.h> 67#include <sys/bus.h> 68#include <sys/conf.h> 69 70#include <machine/bus.h> 71#include <machine/resource.h> 72#include <sys/rman.h> 73 74#include <dev/pci/pcireg.h> 75#include <dev/pci/pcivar.h> 76 77#include <dev/amr/amrio.h> 78#include <dev/amr/amrreg.h> 79#include <dev/amr/amrvar.h> 80 81static int amr_pci_probe(device_t dev); 82static int amr_pci_attach(device_t dev); 83static int amr_pci_detach(device_t dev); 84static int amr_pci_shutdown(device_t dev); 85static int amr_pci_suspend(device_t dev); 86static int amr_pci_resume(device_t dev); 87static void amr_pci_intr(void *arg); 88static void amr_pci_free(struct amr_softc *sc); 89static void amr_sglist_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error); 90static int amr_sglist_map(struct amr_softc *sc); 91static int amr_setup_mbox(struct amr_softc *sc); 92static int amr_ccb_map(struct amr_softc *sc); 93 94static u_int amr_force_sg32 = 0; 95SYSCTL_DECL(_hw_amr); 96SYSCTL_UINT(_hw_amr, OID_AUTO, force_sg32, CTLFLAG_RDTUN, &amr_force_sg32, 0, 97 "Force the AMR driver to use 32bit scatter gather"); 98 99static device_method_t amr_methods[] = { 100 /* Device interface */ 101 DEVMETHOD(device_probe, amr_pci_probe), 102 DEVMETHOD(device_attach, amr_pci_attach), 103 DEVMETHOD(device_detach, amr_pci_detach), 104 DEVMETHOD(device_shutdown, amr_pci_shutdown), 105 DEVMETHOD(device_suspend, amr_pci_suspend), 106 DEVMETHOD(device_resume, amr_pci_resume), 107 108 DEVMETHOD_END 109}; 110 111static driver_t amr_pci_driver = { 112 "amr", 113 amr_methods, 114 sizeof(struct amr_softc) 115}; 116 117static devclass_t amr_devclass; 118DRIVER_MODULE(amr, pci, amr_pci_driver, amr_devclass, 0, 0); 119MODULE_DEPEND(amr, pci, 1, 1, 1); 120MODULE_DEPEND(amr, cam, 1, 1, 1); 121 122static struct amr_ident 123{ 124 int vendor; 125 int device; 126 int flags; 127#define AMR_ID_PROBE_SIG (1<<0) /* generic i960RD, check signature */ 128#define AMR_ID_DO_SG64 (1<<1) 129#define AMR_ID_QUARTZ (1<<2) 130} amr_device_ids[] = { 131 {0x101e, 0x9010, 0}, 132 {0x101e, 0x9060, 0}, 133 {0x8086, 0x1960, AMR_ID_QUARTZ | AMR_ID_PROBE_SIG}, 134 {0x101e, 0x1960, AMR_ID_QUARTZ}, 135 {0x1000, 0x1960, AMR_ID_QUARTZ | AMR_ID_DO_SG64 | AMR_ID_PROBE_SIG}, 136 {0x1000, 0x0407, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, 137 {0x1000, 0x0408, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, 138 {0x1000, 0x0409, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, 139 {0x1028, 0x000e, AMR_ID_QUARTZ | AMR_ID_DO_SG64 | AMR_ID_PROBE_SIG}, /* perc4/di i960 */ 140 {0x1028, 0x000f, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, /* perc4/di Verde*/ 141 {0x1028, 0x0013, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, /* perc4/di */ 142 {0, 0, 0} 143}; 144 145static struct amr_ident * 146amr_find_ident(device_t dev) 147{ 148 struct amr_ident *id; 149 int sig; 150 151 for (id = amr_device_ids; id->vendor != 0; id++) { 152 if ((pci_get_vendor(dev) == id->vendor) && 153 (pci_get_device(dev) == id->device)) { 154 155 /* do we need to test for a signature? */ 156 if (id->flags & AMR_ID_PROBE_SIG) { 157 sig = pci_read_config(dev, AMR_CFG_SIG, 2); 158 if ((sig != AMR_SIGNATURE_1) && (sig != AMR_SIGNATURE_2)) 159 continue; 160 } 161 return (id); 162 } 163 } 164 return (NULL); 165} 166 167static int 168amr_pci_probe(device_t dev) 169{ 170 171 debug_called(1); 172 173 if (amr_find_ident(dev) != NULL) { 174 device_set_desc(dev, LSI_DESC_PCI); 175 return(BUS_PROBE_DEFAULT); 176 } 177 return(ENXIO); 178} 179 180static int 181amr_pci_attach(device_t dev) 182{ 183 struct amr_softc *sc; 184 struct amr_ident *id; 185 int rid, rtype, error; 186 187 debug_called(1); 188 189 /* 190 * Initialise softc. 191 */ 192 sc = device_get_softc(dev); 193 bzero(sc, sizeof(*sc)); 194 sc->amr_dev = dev; 195 196 /* assume failure is 'not configured' */ 197 error = ENXIO; 198 199 /* 200 * Determine board type. 201 */ 202 if ((id = amr_find_ident(dev)) == NULL) 203 return (ENXIO); 204 205 if (id->flags & AMR_ID_QUARTZ) { 206 sc->amr_type |= AMR_TYPE_QUARTZ; 207 } 208 209 if ((amr_force_sg32 == 0) && (id->flags & AMR_ID_DO_SG64) && 210 (sizeof(vm_paddr_t) > 4)) { 211 device_printf(dev, "Using 64-bit DMA\n"); 212 sc->amr_type |= AMR_TYPE_SG64; 213 } 214 215 /* force the busmaster enable bit on */ 216 pci_enable_busmaster(dev); 217 218 /* 219 * Allocate the PCI register window. 220 */ 221 rid = PCIR_BAR(0); 222 rtype = AMR_IS_QUARTZ(sc) ? SYS_RES_MEMORY : SYS_RES_IOPORT; 223 sc->amr_reg = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE); 224 if (sc->amr_reg == NULL) { 225 device_printf(sc->amr_dev, "can't allocate register window\n"); 226 goto out; 227 } 228 sc->amr_btag = rman_get_bustag(sc->amr_reg); 229 sc->amr_bhandle = rman_get_bushandle(sc->amr_reg); 230 231 /* 232 * Allocate and connect our interrupt. 233 */ 234 rid = 0; 235 sc->amr_irq = bus_alloc_resource_any(sc->amr_dev, SYS_RES_IRQ, &rid, 236 RF_SHAREABLE | RF_ACTIVE); 237 if (sc->amr_irq == NULL) { 238 device_printf(sc->amr_dev, "can't allocate interrupt\n"); 239 goto out; 240 } 241 if (bus_setup_intr(sc->amr_dev, sc->amr_irq, 242 INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, NULL, amr_pci_intr, 243 sc, &sc->amr_intr)) { 244 device_printf(sc->amr_dev, "can't set up interrupt\n"); 245 goto out; 246 } 247 248 debug(2, "interrupt attached"); 249 250 /* assume failure is 'out of memory' */ 251 error = ENOMEM; 252 253 /* 254 * Allocate the parent bus DMA tag appropriate for PCI. 255 */ 256 if (bus_dma_tag_create(bus_get_dma_tag(dev), /* PCI parent */ 257 1, 0, /* alignment,boundary */ 258 AMR_IS_SG64(sc) ? 259 BUS_SPACE_MAXADDR : 260 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 261 BUS_SPACE_MAXADDR, /* highaddr */ 262 NULL, NULL, /* filter, filterarg */ 263 BUS_SPACE_MAXSIZE, /* maxsize */ 264 BUS_SPACE_UNRESTRICTED, /* nsegments */ 265 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 266 0, /* flags */ 267 NULL, NULL, /* lockfunc, lockarg */ 268 &sc->amr_parent_dmat)) { 269 device_printf(dev, "can't allocate parent DMA tag\n"); 270 goto out; 271 } 272 273 /* 274 * Create DMA tag for mapping buffers into controller-addressable space. 275 */ 276 if (bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ 277 1, 0, /* alignment,boundary */ 278 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 279 BUS_SPACE_MAXADDR, /* highaddr */ 280 NULL, NULL, /* filter, filterarg */ 281 DFLTPHYS, /* maxsize */ 282 AMR_NSEG, /* nsegments */ 283 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 284 0, /* flags */ 285 busdma_lock_mutex, /* lockfunc */ 286 &sc->amr_list_lock, /* lockarg */ 287 &sc->amr_buffer_dmat)) { 288 device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n"); 289 goto out; 290 } 291 292 if (bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ 293 1, 0, /* alignment,boundary */ 294 BUS_SPACE_MAXADDR, /* lowaddr */ 295 BUS_SPACE_MAXADDR, /* highaddr */ 296 NULL, NULL, /* filter, filterarg */ 297 DFLTPHYS, /* maxsize */ 298 AMR_NSEG, /* nsegments */ 299 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 300 0, /* flags */ 301 busdma_lock_mutex, /* lockfunc */ 302 &sc->amr_list_lock, /* lockarg */ 303 &sc->amr_buffer64_dmat)) { 304 device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n"); 305 goto out; 306 } 307 308 debug(2, "dma tag done"); 309 310 /* 311 * Allocate and set up mailbox in a bus-visible fashion. 312 */ 313 mtx_init(&sc->amr_list_lock, "AMR List Lock", NULL, MTX_DEF); 314 mtx_init(&sc->amr_hw_lock, "AMR HW Lock", NULL, MTX_DEF); 315 if ((error = amr_setup_mbox(sc)) != 0) 316 goto out; 317 318 debug(2, "mailbox setup"); 319 320 /* 321 * Build the scatter/gather buffers. 322 */ 323 if ((error = amr_sglist_map(sc)) != 0) 324 goto out; 325 debug(2, "s/g list mapped"); 326 327 if ((error = amr_ccb_map(sc)) != 0) 328 goto out; 329 debug(2, "ccb mapped"); 330 331 332 /* 333 * Do bus-independant initialisation, bring controller online. 334 */ 335 error = amr_attach(sc); 336 337out: 338 if (error) 339 amr_pci_free(sc); 340 return(error); 341} 342 343/******************************************************************************** 344 * Disconnect from the controller completely, in preparation for unload. 345 */ 346static int 347amr_pci_detach(device_t dev) 348{ 349 struct amr_softc *sc = device_get_softc(dev); 350 int error; 351 352 debug_called(1); 353 354 if (sc->amr_state & AMR_STATE_OPEN) 355 return(EBUSY); 356 357 if ((error = amr_pci_shutdown(dev))) 358 return(error); 359 360 amr_pci_free(sc); 361 362 return(0); 363} 364 365/******************************************************************************** 366 * Bring the controller down to a dormant state and detach all child devices. 367 * 368 * This function is called before detach, system shutdown, or before performing 369 * an operation which may add or delete system disks. (Call amr_startup to 370 * resume normal operation.) 371 * 372 * Note that we can assume that the bioq on the controller is empty, as we won't 373 * allow shutdown if any device is open. 374 */ 375static int 376amr_pci_shutdown(device_t dev) 377{ 378 struct amr_softc *sc = device_get_softc(dev); 379 int i,error; 380 381 debug_called(1); 382 383 /* mark ourselves as in-shutdown */ 384 sc->amr_state |= AMR_STATE_SHUTDOWN; 385 386 387 /* flush controller */ 388 device_printf(sc->amr_dev, "flushing cache..."); 389 printf("%s\n", amr_flush(sc) ? "failed" : "done"); 390 391 error = 0; 392 393 /* delete all our child devices */ 394 for(i = 0 ; i < AMR_MAXLD; i++) { 395 if( sc->amr_drive[i].al_disk != 0) { 396 if((error = device_delete_child(sc->amr_dev,sc->amr_drive[i].al_disk)) != 0) 397 goto shutdown_out; 398 sc->amr_drive[i].al_disk = 0; 399 } 400 } 401 402 /* XXX disable interrupts? */ 403 404shutdown_out: 405 return(error); 406} 407 408/******************************************************************************** 409 * Bring the controller to a quiescent state, ready for system suspend. 410 */ 411static int 412amr_pci_suspend(device_t dev) 413{ 414 struct amr_softc *sc = device_get_softc(dev); 415 416 debug_called(1); 417 418 sc->amr_state |= AMR_STATE_SUSPEND; 419 420 /* flush controller */ 421 device_printf(sc->amr_dev, "flushing cache..."); 422 printf("%s\n", amr_flush(sc) ? "failed" : "done"); 423 424 /* XXX disable interrupts? */ 425 426 return(0); 427} 428 429/******************************************************************************** 430 * Bring the controller back to a state ready for operation. 431 */ 432static int 433amr_pci_resume(device_t dev) 434{ 435 struct amr_softc *sc = device_get_softc(dev); 436 437 debug_called(1); 438 439 sc->amr_state &= ~AMR_STATE_SUSPEND; 440 441 /* XXX enable interrupts? */ 442 443 return(0); 444} 445 446/******************************************************************************* 447 * Take an interrupt, or be poked by other code to look for interrupt-worthy 448 * status. 449 */ 450static void 451amr_pci_intr(void *arg) 452{ 453 struct amr_softc *sc = (struct amr_softc *)arg; 454 455 debug_called(3); 456 457 /* collect finished commands, queue anything waiting */ 458 amr_done(sc); 459} 460 461/******************************************************************************** 462 * Free all of the resources associated with (sc) 463 * 464 * Should not be called if the controller is active. 465 */ 466static void 467amr_pci_free(struct amr_softc *sc) 468{ 469 void *p; 470 471 debug_called(1); 472 473 amr_free(sc); 474 475 /* destroy data-transfer DMA tag */ 476 if (sc->amr_buffer_dmat) 477 bus_dma_tag_destroy(sc->amr_buffer_dmat); 478 if (sc->amr_buffer64_dmat) 479 bus_dma_tag_destroy(sc->amr_buffer64_dmat); 480 481 /* free and destroy DMA memory and tag for passthrough pool */ 482 if (sc->amr_ccb) { 483 bus_dmamap_unload(sc->amr_ccb_dmat, sc->amr_ccb_dmamap); 484 bus_dmamem_free(sc->amr_ccb_dmat, sc->amr_ccb, sc->amr_ccb_dmamap); 485 } 486 if (sc->amr_ccb_dmat) 487 bus_dma_tag_destroy(sc->amr_ccb_dmat); 488 489 /* free and destroy DMA memory and tag for s/g lists */ 490 if (sc->amr_sgtable) { 491 bus_dmamap_unload(sc->amr_sg_dmat, sc->amr_sg_dmamap); 492 bus_dmamem_free(sc->amr_sg_dmat, sc->amr_sgtable, sc->amr_sg_dmamap); 493 } 494 if (sc->amr_sg_dmat) 495 bus_dma_tag_destroy(sc->amr_sg_dmat); 496 497 /* free and destroy DMA memory and tag for mailbox */ 498 p = (void *)(uintptr_t)(volatile void *)sc->amr_mailbox64; 499 if (sc->amr_mailbox) { 500 bus_dmamap_unload(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap); 501 bus_dmamem_free(sc->amr_mailbox_dmat, p, sc->amr_mailbox_dmamap); 502 } 503 if (sc->amr_mailbox_dmat) 504 bus_dma_tag_destroy(sc->amr_mailbox_dmat); 505 506 /* disconnect the interrupt handler */ 507 if (sc->amr_intr) 508 bus_teardown_intr(sc->amr_dev, sc->amr_irq, sc->amr_intr); 509 if (sc->amr_irq != NULL) 510 bus_release_resource(sc->amr_dev, SYS_RES_IRQ, 0, sc->amr_irq); 511 512 /* destroy the parent DMA tag */ 513 if (sc->amr_parent_dmat) 514 bus_dma_tag_destroy(sc->amr_parent_dmat); 515 516 /* release the register window mapping */ 517 if (sc->amr_reg != NULL) 518 bus_release_resource(sc->amr_dev, 519 AMR_IS_QUARTZ(sc) ? SYS_RES_MEMORY : SYS_RES_IOPORT, 520 PCIR_BAR(0), sc->amr_reg); 521} 522 523/******************************************************************************** 524 * Allocate and map the scatter/gather table in bus space. 525 */ 526static void 527amr_sglist_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) 528{ 529 uint32_t *addr; 530 531 debug_called(1); 532 533 addr = arg; 534 *addr = segs[0].ds_addr; 535} 536 537static int 538amr_sglist_map(struct amr_softc *sc) 539{ 540 size_t segsize; 541 void *p; 542 int error; 543 544 debug_called(1); 545 546 /* 547 * Create a single tag describing a region large enough to hold all of 548 * the s/g lists we will need. 549 * 550 * Note that we could probably use AMR_LIMITCMD here, but that may become 551 * tunable. 552 */ 553 if (AMR_IS_SG64(sc)) 554 segsize = sizeof(struct amr_sg64entry) * AMR_NSEG * AMR_MAXCMD; 555 else 556 segsize = sizeof(struct amr_sgentry) * AMR_NSEG * AMR_MAXCMD; 557 558 error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ 559 512, 0, /* alignment,boundary */ 560 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 561 BUS_SPACE_MAXADDR, /* highaddr */ 562 NULL, NULL, /* filter, filterarg */ 563 segsize, 1, /* maxsize, nsegments */ 564 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 565 0, /* flags */ 566 NULL, NULL, /* lockfunc, lockarg */ 567 &sc->amr_sg_dmat); 568 if (error != 0) { 569 device_printf(sc->amr_dev, "can't allocate scatter/gather DMA tag\n"); 570 return(ENOMEM); 571 } 572 573 /* 574 * Allocate enough s/g maps for all commands and permanently map them into 575 * controller-visible space. 576 * 577 * XXX this assumes we can get enough space for all the s/g maps in one 578 * contiguous slab. We may need to switch to a more complex arrangement 579 * where we allocate in smaller chunks and keep a lookup table from slot 580 * to bus address. 581 * 582 * XXX HACK ALERT: at least some controllers don't like the s/g memory 583 * being allocated below 0x2000. We leak some memory if 584 * we get some below this mark and allocate again. We 585 * should be able to avoid this with the tag setup, but 586 * that does't seem to work. 587 */ 588retry: 589 error = bus_dmamem_alloc(sc->amr_sg_dmat, (void **)&p, BUS_DMA_NOWAIT, &sc->amr_sg_dmamap); 590 if (error) { 591 device_printf(sc->amr_dev, "can't allocate s/g table\n"); 592 return(ENOMEM); 593 } 594 bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, p, segsize, amr_sglist_helper, &sc->amr_sgbusaddr, 0); 595 if (sc->amr_sgbusaddr < 0x2000) { 596 debug(1, "s/g table too low (0x%x), reallocating\n", sc->amr_sgbusaddr); 597 goto retry; 598 } 599 600 if (AMR_IS_SG64(sc)) 601 sc->amr_sg64table = (struct amr_sg64entry *)p; 602 sc->amr_sgtable = (struct amr_sgentry *)p; 603 604 return(0); 605} 606 607/******************************************************************************** 608 * Allocate and set up mailbox areas for the controller (sc) 609 * 610 * The basic mailbox structure should be 16-byte aligned. 611 */ 612static int 613amr_setup_mbox(struct amr_softc *sc) 614{ 615 int error; 616 void *p; 617 uint32_t baddr; 618 619 debug_called(1); 620 621 /* 622 * Create a single tag describing a region large enough to hold the entire 623 * mailbox. 624 */ 625 error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ 626 16, 0, /* alignment,boundary */ 627 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 628 BUS_SPACE_MAXADDR, /* highaddr */ 629 NULL, NULL, /* filter, filterarg */ 630 sizeof(struct amr_mailbox64), /* maxsize */ 631 1, /* nsegments */ 632 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 633 0, /* flags */ 634 NULL, NULL, /* lockfunc, lockarg */ 635 &sc->amr_mailbox_dmat); 636 if (error != 0) { 637 device_printf(sc->amr_dev, "can't allocate mailbox tag\n"); 638 return(ENOMEM); 639 } 640 641 /* 642 * Allocate the mailbox structure and permanently map it into 643 * controller-visible space. 644 */ 645 error = bus_dmamem_alloc(sc->amr_mailbox_dmat, (void **)&p, BUS_DMA_NOWAIT, 646 &sc->amr_mailbox_dmamap); 647 if (error) { 648 device_printf(sc->amr_dev, "can't allocate mailbox memory\n"); 649 return(ENOMEM); 650 } 651 bus_dmamap_load(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap, p, 652 sizeof(struct amr_mailbox64), amr_sglist_helper, &baddr, 0); 653 /* 654 * Conventional mailbox is inside the mailbox64 region. 655 */ 656 /* save physical base of the basic mailbox structure */ 657 sc->amr_mailboxphys = baddr + offsetof(struct amr_mailbox64, mb); 658 bzero(p, sizeof(struct amr_mailbox64)); 659 sc->amr_mailbox64 = (struct amr_mailbox64 *)p; 660 sc->amr_mailbox = &sc->amr_mailbox64->mb; 661 662 return(0); 663} 664 665static int 666amr_ccb_map(struct amr_softc *sc) 667{ 668 int ccbsize, error; 669 670 /* 671 * Passthrough and Extended passthrough structures will share the same 672 * memory. 673 */ 674 ccbsize = sizeof(union amr_ccb) * AMR_MAXCMD; 675 error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ 676 128, 0, /* alignment,boundary */ 677 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 678 BUS_SPACE_MAXADDR, /* highaddr */ 679 NULL, NULL, /* filter, filterarg */ 680 ccbsize, /* maxsize */ 681 1, /* nsegments */ 682 ccbsize, /* maxsegsize */ 683 0, /* flags */ 684 NULL, NULL, /* lockfunc, lockarg */ 685 &sc->amr_ccb_dmat); 686 if (error != 0) { 687 device_printf(sc->amr_dev, "can't allocate ccb tag\n"); 688 return (ENOMEM); 689 } 690 691 error = bus_dmamem_alloc(sc->amr_ccb_dmat, (void **)&sc->amr_ccb, 692 BUS_DMA_NOWAIT, &sc->amr_ccb_dmamap); 693 if (error) { 694 device_printf(sc->amr_dev, "can't allocate ccb memory\n"); 695 return (ENOMEM); 696 } 697 bus_dmamap_load(sc->amr_ccb_dmat, sc->amr_ccb_dmamap, sc->amr_ccb, 698 ccbsize, amr_sglist_helper, &sc->amr_ccb_busaddr, 0); 699 bzero(sc->amr_ccb, ccbsize); 700 701 return (0); 702} 703 704