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

Cache object: fe0c1b41295374fb3fc80db150130c06


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