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