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

Cache object: 8569cd68bde97bfd520d4d2f4e96dc2d


[ 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.