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/advansys/adv_eisa.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  * Device probe and attach routines for the following
    3  * Advanced Systems Inc. SCSI controllers:
    4  *
    5  *   Single Channel Products:
    6  *      ABP742 - Bus-Master EISA (240 CDB)
    7  *
    8  *   Dual Channel Products:  
    9  *      ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel)
   10  *
   11  * Copyright (c) 1997 Justin Gibbs.
   12  * All rights reserved.
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions, and the following disclaimer,
   19  *    without modification, immediately at the beginning of the file.
   20  * 2. The name of the author may not be used to endorse or promote products
   21  *    derived from this software without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD: releng/10.0/sys/dev/advansys/adv_eisa.c 241492 2012-10-12 21:31:44Z jhb $");
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/kernel.h>
   42 #include <sys/module.h>
   43 #include <sys/lock.h>
   44 #include <sys/mutex.h>
   45 #include <sys/bus.h>
   46 
   47 #include <machine/bus.h>
   48 #include <machine/resource.h>
   49 #include <sys/rman.h>
   50 
   51 #include <dev/eisa/eisaconf.h>
   52 
   53 #include <dev/advansys/advansys.h>
   54 
   55 #define EISA_DEVICE_ID_ADVANSYS_740     0x04507400
   56 #define EISA_DEVICE_ID_ADVANSYS_750     0x04507500
   57 
   58 #define ADV_EISA_SLOT_OFFSET            0xc00
   59 #define ADV_EISA_OFFSET_CHAN1           0x30
   60 #define ADV_EISA_OFFSET_CHAN2           0x50
   61 #define ADV_EISA_IOSIZE                 0x100
   62 
   63 #define ADV_EISA_ROM_BIOS_ADDR_REG      0x86
   64 #define ADV_EISA_IRQ_BURST_LEN_REG      0x87
   65 #define         ADV_EISA_IRQ_MASK       0x07
   66 #define         ADV_EISA_IRQ_10         0x00
   67 #define         ADV_EISA_IRQ_11         0x01
   68 #define         ADV_EISA_IRQ_12         0x02
   69 #define         ADV_EISA_IRQ_14         0x04
   70 #define         ADV_EISA_IRQ_15         0x05
   71 
   72 #define ADV_EISA_MAX_DMA_ADDR   (0x07FFFFFFL)
   73 #define ADV_EISA_MAX_DMA_COUNT  (0x07FFFFFFL)
   74 
   75 /* 
   76  * The overrun buffer shared amongst all EISA adapters.
   77  */
   78 static  void*           overrun_buf;
   79 static  bus_dma_tag_t   overrun_dmat;
   80 static  bus_dmamap_t    overrun_dmamap;
   81 static  bus_addr_t      overrun_physbase;
   82 
   83 static const char*
   84 adv_eisa_match(eisa_id_t type)
   85 {
   86         switch (type & ~0xF) {
   87         case EISA_DEVICE_ID_ADVANSYS_740:
   88                 return ("AdvanSys ABP-740/742 SCSI adapter");
   89                 break;
   90         case EISA_DEVICE_ID_ADVANSYS_750:
   91                 return ("AdvanSys ABP-750/752 SCSI adapter");
   92                 break;
   93         default:
   94                 break;
   95         }
   96         return (NULL);
   97 }
   98 
   99 static int
  100 adv_eisa_probe(device_t dev)
  101 {
  102         const char *desc;
  103         u_int32_t iobase;
  104         u_int8_t irq;
  105 
  106         desc = adv_eisa_match(eisa_get_id(dev));
  107         if (!desc)
  108                 return (ENXIO);
  109         device_set_desc(dev, desc);
  110 
  111         iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + ADV_EISA_SLOT_OFFSET;
  112 
  113         eisa_add_iospace(dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE);
  114         irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG);
  115         irq &= ADV_EISA_IRQ_MASK;
  116         switch (irq) {
  117         case 0:
  118         case 1:
  119         case 2:
  120         case 4:
  121         case 5:
  122             break;
  123         default:
  124             printf("adv at slot %d: illegal "
  125                    "irq setting %d\n", eisa_get_slot(dev),
  126                    irq);
  127             return ENXIO;
  128         }
  129         eisa_add_intr(dev, irq + 10, EISA_TRIGGER_LEVEL);
  130 
  131         return 0;
  132 }
  133 
  134 /*
  135  * The adv_b stuff to handle twin-channel cards will not work in its current
  136  * incarnation.  It tries to reuse the same softc since adv_alloc() doesn't
  137  * actually allocate a softc.  It also tries to reuse the same unit number
  138  * for both sims.  This can be re-enabled if someone fixes it properly.
  139  */
  140 static int
  141 adv_eisa_attach(device_t dev)
  142 {
  143         struct adv_softc *adv;
  144 #if 0
  145         struct adv_softc *adv_b;
  146 #endif
  147         struct resource *io;
  148         struct resource *irq;
  149         int rid, error;
  150         void *ih;
  151 
  152 #if 0
  153         adv_b = NULL;
  154 #endif
  155 
  156         rid = 0;
  157         io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
  158         if (!io) {
  159                 device_printf(dev, "No I/O space?!\n");
  160                 return ENOMEM;
  161         }
  162 
  163         rid = 0;
  164         irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  165                                      RF_SHAREABLE | RF_ACTIVE);
  166         if (!irq) {
  167                 device_printf(dev, "No irq?!\n");
  168                 bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
  169                 return ENOMEM;
  170 
  171         }
  172 
  173         switch (eisa_get_id(dev) & ~0xF) {
  174         case EISA_DEVICE_ID_ADVANSYS_750:
  175 #if 0
  176                 adv_b = adv_alloc(dev, io, ADV_EISA_OFFSET_CHAN2);
  177                 if (adv_b == NULL)
  178                         goto bad;
  179                 
  180                 /*
  181                  * Allocate a parent dmatag for all tags created
  182                  * by the MI portions of the advansys driver
  183                  */
  184                 error = bus_dma_tag_create(
  185                                 /* parent       */ bus_get_dma_tag(dev),
  186                                 /* alignment    */ 1,
  187                                 /* boundary     */ 0,
  188                                 /* lowaddr      */ ADV_EISA_MAX_DMA_ADDR,
  189                                 /* highaddr     */ BUS_SPACE_MAXADDR,
  190                                 /* filter       */ NULL,
  191                                 /* filterarg    */ NULL,
  192                                 /* maxsize      */ BUS_SPACE_MAXSIZE_32BIT,
  193                                 /* nsegments    */ ~0,
  194                                 /* maxsegsz     */ ADV_EISA_MAX_DMA_COUNT,
  195                                 /* flags        */ 0,
  196                                 /* lockfunc     */ NULL,
  197                                 /* lockarg      */ NULL,
  198                                 &adv_b->parent_dmat);
  199  
  200                 if (error != 0) {
  201                         device_printf(dev, "Could not allocate DMA tag - error %d\n",
  202                                error);
  203                         adv_free(adv_b);
  204                         goto bad;
  205                 }
  206 
  207                 adv_b->init_level++;
  208 #endif
  209 
  210                 /* FALLTHROUGH */
  211         case EISA_DEVICE_ID_ADVANSYS_740:
  212                 adv = adv_alloc(dev, io, ADV_EISA_OFFSET_CHAN1);
  213                 if (adv == NULL) {
  214 #if 0
  215                         if (adv_b != NULL)
  216                                 adv_free(adv_b);
  217 #endif
  218                         goto bad;
  219                 }
  220 
  221                 /*
  222                  * Allocate a parent dmatag for all tags created
  223                  * by the MI portions of the advansys driver
  224                  */
  225                 error = bus_dma_tag_create(
  226                                 /* parent       */ bus_get_dma_tag(dev),
  227                                 /* alignment    */ 1,
  228                                 /* boundary     */ 0,
  229                                 /* lowaddr      */ ADV_EISA_MAX_DMA_ADDR,
  230                                 /* highaddr     */ BUS_SPACE_MAXADDR,
  231                                 /* filter       */ NULL,
  232                                 /* filterarg    */ NULL,
  233                                 /* maxsize      */ BUS_SPACE_MAXSIZE_32BIT,
  234                                 /* nsegments    */ ~0,
  235                                 /* maxsegsz     */ ADV_EISA_MAX_DMA_COUNT,
  236                                 /* flags        */ 0,
  237                                 /* lockfunc     */ NULL,
  238                                 /* lockarg      */ NULL,
  239                                 &adv->parent_dmat);
  240  
  241                 if (error != 0) {
  242                         device_printf(dev, "Could not allocate DMA tag - error %d\n",
  243                                error);
  244                         adv_free(adv);
  245                         goto bad;
  246                 }
  247 
  248                 adv->init_level++;
  249                 break;
  250         default: 
  251                 printf("adveisaattach: Unknown device type!\n");
  252                 goto bad;
  253                 break;
  254         }
  255 
  256         if (overrun_buf == NULL) {
  257                 /* Need to allocate our overrun buffer */
  258                 if (bus_dma_tag_create(
  259                                 /* parent       */ bus_get_dma_tag(dev),
  260                                 /* alignment    */ 8,
  261                                 /* boundary     */ 0,
  262                                 /* lowaddr      */ ADV_EISA_MAX_DMA_ADDR,
  263                                 /* highaddr     */ BUS_SPACE_MAXADDR,
  264                                 /* filter       */ NULL,
  265                                 /* filterarg    */ NULL,
  266                                 /* maxsize      */ ADV_OVERRUN_BSIZE,
  267                                 /* nsegments    */ 1,
  268                                 /* maxsegsz     */ BUS_SPACE_MAXSIZE_32BIT,
  269                                 /* flags        */ 0,
  270                                 /* lockfunc     */ NULL,
  271                                 /* lockarg      */ NULL,
  272                                 &overrun_dmat) != 0) {
  273                         adv_free(adv);
  274                         goto bad;
  275                 }
  276                 if (bus_dmamem_alloc(overrun_dmat,
  277                                      &overrun_buf,
  278                                      BUS_DMA_NOWAIT,
  279                                      &overrun_dmamap) != 0) {
  280                         bus_dma_tag_destroy(overrun_dmat);
  281                         adv_free(adv);
  282                         goto bad;
  283                 }
  284                 /* And permanently map it in */  
  285                 bus_dmamap_load(overrun_dmat, overrun_dmamap,
  286                                 overrun_buf, ADV_OVERRUN_BSIZE,
  287                                 adv_map, &overrun_physbase,
  288                                 /*flags*/0);
  289         }
  290         
  291         /*
  292          * Now that we know we own the resources we need, do the 
  293          * card initialization.
  294          */
  295 
  296         /*
  297          * Stop the chip.
  298          */
  299         ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
  300         ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
  301 
  302         adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
  303                           + ADV_CHIP_MIN_VER_EISA - 1;
  304 
  305         if (adv_init(adv) != 0) {
  306                 adv_free(adv);
  307 #if 0
  308                 if (adv_b != NULL)
  309                         adv_free(adv_b);
  310 #endif
  311                 goto bad;
  312         }
  313 
  314         adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
  315         adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
  316 
  317 #if 0
  318         if (adv_b != NULL) {
  319                 /*
  320                  * Stop the chip.
  321                  */
  322                 ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT);
  323                 ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0);
  324 
  325                 adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
  326                                     + ADV_CHIP_MIN_VER_EISA - 1;
  327 
  328                 if (adv_init(adv_b) != 0) {
  329                         adv_free(adv_b);
  330                 } else {
  331                         adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
  332                         adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
  333                 }
  334         }
  335 #endif
  336 
  337         /*
  338          * Enable our interrupt handler.
  339          */
  340         if (bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL,
  341             adv_intr, adv, &ih) != 0) {
  342                 adv_free(adv);
  343                 goto bad;
  344         }
  345 
  346         /* Attach sub-devices */
  347         if (adv_attach(adv) != 0) {
  348                 adv_free(adv);
  349                 goto bad;
  350         }
  351 #if 0
  352         if (adv_b != NULL)
  353                 adv_attach(adv_b);
  354 #endif
  355 
  356         return 0;
  357 
  358  bad:
  359         bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
  360         bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
  361         return ENXIO;
  362 }
  363 
  364 static device_method_t adv_eisa_methods[] = {
  365         /* Device interface */
  366         DEVMETHOD(device_probe,         adv_eisa_probe),
  367         DEVMETHOD(device_attach,        adv_eisa_attach),
  368         { 0, 0 }
  369 };
  370 
  371 static driver_t adv_eisa_driver = {
  372         "adv", adv_eisa_methods, sizeof(struct adv_softc)
  373 };
  374 
  375 static devclass_t adv_eisa_devclass;
  376 DRIVER_MODULE(adv, eisa, adv_eisa_driver, adv_eisa_devclass, 0, 0);
  377 MODULE_DEPEND(adv, eisa, 1, 1, 1);

Cache object: 2f044fc5df53a114a536d78e2e8df3db


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