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