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$");
   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 static int
  135 adv_eisa_attach(device_t dev)
  136 {
  137         struct adv_softc *adv;
  138         struct adv_softc *adv_b;
  139         struct resource *io;
  140         struct resource *irq;
  141         int rid, error;
  142         void *ih;
  143 
  144         adv_b = NULL;
  145 
  146         rid = 0;
  147         io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
  148         if (!io) {
  149                 device_printf(dev, "No I/O space?!\n");
  150                 return ENOMEM;
  151         }
  152 
  153         rid = 0;
  154         irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  155                                      RF_SHAREABLE | RF_ACTIVE);
  156         if (!irq) {
  157                 device_printf(dev, "No irq?!\n");
  158                 bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
  159                 return ENOMEM;
  160 
  161         }
  162 
  163         switch (eisa_get_id(dev) & ~0xF) {
  164         case EISA_DEVICE_ID_ADVANSYS_750:
  165                 adv_b = adv_alloc(dev, rman_get_bustag(io),
  166                                   rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN2);
  167                 if (adv_b == NULL)
  168                         goto bad;
  169                 
  170                 /*
  171                  * Allocate a parent dmatag for all tags created
  172                  * by the MI portions of the advansys driver
  173                  */
  174                 /* XXX Should be a child of the PCI bus dma tag */
  175                 error = bus_dma_tag_create(
  176                                 /* parent       */ NULL,
  177                                 /* alignment    */ 1,
  178                                 /* boundary     */ 0,
  179                                 /* lowaddr      */ ADV_EISA_MAX_DMA_ADDR,
  180                                 /* highaddr     */ BUS_SPACE_MAXADDR,
  181                                 /* filter       */ NULL,
  182                                 /* filterarg    */ NULL,
  183                                 /* maxsize      */ BUS_SPACE_MAXSIZE_32BIT,
  184                                 /* nsegments    */ ~0,
  185                                 /* maxsegsz     */ ADV_EISA_MAX_DMA_COUNT,
  186                                 /* flags        */ 0,
  187                                 /* lockfunc     */ busdma_lock_mutex,
  188                                 /* lockarg      */ &Giant,
  189                                 &adv_b->parent_dmat);
  190  
  191                 if (error != 0) {
  192                         printf("%s: Could not allocate DMA tag - error %d\n",
  193                                adv_name(adv_b), error);
  194                         adv_free(adv_b);
  195                         goto bad;
  196                 }
  197 
  198                 adv_b->init_level++;
  199 
  200                 /* FALLTHROUGH */
  201         case EISA_DEVICE_ID_ADVANSYS_740:
  202                 adv = adv_alloc(dev, rman_get_bustag(io),
  203                                 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1);
  204                 if (adv == NULL) {
  205                         if (adv_b != NULL)
  206                                 adv_free(adv_b);
  207                         goto bad;
  208                 }
  209 
  210                 /*
  211                  * Allocate a parent dmatag for all tags created
  212                  * by the MI portions of the advansys driver
  213                  */
  214                 /* XXX Should be a child of the PCI bus dma tag */
  215                 error = bus_dma_tag_create(
  216                                 /* parent       */ NULL,
  217                                 /* alignment    */ 1,
  218                                 /* boundary     */ 0,
  219                                 /* lowaddr      */ ADV_EISA_MAX_DMA_ADDR,
  220                                 /* highaddr     */ BUS_SPACE_MAXADDR,
  221                                 /* filter       */ NULL,
  222                                 /* filterarg    */ NULL,
  223                                 /* maxsize      */ BUS_SPACE_MAXSIZE_32BIT,
  224                                 /* nsegments    */ ~0,
  225                                 /* maxsegsz     */ ADV_EISA_MAX_DMA_COUNT,
  226                                 /* flags        */ 0,
  227                                 /* lockfunc     */ busdma_lock_mutex,
  228                                 /* lockarg      */ &Giant,
  229                                 &adv->parent_dmat);
  230  
  231                 if (error != 0) {
  232                         printf("%s: Could not allocate DMA tag - error %d\n",
  233                                adv_name(adv), error);
  234                         adv_free(adv);
  235                         goto bad;
  236                 }
  237 
  238                 adv->init_level++;
  239                 break;
  240         default: 
  241                 printf("adveisaattach: Unknown device type!\n");
  242                 goto bad;
  243                 break;
  244         }
  245 
  246         if (overrun_buf == NULL) {
  247                 /* Need to allocate our overrun buffer */
  248                 if (bus_dma_tag_create(
  249                                 /* parent       */ adv->parent_dmat,
  250                                 /* alignment    */ 8,
  251                                 /* boundary     */ 0,
  252                                 /* lowaddr      */ ADV_EISA_MAX_DMA_ADDR,
  253                                 /* highaddr     */ BUS_SPACE_MAXADDR,
  254                                 /* filter       */ NULL,
  255                                 /* filterarg    */ NULL,
  256                                 /* maxsize      */ ADV_OVERRUN_BSIZE,
  257                                 /* nsegments    */ 1,
  258                                 /* maxsegsz     */ BUS_SPACE_MAXSIZE_32BIT,
  259                                 /* flags        */ 0,
  260                                 /* lockfunc     */ busdma_lock_mutex,
  261                                 /* lockarg      */ &Giant,
  262                                 &overrun_dmat) != 0) {
  263                         adv_free(adv);
  264                         goto bad;
  265                 }
  266                 if (bus_dmamem_alloc(overrun_dmat,
  267                                      &overrun_buf,
  268                                      BUS_DMA_NOWAIT,
  269                                      &overrun_dmamap) != 0) {
  270                         bus_dma_tag_destroy(overrun_dmat);
  271                         adv_free(adv);
  272                         goto bad;
  273                 }
  274                 /* And permanently map it in */  
  275                 bus_dmamap_load(overrun_dmat, overrun_dmamap,
  276                                 overrun_buf, ADV_OVERRUN_BSIZE,
  277                                 adv_map, &overrun_physbase,
  278                                 /*flags*/0);
  279         }
  280         
  281         /*
  282          * Now that we know we own the resources we need, do the 
  283          * card initialization.
  284          */
  285 
  286         /*
  287          * Stop the chip.
  288          */
  289         ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
  290         ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
  291 
  292         adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
  293                           + ADV_CHIP_MIN_VER_EISA - 1;
  294 
  295         if (adv_init(adv) != 0) {
  296                 adv_free(adv);
  297                 if (adv_b != NULL)
  298                         adv_free(adv_b);
  299                 return(-1);
  300         }
  301 
  302         adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
  303         adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
  304 
  305         if (adv_b != NULL) {
  306                 /*
  307                  * Stop the chip.
  308                  */
  309                 ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT);
  310                 ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0);
  311 
  312                 adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
  313                                     + ADV_CHIP_MIN_VER_EISA - 1;
  314 
  315                 if (adv_init(adv_b) != 0) {
  316                         adv_free(adv_b);
  317                 } else {
  318                         adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
  319                         adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
  320                 }
  321         }
  322 
  323         /*
  324          * Enable our interrupt handler.
  325          */
  326         bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, NULL, adv_intr, 
  327             adv, &ih);
  328 
  329         /* Attach sub-devices - always succeeds */
  330         adv_attach(adv);
  331         if (adv_b != NULL)
  332                 adv_attach(adv_b);
  333 
  334         return 0;
  335 
  336  bad:
  337         bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
  338         bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
  339         return -1;
  340 }
  341 
  342 static device_method_t adv_eisa_methods[] = {
  343         /* Device interface */
  344         DEVMETHOD(device_probe,         adv_eisa_probe),
  345         DEVMETHOD(device_attach,        adv_eisa_attach),
  346         { 0, 0 }
  347 };
  348 
  349 static driver_t adv_eisa_driver = {
  350         "adv", adv_eisa_methods, sizeof(struct adv_softc)
  351 };
  352 
  353 static devclass_t adv_eisa_devclass;
  354 DRIVER_MODULE(adv, eisa, adv_eisa_driver, adv_eisa_devclass, 0, 0);
  355 MODULE_DEPEND(adv, eisa, 1, 1, 1);

Cache object: 667ae0f2e81cb5812ab4b12edb7b2603


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