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