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/buslogic/bt_isa.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  * Product specific probe and attach routines for:
    3  *      Buslogic BT-54X and BT-445 cards
    4  *
    5  * Copyright (c) 1998, 1999 Justin T. Gibbs
    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  *    without modification, immediately at the beginning of the file.
   14  * 2. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   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 FOR
   21  * 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: releng/5.0/sys/dev/buslogic/bt_isa.c 104710 2002-10-09 08:54:32Z peter $
   30  */
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/kernel.h>
   35 #include <sys/module.h>
   36 #include <sys/bus.h>
   37 
   38 #include <machine/bus_pio.h>
   39 #include <machine/bus.h>
   40 #include <machine/resource.h>
   41 #include <sys/rman.h>
   42 
   43 #include <isa/isavar.h>
   44 #include <dev/buslogic/btreg.h>
   45 
   46 #include <cam/scsi/scsi_all.h>
   47 
   48 static  bus_dma_filter_t btvlbouncefilter;
   49 static  bus_dmamap_callback_t btmapsensebuffers;
   50 
   51 static int
   52 bt_isa_alloc_resources(device_t dev, u_long portstart, u_long portend)
   53 {
   54         int rid;
   55         struct resource *port;
   56         struct resource *irq;
   57         struct resource *drq;
   58 
   59         rid = 0;
   60         port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
   61                                   portstart, portend, BT_NREGS, RF_ACTIVE);
   62         if (!port)
   63                 return (ENOMEM);
   64 
   65         if (isa_get_irq(dev) != -1) {
   66                 rid = 0;
   67                 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
   68                                          0, ~0, 1, RF_ACTIVE);
   69                 if (!irq) {
   70                         if (port)
   71                                 bus_release_resource(dev, SYS_RES_IOPORT,
   72                                                      0, port);
   73                         return (ENOMEM);
   74                 }
   75         } else
   76                 irq = 0;
   77 
   78         if (isa_get_drq(dev) != -1) {
   79                 rid = 0;
   80                 drq = bus_alloc_resource(dev, SYS_RES_DRQ, &rid,
   81                                          0, ~0, 1, RF_ACTIVE);
   82                 if (!drq) {
   83                         if (port)
   84                                 bus_release_resource(dev, SYS_RES_IOPORT,
   85                                                      0, port);
   86                         if (irq)
   87                                 bus_release_resource(dev, SYS_RES_IRQ,
   88                                                      0, irq);
   89                         return (ENOMEM);
   90                 }
   91         } else
   92                 drq = 0;
   93 
   94         bt_init_softc(dev, port, irq, drq);
   95 
   96         return (0);
   97 }
   98 
   99 static void
  100 bt_isa_release_resources(device_t dev)
  101 {
  102         struct  bt_softc *bt = device_get_softc(dev);
  103 
  104         if (bt->port)
  105                 bus_release_resource(dev, SYS_RES_IOPORT, 0, bt->port);
  106         if (bt->irq)
  107                 bus_release_resource(dev, SYS_RES_IRQ, 0, bt->irq);
  108         if (bt->drq)
  109                 bus_release_resource(dev, SYS_RES_DRQ, 0, bt->drq);
  110         bt_free_softc(dev);
  111 }
  112 
  113 /*
  114  * Check if the device can be found at the port given
  115  * and if so, set it up ready for further work
  116  * as an argument, takes the isa_device structure from
  117  * autoconf.c
  118  */
  119 static int
  120 bt_isa_probe(device_t dev)
  121 {
  122         /*
  123          * find unit and check we have that many defined
  124          */
  125         int     port_index;
  126         int     max_port_index;
  127 
  128         /* No pnp support */
  129         if (isa_get_vendorid(dev))
  130                 return (ENXIO);
  131 
  132         port_index = 0;
  133         max_port_index = BT_NUM_ISAPORTS - 1;
  134         /*
  135          * Bound our board search if the user has
  136          * specified an exact port.
  137          */
  138         bt_find_probe_range(isa_get_port(dev), &port_index, &max_port_index);
  139 
  140         if (port_index < 0)
  141                 return (ENXIO);
  142 
  143         /* Attempt to find an adapter */
  144         for (;port_index <= max_port_index; port_index++) {
  145                 struct bt_probe_info info;
  146                 u_int ioport;
  147 
  148                 ioport = bt_iop_from_bio(port_index);
  149 
  150                 /*
  151                  * Ensure this port has not already been claimed already
  152                  * by a PCI, EISA or ISA adapter.
  153                  */
  154                 if (bt_check_probed_iop(ioport) != 0)
  155                         continue;
  156 
  157                 /* Initialise the softc for use during probing */
  158                 if (bt_isa_alloc_resources(dev, ioport,
  159                                            ioport + BT_NREGS -1) != 0)
  160                         continue;
  161 
  162                 /* We're going to attempt to probe it now, so mark it probed */
  163                 bt_mark_probed_bio(port_index);
  164 
  165                 if (bt_port_probe(dev, &info) != 0) {
  166                         if (bootverbose)
  167                                 printf("bt_isa_probe: Probe failed at 0x%x\n",
  168                                        ioport);
  169                         bt_isa_release_resources(dev);
  170                         continue;
  171                 }
  172 
  173                 bt_isa_release_resources(dev);
  174 
  175                 bus_set_resource(dev, SYS_RES_DRQ, 0, info.drq, 1);
  176                 bus_set_resource(dev, SYS_RES_IRQ, 0, info.irq, 1);
  177 
  178                 return (0);
  179         }
  180 
  181         return (ENXIO);
  182 }
  183 
  184 /*
  185  * Attach all the sub-devices we can find
  186  */
  187 static int
  188 bt_isa_attach(device_t dev)
  189 {
  190         struct  bt_softc *bt = device_get_softc(dev);
  191         bus_dma_filter_t *filter;
  192         void             *filter_arg;
  193         bus_addr_t       lowaddr;
  194         int              error, drq;
  195 
  196         /* Initialise softc */
  197         error = bt_isa_alloc_resources(dev, 0, ~0);
  198         if (error) {
  199                 device_printf(dev, "can't allocate resources in bt_isa_attach\n");
  200                 return error;
  201         }
  202 
  203         /* Program the DMA channel for external control */
  204         if ((drq = isa_get_drq(dev)) != -1)
  205                 isa_dmacascade(drq);
  206 
  207         /* Allocate our parent dmatag */
  208         filter = NULL;
  209         filter_arg = NULL;
  210         lowaddr = BUS_SPACE_MAXADDR_24BIT;
  211         if (bt->model[0] == '4') {
  212                 /*
  213                  * This is a VL adapter.  Typically, VL devices have access
  214                  * to the full 32bit address space.  On BT-445S adapters
  215                  * prior to revision E, there is a hardware bug that causes
  216                  * corruption of transfers to/from addresses in the range of
  217                  * the BIOS modulo 16MB.  The only properly functioning
  218                  * BT-445S Host Adapters have firmware version 3.37.
  219                  * If we encounter one of these adapters and the BIOS is
  220                  * installed, install a filter function for our bus_dma_map
  221                  * that will catch these accesses and bounce them to a safe
  222                  * region of memory.
  223                  */
  224                 if (bt->bios_addr != 0
  225                  && strcmp(bt->model, "445S") == 0
  226                  && strcmp(bt->firmware_ver, "3.37") < 0) {
  227                         filter = btvlbouncefilter;
  228                         filter_arg = bt;
  229                 } else {
  230                         lowaddr = BUS_SPACE_MAXADDR_32BIT;
  231                 }
  232         }
  233                         
  234         /* XXX Should be a child of the ISA or VL bus dma tag */
  235         if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/1, /*boundary*/0,
  236                                lowaddr, /*highaddr*/BUS_SPACE_MAXADDR,
  237                                filter, filter_arg,
  238                                /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
  239                                /*nsegments*/~0,
  240                                /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
  241                                /*flags*/0, &bt->parent_dmat) != 0) {
  242                 bt_isa_release_resources(dev);
  243                 return (ENOMEM);
  244         }                              
  245 
  246         error = bt_init(dev);
  247         if (error) {
  248                 bt_isa_release_resources(dev);
  249                 return (ENOMEM);
  250         }
  251 
  252         if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
  253                 /* DMA tag for our sense buffers */
  254                 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/1,
  255                                        /*boundary*/0,
  256                                        /*lowaddr*/BUS_SPACE_MAXADDR,
  257                                        /*highaddr*/BUS_SPACE_MAXADDR,
  258                                        /*filter*/NULL, /*filterarg*/NULL,
  259                                        bt->max_ccbs
  260                                            * sizeof(struct scsi_sense_data),
  261                                        /*nsegments*/1,
  262                                        /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
  263                                        /*flags*/0, &bt->sense_dmat) != 0) {
  264                         bt_isa_release_resources(dev);
  265                         return (ENOMEM);
  266                 }
  267 
  268                 bt->init_level++;
  269 
  270                 /* Allocation of sense buffers */
  271                 if (bus_dmamem_alloc(bt->sense_dmat,
  272                                      (void **)&bt->sense_buffers,
  273                                      BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
  274                         bt_isa_release_resources(dev);
  275                         return (ENOMEM);
  276                 }
  277 
  278                 bt->init_level++;
  279 
  280                 /* And permanently map them */
  281                 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap,
  282                                 bt->sense_buffers,
  283                                 bt->max_ccbs * sizeof(*bt->sense_buffers),
  284                                 btmapsensebuffers, bt, /*flags*/0);
  285 
  286                 bt->init_level++;
  287         }
  288 
  289         error = bt_attach(dev);
  290         if (error) {
  291                 bt_isa_release_resources(dev);
  292                 return (error);
  293         }
  294 
  295         return (0);
  296 }
  297 
  298 #define BIOS_MAP_SIZE (16 * 1024)
  299 
  300 static int
  301 btvlbouncefilter(void *arg, bus_addr_t addr)
  302 {
  303         struct bt_softc *bt;
  304 
  305         bt = (struct bt_softc *)arg;
  306 
  307         addr &= BUS_SPACE_MAXADDR_24BIT;
  308 
  309         if (addr == 0
  310          || (addr >= bt->bios_addr
  311           && addr < (bt->bios_addr + BIOS_MAP_SIZE)))
  312                 return (1);
  313         return (0);
  314 }
  315 
  316 static void
  317 btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
  318 {
  319         struct bt_softc* bt;
  320 
  321         bt = (struct bt_softc*)arg;
  322         bt->sense_buffers_physbase = segs->ds_addr;
  323 }
  324 
  325 static device_method_t bt_isa_methods[] = {
  326         /* Device interface */
  327         DEVMETHOD(device_probe,         bt_isa_probe),
  328         DEVMETHOD(device_attach,        bt_isa_attach),
  329 
  330         { 0, 0 }
  331 };
  332 
  333 static driver_t bt_isa_driver = {
  334         "bt",
  335         bt_isa_methods,
  336         sizeof(struct bt_softc),
  337 };
  338 
  339 static devclass_t bt_devclass;
  340 
  341 DRIVER_MODULE(bt, isa, bt_isa_driver, bt_devclass, 0, 0);

Cache object: b47a800b22dc42d3dd4515b3eaf36d7b


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