twe_freebsd.c revision 166901
1/*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2003 Paul Saab 4 * Copyright (c) 2003 Vinod Kashyap 5 * Copyright (c) 2000 BSDi 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: head/sys/dev/twe/twe_freebsd.c 166901 2007-02-23 12:19:07Z piso $ 30 */ 31 32/* 33 * FreeBSD-specific code. 34 */ 35 36#include <dev/twe/twe_compat.h> 37#include <dev/twe/twereg.h> 38#include <dev/twe/tweio.h> 39#include <dev/twe/twevar.h> 40#include <dev/twe/twe_tables.h> 41 42#include <vm/vm.h> 43 44static devclass_t twe_devclass; 45 46#ifdef TWE_DEBUG 47static u_int32_t twed_bio_in; 48#define TWED_BIO_IN twed_bio_in++ 49static u_int32_t twed_bio_out; 50#define TWED_BIO_OUT twed_bio_out++ 51#else 52#define TWED_BIO_IN 53#define TWED_BIO_OUT 54#endif 55 56static void twe_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error); 57static void twe_setup_request_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error); 58 59/******************************************************************************** 60 ******************************************************************************** 61 Control device interface 62 ******************************************************************************** 63 ********************************************************************************/ 64 65static d_open_t twe_open; 66static d_close_t twe_close; 67static d_ioctl_t twe_ioctl_wrapper; 68 69static struct cdevsw twe_cdevsw = { 70 .d_version = D_VERSION, 71 .d_flags = D_NEEDGIANT, 72 .d_open = twe_open, 73 .d_close = twe_close, 74 .d_ioctl = twe_ioctl_wrapper, 75 .d_name = "twe", 76}; 77 78/******************************************************************************** 79 * Accept an open operation on the control device. 80 */ 81static int 82twe_open(struct cdev *dev, int flags, int fmt, d_thread_t *td) 83{ 84 int unit = minor(dev); 85 struct twe_softc *sc = devclass_get_softc(twe_devclass, unit); 86 87 sc->twe_state |= TWE_STATE_OPEN; 88 return(0); 89} 90 91/******************************************************************************** 92 * Accept the last close on the control device. 93 */ 94static int 95twe_close(struct cdev *dev, int flags, int fmt, d_thread_t *td) 96{ 97 int unit = minor(dev); 98 struct twe_softc *sc = devclass_get_softc(twe_devclass, unit); 99 100 sc->twe_state &= ~TWE_STATE_OPEN; 101 return (0); 102} 103 104/******************************************************************************** 105 * Handle controller-specific control operations. 106 */ 107static int 108twe_ioctl_wrapper(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *td) 109{ 110 struct twe_softc *sc = (struct twe_softc *)dev->si_drv1; 111 112 return(twe_ioctl(sc, cmd, addr)); 113} 114 115/******************************************************************************** 116 ******************************************************************************** 117 PCI device interface 118 ******************************************************************************** 119 ********************************************************************************/ 120 121static int twe_probe(device_t dev); 122static int twe_attach(device_t dev); 123static void twe_free(struct twe_softc *sc); 124static int twe_detach(device_t dev); 125static int twe_shutdown(device_t dev); 126static int twe_suspend(device_t dev); 127static int twe_resume(device_t dev); 128static void twe_pci_intr(void *arg); 129static void twe_intrhook(void *arg); 130 131static device_method_t twe_methods[] = { 132 /* Device interface */ 133 DEVMETHOD(device_probe, twe_probe), 134 DEVMETHOD(device_attach, twe_attach), 135 DEVMETHOD(device_detach, twe_detach), 136 DEVMETHOD(device_shutdown, twe_shutdown), 137 DEVMETHOD(device_suspend, twe_suspend), 138 DEVMETHOD(device_resume, twe_resume), 139 140 DEVMETHOD(bus_print_child, bus_generic_print_child), 141 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 142 { 0, 0 } 143}; 144 145static driver_t twe_pci_driver = { 146 "twe", 147 twe_methods, 148 sizeof(struct twe_softc) 149}; 150 151DRIVER_MODULE(twe, pci, twe_pci_driver, twe_devclass, 0, 0); 152 153/******************************************************************************** 154 * Match a 3ware Escalade ATA RAID controller. 155 */ 156static int 157twe_probe(device_t dev) 158{ 159 160 debug_called(4); 161 162 if ((pci_get_vendor(dev) == TWE_VENDOR_ID) && 163 ((pci_get_device(dev) == TWE_DEVICE_ID) || 164 (pci_get_device(dev) == TWE_DEVICE_ID_ASIC))) { 165 device_set_desc_copy(dev, TWE_DEVICE_NAME ". Driver version " TWE_DRIVER_VERSION_STRING); 166 return(BUS_PROBE_DEFAULT); 167 } 168 return(ENXIO); 169} 170 171/******************************************************************************** 172 * Allocate resources, initialise the controller. 173 */ 174static int 175twe_attach(device_t dev) 176{ 177 struct twe_softc *sc; 178 int rid, error; 179 u_int32_t command; 180 181 debug_called(4); 182 183 /* 184 * Initialise the softc structure. 185 */ 186 sc = device_get_softc(dev); 187 sc->twe_dev = dev; 188 189 sysctl_ctx_init(&sc->sysctl_ctx); 190 sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, 191 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, 192 device_get_nameunit(dev), CTLFLAG_RD, 0, ""); 193 if (sc->sysctl_tree == NULL) { 194 twe_printf(sc, "cannot add sysctl tree node\n"); 195 return (ENXIO); 196 } 197 SYSCTL_ADD_STRING(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), 198 OID_AUTO, "driver_version", CTLFLAG_RD, TWE_DRIVER_VERSION_STRING, 0, 199 "TWE driver version"); 200 201 /* 202 * Make sure we are going to be able to talk to this board. 203 */ 204 command = pci_read_config(dev, PCIR_COMMAND, 2); 205 if ((command & PCIM_CMD_PORTEN) == 0) { 206 twe_printf(sc, "register window not available\n"); 207 return(ENXIO); 208 } 209 /* 210 * Force the busmaster enable bit on, in case the BIOS forgot. 211 */ 212 command |= PCIM_CMD_BUSMASTEREN; 213 pci_write_config(dev, PCIR_COMMAND, command, 2); 214 215 /* 216 * Allocate the PCI register window. 217 */ 218 rid = TWE_IO_CONFIG_REG; 219 if ((sc->twe_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 220 RF_ACTIVE)) == NULL) { 221 twe_printf(sc, "can't allocate register window\n"); 222 twe_free(sc); 223 return(ENXIO); 224 } 225 sc->twe_btag = rman_get_bustag(sc->twe_io); 226 sc->twe_bhandle = rman_get_bushandle(sc->twe_io); 227 228 /* 229 * Allocate the parent bus DMA tag appropriate for PCI. 230 */ 231 if (bus_dma_tag_create(NULL, /* parent */ 232 1, 0, /* alignment, boundary */ 233 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 234 BUS_SPACE_MAXADDR, /* highaddr */ 235 NULL, NULL, /* filter, filterarg */ 236 MAXBSIZE, TWE_MAX_SGL_LENGTH, /* maxsize, nsegments */ 237 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 238 0, /* flags */ 239 NULL, /* lockfunc */ 240 NULL, /* lockarg */ 241 &sc->twe_parent_dmat)) { 242 twe_printf(sc, "can't allocate parent DMA tag\n"); 243 twe_free(sc); 244 return(ENOMEM); 245 } 246 247 /* 248 * Allocate and connect our interrupt. 249 */ 250 rid = 0; 251 if ((sc->twe_irq = bus_alloc_resource_any(sc->twe_dev, SYS_RES_IRQ, 252 &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 253 twe_printf(sc, "can't allocate interrupt\n"); 254 twe_free(sc); 255 return(ENXIO); 256 } 257 if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY, 258 NULL, twe_pci_intr, sc, &sc->twe_intr)) { 259 twe_printf(sc, "can't set up interrupt\n"); 260 twe_free(sc); 261 return(ENXIO); 262 } 263 264 /* 265 * Create DMA tag for mapping command's into controller-addressable space. 266 */ 267 if (bus_dma_tag_create(sc->twe_parent_dmat, /* parent */ 268 1, 0, /* alignment, boundary */ 269 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 270 BUS_SPACE_MAXADDR, /* highaddr */ 271 NULL, NULL, /* filter, filterarg */ 272 sizeof(TWE_Command) * 273 TWE_Q_LENGTH, 1, /* maxsize, nsegments */ 274 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 275 0, /* flags */ 276 NULL, /* lockfunc */ 277 NULL, /* lockarg */ 278 &sc->twe_cmd_dmat)) { 279 twe_printf(sc, "can't allocate data buffer DMA tag\n"); 280 twe_free(sc); 281 return(ENOMEM); 282 } 283 /* 284 * Allocate memory and make it available for DMA. 285 */ 286 if (bus_dmamem_alloc(sc->twe_cmd_dmat, (void **)&sc->twe_cmd, 287 BUS_DMA_NOWAIT, &sc->twe_cmdmap)) { 288 twe_printf(sc, "can't allocate command memory\n"); 289 return(ENOMEM); 290 } 291 bus_dmamap_load(sc->twe_cmd_dmat, sc->twe_cmdmap, sc->twe_cmd, 292 sizeof(TWE_Command) * TWE_Q_LENGTH, 293 twe_setup_request_dmamap, sc, 0); 294 bzero(sc->twe_cmd, sizeof(TWE_Command) * TWE_Q_LENGTH); 295 296 /* 297 * Create DMA tag for mapping objects into controller-addressable space. 298 */ 299 if (bus_dma_tag_create(sc->twe_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, TWE_MAX_SGL_LENGTH,/* maxsize, nsegments */ 305 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 306 BUS_DMA_ALLOCNOW, /* flags */ 307 busdma_lock_mutex, /* lockfunc */ 308 &Giant, /* lockarg */ 309 &sc->twe_buffer_dmat)) { 310 twe_printf(sc, "can't allocate data buffer DMA tag\n"); 311 twe_free(sc); 312 return(ENOMEM); 313 } 314 315 /* 316 * Create DMA tag for mapping objects into controller-addressable space. 317 */ 318 if (bus_dma_tag_create(sc->twe_parent_dmat, /* parent */ 319 1, 0, /* alignment, boundary */ 320 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 321 BUS_SPACE_MAXADDR, /* highaddr */ 322 NULL, NULL, /* filter, filterarg */ 323 MAXBSIZE, 1, /* maxsize, nsegments */ 324 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 325 0, /* flags */ 326 NULL, /* lockfunc */ 327 NULL, /* lockarg */ 328 &sc->twe_immediate_dmat)) { 329 twe_printf(sc, "can't allocate data buffer DMA tag\n"); 330 twe_free(sc); 331 return(ENOMEM); 332 } 333 /* 334 * Allocate memory for requests which cannot sleep or support continuation. 335 */ 336 if (bus_dmamem_alloc(sc->twe_immediate_dmat, (void **)&sc->twe_immediate, 337 BUS_DMA_NOWAIT, &sc->twe_immediate_map)) { 338 twe_printf(sc, "can't allocate memory for immediate requests\n"); 339 return(ENOMEM); 340 } 341 342 /* 343 * Initialise the controller and driver core. 344 */ 345 if ((error = twe_setup(sc))) { 346 twe_free(sc); 347 return(error); 348 } 349 350 /* 351 * Print some information about the controller and configuration. 352 */ 353 twe_describe_controller(sc); 354 355 /* 356 * Create the control device. 357 */ 358 sc->twe_dev_t = make_dev(&twe_cdevsw, device_get_unit(sc->twe_dev), UID_ROOT, GID_OPERATOR, 359 S_IRUSR | S_IWUSR, "twe%d", device_get_unit(sc->twe_dev)); 360 sc->twe_dev_t->si_drv1 = sc; 361 /* 362 * Schedule ourselves to bring the controller up once interrupts are available. 363 * This isn't strictly necessary, since we disable interrupts while probing the 364 * controller, but it is more in keeping with common practice for other disk 365 * devices. 366 */ 367 sc->twe_ich.ich_func = twe_intrhook; 368 sc->twe_ich.ich_arg = sc; 369 if (config_intrhook_establish(&sc->twe_ich) != 0) { 370 twe_printf(sc, "can't establish configuration hook\n"); 371 twe_free(sc); 372 return(ENXIO); 373 } 374 375 return(0); 376} 377 378/******************************************************************************** 379 * Free all of the resources associated with (sc). 380 * 381 * Should not be called if the controller is active. 382 */ 383static void 384twe_free(struct twe_softc *sc) 385{ 386 struct twe_request *tr; 387 388 debug_called(4); 389 390 /* throw away any command buffers */ 391 while ((tr = twe_dequeue_free(sc)) != NULL) 392 twe_free_request(tr); 393 394 if (sc->twe_cmd != NULL) { 395 bus_dmamap_unload(sc->twe_cmd_dmat, sc->twe_cmdmap); 396 bus_dmamem_free(sc->twe_cmd_dmat, sc->twe_cmd, sc->twe_cmdmap); 397 } 398 399 if (sc->twe_immediate != NULL) { 400 bus_dmamap_unload(sc->twe_immediate_dmat, sc->twe_immediate_map); 401 bus_dmamem_free(sc->twe_immediate_dmat, sc->twe_immediate, 402 sc->twe_immediate_map); 403 } 404 405 if (sc->twe_immediate_dmat) 406 bus_dma_tag_destroy(sc->twe_immediate_dmat); 407 408 /* destroy the data-transfer DMA tag */ 409 if (sc->twe_buffer_dmat) 410 bus_dma_tag_destroy(sc->twe_buffer_dmat); 411 412 /* disconnect the interrupt handler */ 413 if (sc->twe_intr) 414 bus_teardown_intr(sc->twe_dev, sc->twe_irq, sc->twe_intr); 415 if (sc->twe_irq != NULL) 416 bus_release_resource(sc->twe_dev, SYS_RES_IRQ, 0, sc->twe_irq); 417 418 /* destroy the parent DMA tag */ 419 if (sc->twe_parent_dmat) 420 bus_dma_tag_destroy(sc->twe_parent_dmat); 421 422 /* release the register window mapping */ 423 if (sc->twe_io != NULL) 424 bus_release_resource(sc->twe_dev, SYS_RES_IOPORT, TWE_IO_CONFIG_REG, sc->twe_io); 425 426 /* destroy control device */ 427 if (sc->twe_dev_t != (struct cdev *)NULL) 428 destroy_dev(sc->twe_dev_t); 429 430 sysctl_ctx_free(&sc->sysctl_ctx); 431} 432 433/******************************************************************************** 434 * Disconnect from the controller completely, in preparation for unload. 435 */ 436static int 437twe_detach(device_t dev) 438{ 439 struct twe_softc *sc = device_get_softc(dev); 440 int s, error; 441 442 debug_called(4); 443 444 error = EBUSY; 445 s = splbio(); 446 if (sc->twe_state & TWE_STATE_OPEN) 447 goto out; 448 449 /* 450 * Shut the controller down. 451 */ 452 if (twe_shutdown(dev)) 453 goto out; 454 455 twe_free(sc); 456 457 error = 0; 458 out: 459 splx(s); 460 return(error); 461} 462 463/******************************************************************************** 464 * Bring the controller down to a dormant state and detach all child devices. 465 * 466 * Note that we can assume that the bioq on the controller is empty, as we won't 467 * allow shutdown if any device is open. 468 */ 469static int 470twe_shutdown(device_t dev) 471{ 472 struct twe_softc *sc = device_get_softc(dev); 473 int i, s, error = 0; 474 475 debug_called(4); 476 477 s = splbio(); 478 479 /* 480 * Delete all our child devices. 481 */ 482 for (i = 0; i < TWE_MAX_UNITS; i++) { 483 if (sc->twe_drive[i].td_disk != 0) { 484 if ((error = twe_detach_drive(sc, i)) != 0) 485 goto out; 486 } 487 } 488 489 /* 490 * Bring the controller down. 491 */ 492 twe_deinit(sc); 493 494out: 495 splx(s); 496 return(error); 497} 498 499/******************************************************************************** 500 * Bring the controller to a quiescent state, ready for system suspend. 501 */ 502static int 503twe_suspend(device_t dev) 504{ 505 struct twe_softc *sc = device_get_softc(dev); 506 int s; 507 508 debug_called(4); 509 510 s = splbio(); 511 sc->twe_state |= TWE_STATE_SUSPEND; 512 513 twe_disable_interrupts(sc); 514 splx(s); 515 516 return(0); 517} 518 519/******************************************************************************** 520 * Bring the controller back to a state ready for operation. 521 */ 522static int 523twe_resume(device_t dev) 524{ 525 struct twe_softc *sc = device_get_softc(dev); 526 527 debug_called(4); 528 529 sc->twe_state &= ~TWE_STATE_SUSPEND; 530 twe_enable_interrupts(sc); 531 532 return(0); 533} 534 535/******************************************************************************* 536 * Take an interrupt, or be poked by other code to look for interrupt-worthy 537 * status. 538 */ 539static void 540twe_pci_intr(void *arg) 541{ 542 twe_intr((struct twe_softc *)arg); 543} 544 545/******************************************************************************** 546 * Delayed-startup hook 547 */ 548static void 549twe_intrhook(void *arg) 550{ 551 struct twe_softc *sc = (struct twe_softc *)arg; 552 553 /* pull ourselves off the intrhook chain */ 554 config_intrhook_disestablish(&sc->twe_ich); 555 556 /* call core startup routine */ 557 twe_init(sc); 558} 559 560/******************************************************************************** 561 * Given a detected drive, attach it to the bio interface. 562 * 563 * This is called from twe_add_unit. 564 */ 565int 566twe_attach_drive(struct twe_softc *sc, struct twe_drive *dr) 567{ 568 char buf[80]; 569 int error; 570 571 dr->td_disk = device_add_child(sc->twe_dev, NULL, -1); 572 if (dr->td_disk == NULL) { 573 twe_printf(sc, "Cannot add unit\n"); 574 return (EIO); 575 } 576 device_set_ivars(dr->td_disk, dr); 577 578 /* 579 * XXX It would make sense to test the online/initialising bits, but they seem to be 580 * always set... 581 */ 582 sprintf(buf, "Unit %d, %s, %s", 583 dr->td_twe_unit, 584 twe_describe_code(twe_table_unittype, dr->td_type), 585 twe_describe_code(twe_table_unitstate, dr->td_state & TWE_PARAM_UNITSTATUS_MASK)); 586 device_set_desc_copy(dr->td_disk, buf); 587 588 if ((error = bus_generic_attach(sc->twe_dev)) != 0) { 589 twe_printf(sc, "Cannot attach unit to controller. error = %d\n", error); 590 return (EIO); 591 } 592 return (0); 593} 594 595/******************************************************************************** 596 * Detach the specified unit if it exsists 597 * 598 * This is called from twe_del_unit. 599 */ 600int 601twe_detach_drive(struct twe_softc *sc, int unit) 602{ 603 int error = 0; 604 605 if ((error = device_delete_child(sc->twe_dev, sc->twe_drive[unit].td_disk)) != 0) { 606 twe_printf(sc, "failed to delete unit %d\n", unit); 607 return(error); 608 } 609 bzero(&sc->twe_drive[unit], sizeof(sc->twe_drive[unit])); 610 return(error); 611} 612 613/******************************************************************************** 614 * Clear a PCI parity error. 615 */ 616void 617twe_clear_pci_parity_error(struct twe_softc *sc) 618{ 619 TWE_CONTROL(sc, TWE_CONTROL_CLEAR_PARITY_ERROR); 620 pci_write_config(sc->twe_dev, PCIR_STATUS, TWE_PCI_CLEAR_PARITY_ERROR, 2); 621} 622 623/******************************************************************************** 624 * Clear a PCI abort. 625 */ 626void 627twe_clear_pci_abort(struct twe_softc *sc) 628{ 629 TWE_CONTROL(sc, TWE_CONTROL_CLEAR_PCI_ABORT); 630 pci_write_config(sc->twe_dev, PCIR_STATUS, TWE_PCI_CLEAR_PCI_ABORT, 2); 631} 632 633/******************************************************************************** 634 ******************************************************************************** 635 Disk device 636 ******************************************************************************** 637 ********************************************************************************/ 638 639/* 640 * Disk device softc 641 */ 642struct twed_softc 643{ 644 device_t twed_dev; 645 struct twe_softc *twed_controller; /* parent device softc */ 646 struct twe_drive *twed_drive; /* drive data in parent softc */ 647 struct disk *twed_disk; /* generic disk handle */ 648}; 649 650/* 651 * Disk device bus interface 652 */ 653static int twed_probe(device_t dev); 654static int twed_attach(device_t dev); 655static int twed_detach(device_t dev); 656 657static device_method_t twed_methods[] = { 658 DEVMETHOD(device_probe, twed_probe), 659 DEVMETHOD(device_attach, twed_attach), 660 DEVMETHOD(device_detach, twed_detach), 661 { 0, 0 } 662}; 663 664static driver_t twed_driver = { 665 "twed", 666 twed_methods, 667 sizeof(struct twed_softc) 668}; 669 670static devclass_t twed_devclass; 671DRIVER_MODULE(twed, twe, twed_driver, twed_devclass, 0, 0); 672 673/* 674 * Disk device control interface. 675 */ 676 677#ifdef FREEBSD_4 678static int disks_registered = 0; 679#endif 680 681/******************************************************************************** 682 * Handle open from generic layer. 683 * 684 * Note that this is typically only called by the diskslice code, and not 685 * for opens on subdevices (eg. slices, partitions). 686 */ 687static int 688twed_open(struct disk *dp) 689{ 690 struct twed_softc *sc = (struct twed_softc *)dp->d_drv1; 691 692 debug_called(4); 693 694 if (sc == NULL) 695 return (ENXIO); 696 697 /* check that the controller is up and running */ 698 if (sc->twed_controller->twe_state & TWE_STATE_SHUTDOWN) 699 return(ENXIO); 700 701 return (0); 702} 703 704/******************************************************************************** 705 * Handle an I/O request. 706 */ 707static void 708twed_strategy(twe_bio *bp) 709{ 710 struct twed_softc *sc = (struct twed_softc *)TWE_BIO_SOFTC(bp); 711 712 debug_called(4); 713 714 bp->bio_driver1 = &sc->twed_drive->td_twe_unit; 715 TWED_BIO_IN; 716 717 /* bogus disk? */ 718 if (sc == NULL || sc->twed_drive->td_disk == NULL) { 719 TWE_BIO_SET_ERROR(bp, EINVAL); 720 printf("twe: bio for invalid disk!\n"); 721 TWE_BIO_DONE(bp); 722 TWED_BIO_OUT; 723 return; 724 } 725 726 /* perform accounting */ 727 TWE_BIO_STATS_START(bp); 728 729 /* queue the bio on the controller */ 730 twe_enqueue_bio(sc->twed_controller, bp); 731 732 /* poke the controller to start I/O */ 733 twe_startio(sc->twed_controller); 734 return; 735} 736 737/******************************************************************************** 738 * System crashdump support 739 */ 740static int 741twed_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length) 742{ 743 struct twed_softc *twed_sc; 744 struct twe_softc *twe_sc; 745 int error; 746 struct disk *dp; 747 748 dp = arg; 749 twed_sc = (struct twed_softc *)dp->d_drv1; 750 if (twed_sc == NULL) 751 return(ENXIO); 752 twe_sc = (struct twe_softc *)twed_sc->twed_controller; 753 754 if (length > 0) { 755 if ((error = twe_dump_blocks(twe_sc, twed_sc->twed_drive->td_twe_unit, offset / TWE_BLOCK_SIZE, virtual, length / TWE_BLOCK_SIZE)) != 0) 756 return(error); 757 } 758 return(0); 759} 760 761/******************************************************************************** 762 * Handle completion of an I/O request. 763 */ 764void 765twed_intr(twe_bio *bp) 766{ 767 debug_called(4); 768 769 /* if no error, transfer completed */ 770 if (!TWE_BIO_HAS_ERROR(bp)) 771 TWE_BIO_RESID(bp) = 0; 772 773 TWE_BIO_STATS_END(bp); 774 TWE_BIO_DONE(bp); 775 TWED_BIO_OUT; 776} 777 778/******************************************************************************** 779 * Default probe stub. 780 */ 781static int 782twed_probe(device_t dev) 783{ 784 return (0); 785} 786 787/******************************************************************************** 788 * Attach a unit to the controller. 789 */ 790static int 791twed_attach(device_t dev) 792{ 793 struct twed_softc *sc; 794 device_t parent; 795 796 debug_called(4); 797 798 /* initialise our softc */ 799 sc = device_get_softc(dev); 800 parent = device_get_parent(dev); 801 sc->twed_controller = (struct twe_softc *)device_get_softc(parent); 802 sc->twed_drive = device_get_ivars(dev); 803 sc->twed_dev = dev; 804 805 /* report the drive */ 806 twed_printf(sc, "%uMB (%u sectors)\n", 807 sc->twed_drive->td_size / ((1024 * 1024) / TWE_BLOCK_SIZE), 808 sc->twed_drive->td_size); 809 810 /* attach a generic disk device to ourselves */ 811 812 sc->twed_drive->td_sys_unit = device_get_unit(dev); 813 814 sc->twed_disk = disk_alloc(); 815 sc->twed_disk->d_open = twed_open; 816 sc->twed_disk->d_strategy = twed_strategy; 817 sc->twed_disk->d_dump = (dumper_t *)twed_dump; 818 sc->twed_disk->d_name = "twed"; 819 sc->twed_disk->d_drv1 = sc; 820 sc->twed_disk->d_maxsize = (TWE_MAX_SGL_LENGTH - 1) * PAGE_SIZE; 821 sc->twed_disk->d_sectorsize = TWE_BLOCK_SIZE; 822 sc->twed_disk->d_mediasize = TWE_BLOCK_SIZE * (off_t)sc->twed_drive->td_size; 823 sc->twed_disk->d_fwsectors = sc->twed_drive->td_sectors; 824 sc->twed_disk->d_fwheads = sc->twed_drive->td_heads; 825 sc->twed_disk->d_unit = sc->twed_drive->td_sys_unit; 826 sc->twed_disk->d_flags = DISKFLAG_NEEDSGIANT; 827 828 disk_create(sc->twed_disk, DISK_VERSION); 829 830#ifdef FREEBSD_4 831 disks_registered++; 832#endif 833 834 /* set the maximum I/O size to the theoretical maximum allowed by the S/G list size */ 835 836 return (0); 837} 838 839/******************************************************************************** 840 * Disconnect ourselves from the system. 841 */ 842static int 843twed_detach(device_t dev) 844{ 845 struct twed_softc *sc = (struct twed_softc *)device_get_softc(dev); 846 847 debug_called(4); 848 849 if (sc->twed_disk->d_flags & DISKFLAG_OPEN) 850 return(EBUSY); 851 852 disk_destroy(sc->twed_disk); 853 854#ifdef FREEBSD_4 855 if (--disks_registered == 0) 856 cdevsw_remove(&tweddisk_cdevsw); 857#endif 858 return(0); 859} 860 861/******************************************************************************** 862 ******************************************************************************** 863 Misc 864 ******************************************************************************** 865 ********************************************************************************/ 866 867/******************************************************************************** 868 * Allocate a command buffer 869 */ 870MALLOC_DEFINE(TWE_MALLOC_CLASS, "twe_commands", "twe commands"); 871 872struct twe_request * 873twe_allocate_request(struct twe_softc *sc, int tag) 874{ 875 struct twe_request *tr; 876 877 if ((tr = malloc(sizeof(struct twe_request), TWE_MALLOC_CLASS, M_WAITOK)) == NULL) { 878 twe_printf(sc, "unable to allocate memory for tag %d\n", tag); 879 return(NULL); 880 } 881 bzero(tr, sizeof(*tr)); 882 tr->tr_sc = sc; 883 tr->tr_tag = tag; 884 if (bus_dmamap_create(sc->twe_buffer_dmat, 0, &tr->tr_dmamap)) { 885 twe_free_request(tr); 886 twe_printf(sc, "unable to allocate dmamap for tag %d\n", tag); 887 return(NULL); 888 } 889 return(tr); 890} 891 892/******************************************************************************** 893 * Permanently discard a command buffer. 894 */ 895void 896twe_free_request(struct twe_request *tr) 897{ 898 struct twe_softc *sc = tr->tr_sc; 899 900 debug_called(4); 901 902 bus_dmamap_destroy(sc->twe_buffer_dmat, tr->tr_dmamap); 903 free(tr, TWE_MALLOC_CLASS); 904} 905 906/******************************************************************************** 907 * Map/unmap (tr)'s command and data in the controller's addressable space. 908 * 909 * These routines ensure that the data which the controller is going to try to 910 * access is actually visible to the controller, in a machine-independant 911 * fashion. Due to a hardware limitation, I/O buffers must be 512-byte aligned 912 * and we take care of that here as well. 913 */ 914static void 915twe_fillin_sgl(TWE_SG_Entry *sgl, bus_dma_segment_t *segs, int nsegments, int max_sgl) 916{ 917 int i; 918 919 for (i = 0; i < nsegments; i++) { 920 sgl[i].address = segs[i].ds_addr; 921 sgl[i].length = segs[i].ds_len; 922 } 923 for (; i < max_sgl; i++) { /* XXX necessary? */ 924 sgl[i].address = 0; 925 sgl[i].length = 0; 926 } 927} 928 929static void 930twe_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error) 931{ 932 struct twe_request *tr = (struct twe_request *)arg; 933 struct twe_softc *sc = tr->tr_sc; 934 TWE_Command *cmd = TWE_FIND_COMMAND(tr); 935 936 debug_called(4); 937 938 if (tr->tr_flags & TWE_CMD_MAPPED) 939 panic("already mapped command"); 940 941 tr->tr_flags |= TWE_CMD_MAPPED; 942 943 if (tr->tr_flags & TWE_CMD_IN_PROGRESS) 944 sc->twe_state &= ~TWE_STATE_FRZN; 945 /* save base of first segment in command (applicable if there only one segment) */ 946 tr->tr_dataphys = segs[0].ds_addr; 947 948 /* correct command size for s/g list size */ 949 cmd->generic.size += 2 * nsegments; 950 951 /* 952 * Due to the fact that parameter and I/O commands have the scatter/gather list in 953 * different places, we need to determine which sort of command this actually is 954 * before we can populate it correctly. 955 */ 956 switch(cmd->generic.opcode) { 957 case TWE_OP_GET_PARAM: 958 case TWE_OP_SET_PARAM: 959 cmd->generic.sgl_offset = 2; 960 twe_fillin_sgl(&cmd->param.sgl[0], segs, nsegments, TWE_MAX_SGL_LENGTH); 961 break; 962 case TWE_OP_READ: 963 case TWE_OP_WRITE: 964 cmd->generic.sgl_offset = 3; 965 twe_fillin_sgl(&cmd->io.sgl[0], segs, nsegments, TWE_MAX_SGL_LENGTH); 966 break; 967 case TWE_OP_ATA_PASSTHROUGH: 968 cmd->generic.sgl_offset = 5; 969 twe_fillin_sgl(&cmd->ata.sgl[0], segs, nsegments, TWE_MAX_ATA_SGL_LENGTH); 970 break; 971 default: 972 /* 973 * Fall back to what the linux driver does. 974 * Do this because the API may send an opcode 975 * the driver knows nothing about and this will 976 * at least stop PCIABRT's from hosing us. 977 */ 978 switch (cmd->generic.sgl_offset) { 979 case 2: 980 twe_fillin_sgl(&cmd->param.sgl[0], segs, nsegments, TWE_MAX_SGL_LENGTH); 981 break; 982 case 3: 983 twe_fillin_sgl(&cmd->io.sgl[0], segs, nsegments, TWE_MAX_SGL_LENGTH); 984 break; 985 case 5: 986 twe_fillin_sgl(&cmd->ata.sgl[0], segs, nsegments, TWE_MAX_ATA_SGL_LENGTH); 987 break; 988 } 989 } 990 991 if (tr->tr_flags & TWE_CMD_DATAIN) { 992 if (tr->tr_flags & TWE_CMD_IMMEDIATE) { 993 bus_dmamap_sync(sc->twe_immediate_dmat, sc->twe_immediate_map, 994 BUS_DMASYNC_PREREAD); 995 } else { 996 bus_dmamap_sync(sc->twe_buffer_dmat, tr->tr_dmamap, 997 BUS_DMASYNC_PREREAD); 998 } 999 } 1000 1001 if (tr->tr_flags & TWE_CMD_DATAOUT) { 1002 /* 1003 * if we're using an alignment buffer, and we're writing data 1004 * copy the real data out 1005 */ 1006 if (tr->tr_flags & TWE_CMD_ALIGNBUF) 1007 bcopy(tr->tr_realdata, tr->tr_data, tr->tr_length); 1008 1009 if (tr->tr_flags & TWE_CMD_IMMEDIATE) { 1010 bus_dmamap_sync(sc->twe_immediate_dmat, sc->twe_immediate_map, 1011 BUS_DMASYNC_PREWRITE); 1012 } else { 1013 bus_dmamap_sync(sc->twe_buffer_dmat, tr->tr_dmamap, 1014 BUS_DMASYNC_PREWRITE); 1015 } 1016 } 1017 1018 if (twe_start(tr) == EBUSY) { 1019 tr->tr_sc->twe_state |= TWE_STATE_CTLR_BUSY; 1020 twe_requeue_ready(tr); 1021 } 1022} 1023 1024static void 1025twe_setup_request_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error) 1026{ 1027 struct twe_softc *sc = (struct twe_softc *)arg; 1028 1029 debug_called(4); 1030 1031 /* command can't cross a page boundary */ 1032 sc->twe_cmdphys = segs[0].ds_addr; 1033} 1034 1035int 1036twe_map_request(struct twe_request *tr) 1037{ 1038 struct twe_softc *sc = tr->tr_sc; 1039 int error = 0; 1040 1041 debug_called(4); 1042 1043 if (sc->twe_state & (TWE_STATE_CTLR_BUSY | TWE_STATE_FRZN)) { 1044 twe_requeue_ready(tr); 1045 return (EBUSY); 1046 } 1047 1048 bus_dmamap_sync(sc->twe_cmd_dmat, sc->twe_cmdmap, BUS_DMASYNC_PREWRITE); 1049 1050 /* 1051 * If the command involves data, map that too. 1052 */ 1053 if (tr->tr_data != NULL && ((tr->tr_flags & TWE_CMD_MAPPED) == 0)) { 1054 1055 /* 1056 * Data must be 64-byte aligned; allocate a fixup buffer if it's not. 1057 */ 1058 if (((vm_offset_t)tr->tr_data % TWE_ALIGNMENT) != 0) { 1059 tr->tr_realdata = tr->tr_data; /* save pointer to 'real' data */ 1060 tr->tr_flags |= TWE_CMD_ALIGNBUF; 1061 tr->tr_data = malloc(tr->tr_length, TWE_MALLOC_CLASS, M_NOWAIT); 1062 if (tr->tr_data == NULL) { 1063 twe_printf(sc, "%s: malloc failed\n", __func__); 1064 tr->tr_data = tr->tr_realdata; /* restore original data pointer */ 1065 return(ENOMEM); 1066 } 1067 } 1068 1069 /* 1070 * Map the data buffer into bus space and build the s/g list. 1071 */ 1072 if (tr->tr_flags & TWE_CMD_IMMEDIATE) { 1073 error = bus_dmamap_load(sc->twe_immediate_dmat, sc->twe_immediate_map, sc->twe_immediate, 1074 tr->tr_length, twe_setup_data_dmamap, tr, BUS_DMA_NOWAIT); 1075 } else { 1076 error = bus_dmamap_load(sc->twe_buffer_dmat, tr->tr_dmamap, tr->tr_data, tr->tr_length, 1077 twe_setup_data_dmamap, tr, 0); 1078 } 1079 if (error == EINPROGRESS) { 1080 tr->tr_flags |= TWE_CMD_IN_PROGRESS; 1081 sc->twe_state |= TWE_STATE_FRZN; 1082 error = 0; 1083 } 1084 } else 1085 if ((error = twe_start(tr)) == EBUSY) { 1086 sc->twe_state |= TWE_STATE_CTLR_BUSY; 1087 twe_requeue_ready(tr); 1088 } 1089 1090 return(error); 1091} 1092 1093void 1094twe_unmap_request(struct twe_request *tr) 1095{ 1096 struct twe_softc *sc = tr->tr_sc; 1097 1098 debug_called(4); 1099 1100 bus_dmamap_sync(sc->twe_cmd_dmat, sc->twe_cmdmap, BUS_DMASYNC_POSTWRITE); 1101 1102 /* 1103 * If the command involved data, unmap that too. 1104 */ 1105 if (tr->tr_data != NULL) { 1106 if (tr->tr_flags & TWE_CMD_DATAIN) { 1107 if (tr->tr_flags & TWE_CMD_IMMEDIATE) { 1108 bus_dmamap_sync(sc->twe_immediate_dmat, sc->twe_immediate_map, 1109 BUS_DMASYNC_POSTREAD); 1110 } else { 1111 bus_dmamap_sync(sc->twe_buffer_dmat, tr->tr_dmamap, 1112 BUS_DMASYNC_POSTREAD); 1113 } 1114 1115 /* if we're using an alignment buffer, and we're reading data, copy the real data in */ 1116 if (tr->tr_flags & TWE_CMD_ALIGNBUF) 1117 bcopy(tr->tr_data, tr->tr_realdata, tr->tr_length); 1118 } 1119 if (tr->tr_flags & TWE_CMD_DATAOUT) { 1120 if (tr->tr_flags & TWE_CMD_IMMEDIATE) { 1121 bus_dmamap_sync(sc->twe_immediate_dmat, sc->twe_immediate_map, 1122 BUS_DMASYNC_POSTWRITE); 1123 } else { 1124 bus_dmamap_sync(sc->twe_buffer_dmat, tr->tr_dmamap, 1125 BUS_DMASYNC_POSTWRITE); 1126 } 1127 } 1128 1129 if (tr->tr_flags & TWE_CMD_IMMEDIATE) { 1130 bus_dmamap_unload(sc->twe_immediate_dmat, sc->twe_immediate_map); 1131 } else { 1132 bus_dmamap_unload(sc->twe_buffer_dmat, tr->tr_dmamap); 1133 } 1134 } 1135 1136 /* free alignment buffer if it was used */ 1137 if (tr->tr_flags & TWE_CMD_ALIGNBUF) { 1138 free(tr->tr_data, TWE_MALLOC_CLASS); 1139 tr->tr_data = tr->tr_realdata; /* restore 'real' data pointer */ 1140 } 1141} 1142 1143#ifdef TWE_DEBUG 1144void twe_report(void); 1145/******************************************************************************** 1146 * Print current controller status, call from DDB. 1147 */ 1148void 1149twe_report(void) 1150{ 1151 struct twe_softc *sc; 1152 int i, s; 1153 1154 s = splbio(); 1155 for (i = 0; (sc = devclass_get_softc(twe_devclass, i)) != NULL; i++) 1156 twe_print_controller(sc); 1157 printf("twed: total bio count in %u out %u\n", twed_bio_in, twed_bio_out); 1158 splx(s); 1159} 1160#endif 1161