The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/twe/twe_freebsd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 7b118e53f5b1e08848d26c9785835ac2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.