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: src/sys/dev/advansys/adv_eisa.c,v 1.16.2.1 2005/01/30 00:59:23 imp Exp $");
   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_pio.h>
   48 #include <machine/bus.h>
   49 #include <machine/resource.h>
   50 #include <sys/rman.h>
   51 
   52 #include <dev/eisa/eisaconf.h>
   53 
   54 #include <dev/advansys/advansys.h>
   55 
   56 #define EISA_DEVICE_ID_ADVANSYS_740     0x04507400
   57 #define EISA_DEVICE_ID_ADVANSYS_750     0x04507500
   58 
   59 #define ADV_EISA_SLOT_OFFSET            0xc00
   60 #define ADV_EISA_OFFSET_CHAN1           0x30
   61 #define ADV_EISA_OFFSET_CHAN2           0x50
   62 #define ADV_EISA_IOSIZE                 0x100
   63 
   64 #define ADV_EISA_ROM_BIOS_ADDR_REG      0x86
   65 #define ADV_EISA_IRQ_BURST_LEN_REG      0x87
   66 #define         ADV_EISA_IRQ_MASK       0x07
   67 #define         ADV_EISA_IRQ_10         0x00
   68 #define         ADV_EISA_IRQ_11         0x01
   69 #define         ADV_EISA_IRQ_12         0x02
   70 #define         ADV_EISA_IRQ_14         0x04
   71 #define         ADV_EISA_IRQ_15         0x05
   72 
   73 #define ADV_EISA_MAX_DMA_ADDR   (0x07FFFFFFL)
   74 #define ADV_EISA_MAX_DMA_COUNT  (0x07FFFFFFL)
   75 
   76 /* 
   77  * The overrun buffer shared amongst all EISA adapters.
   78  */
   79 static  u_int8_t*       overrun_buf;
   80 static  bus_dma_tag_t   overrun_dmat;
   81 static  bus_dmamap_t    overrun_dmamap;
   82 static  bus_addr_t      overrun_physbase;
   83 
   84 static const char*
   85 adv_eisa_match(eisa_id_t type)
   86 {
   87         switch (type & ~0xF) {
   88         case EISA_DEVICE_ID_ADVANSYS_740:
   89                 return ("AdvanSys ABP-740/742 SCSI adapter");
   90                 break;
   91         case EISA_DEVICE_ID_ADVANSYS_750:
   92                 return ("AdvanSys ABP-750/752 SCSI adapter");
   93                 break;
   94         default:
   95                 break;
   96         }
   97         return (NULL);
   98 }
   99 
  100 static int
  101 adv_eisa_probe(device_t dev)
  102 {
  103         const char *desc;
  104         u_int32_t iobase;
  105         u_int8_t irq;
  106 
  107         desc = adv_eisa_match(eisa_get_id(dev));
  108         if (!desc)
  109                 return (ENXIO);
  110         device_set_desc(dev, desc);
  111 
  112         iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + ADV_EISA_SLOT_OFFSET;
  113 
  114         eisa_add_iospace(dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE);
  115         irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG);
  116         irq &= ADV_EISA_IRQ_MASK;
  117         switch (irq) {
  118         case 0:
  119         case 1:
  120         case 2:
  121         case 4:
  122         case 5:
  123             break;
  124         default:
  125             printf("adv at slot %d: illegal "
  126                    "irq setting %d\n", eisa_get_slot(dev),
  127                    irq);
  128             return ENXIO;
  129         }
  130         eisa_add_intr(dev, irq + 10, EISA_TRIGGER_LEVEL);
  131 
  132         return 0;
  133 }
  134 
  135 static int
  136 adv_eisa_attach(device_t dev)
  137 {
  138         struct adv_softc *adv;
  139         struct adv_softc *adv_b;
  140         struct resource *io;
  141         struct resource *irq;
  142         int rid, error;
  143         void *ih;
  144 
  145         adv_b = NULL;
  146 
  147         rid = 0;
  148         io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
  149         if (!io) {
  150                 device_printf(dev, "No I/O space?!\n");
  151                 return ENOMEM;
  152         }
  153 
  154         rid = 0;
  155         irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  156                                      RF_SHAREABLE | RF_ACTIVE);
  157         if (!irq) {
  158                 device_printf(dev, "No irq?!\n");
  159                 bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
  160                 return ENOMEM;
  161 
  162         }
  163 
  164         switch (eisa_get_id(dev) & ~0xF) {
  165         case EISA_DEVICE_ID_ADVANSYS_750:
  166                 adv_b = adv_alloc(dev, rman_get_bustag(io),
  167                                   rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN2);
  168                 if (adv_b == NULL)
  169                         goto bad;
  170                 
  171                 /*
  172                  * Allocate a parent dmatag for all tags created
  173                  * by the MI portions of the advansys driver
  174                  */
  175                 /* XXX Should be a child of the PCI bus dma tag */
  176                 error = bus_dma_tag_create(
  177                                 /* parent       */ NULL,
  178                                 /* alignment    */ 1,
  179                                 /* boundary     */ 0,
  180                                 /* lowaddr      */ ADV_EISA_MAX_DMA_ADDR,
  181                                 /* highaddr     */ BUS_SPACE_MAXADDR,
  182                                 /* filter       */ NULL,
  183                                 /* filterarg    */ NULL,
  184                                 /* maxsize      */ BUS_SPACE_MAXSIZE_32BIT,
  185                                 /* nsegments    */ ~0,
  186                                 /* maxsegsz     */ ADV_EISA_MAX_DMA_COUNT,
  187                                 /* flags        */ 0,
  188                                 /* lockfunc     */ busdma_lock_mutex,
  189                                 /* lockarg      */ &Giant,
  190                                 &adv_b->parent_dmat);
  191  
  192                 if (error != 0) {
  193                         printf("%s: Could not allocate DMA tag - error %d\n",
  194                                adv_name(adv_b), error);
  195                         adv_free(adv_b);
  196                         goto bad;
  197                 }
  198 
  199                 adv_b->init_level++;
  200 
  201                 /* FALLTHROUGH */
  202         case EISA_DEVICE_ID_ADVANSYS_740:
  203                 adv = adv_alloc(dev, rman_get_bustag(io),
  204                                 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1);
  205                 if (adv == NULL) {
  206                         if (adv_b != NULL)
  207                                 adv_free(adv_b);
  208                         goto bad;
  209                 }
  210 
  211                 /*
  212                  * Allocate a parent dmatag for all tags created
  213                  * by the MI portions of the advansys driver
  214                  */
  215                 /* XXX Should be a child of the PCI bus dma tag */
  216                 error = bus_dma_tag_create(
  217                                 /* parent       */ NULL,
  218                                 /* alignment    */ 1,
  219                                 /* boundary     */ 0,
  220                                 /* lowaddr      */ ADV_EISA_MAX_DMA_ADDR,
  221                                 /* highaddr     */ BUS_SPACE_MAXADDR,
  222                                 /* filter       */ NULL,
  223                                 /* filterarg    */ NULL,
  224                                 /* maxsize      */ BUS_SPACE_MAXSIZE_32BIT,
  225                                 /* nsegments    */ ~0,
  226                                 /* maxsegsz     */ ADV_EISA_MAX_DMA_COUNT,
  227                                 /* flags        */ 0,
  228                                 /* lockfunc     */ busdma_lock_mutex,
  229                                 /* lockarg      */ &Giant,
  230                                 &adv->parent_dmat);
  231  
  232                 if (error != 0) {
  233                         printf("%s: Could not allocate DMA tag - error %d\n",
  234                                adv_name(adv), error);
  235                         adv_free(adv);
  236                         goto bad;
  237                 }
  238 
  239                 adv->init_level++;
  240                 break;
  241         default: 
  242                 printf("adveisaattach: Unknown device type!\n");
  243                 goto bad;
  244                 break;
  245         }
  246 
  247         if (overrun_buf == NULL) {
  248                 /* Need to allocate our overrun buffer */
  249                 if (bus_dma_tag_create(
  250                                 /* parent       */ adv->parent_dmat,
  251                                 /* alignment    */ 8,
  252                                 /* boundary     */ 0,
  253                                 /* lowaddr      */ ADV_EISA_MAX_DMA_ADDR,
  254                                 /* highaddr     */ BUS_SPACE_MAXADDR,
  255                                 /* filter       */ NULL,
  256                                 /* filterarg    */ NULL,
  257                                 /* maxsize      */ ADV_OVERRUN_BSIZE,
  258                                 /* nsegments    */ 1,
  259                                 /* maxsegsz     */ BUS_SPACE_MAXSIZE_32BIT,
  260                                 /* flags        */ 0,
  261                                 /* lockfunc     */ busdma_lock_mutex,
  262                                 /* lockarg      */ &Giant,
  263                                 &overrun_dmat) != 0) {
  264                         adv_free(adv);
  265                         goto bad;
  266                 }
  267                 if (bus_dmamem_alloc(overrun_dmat,
  268                                      (void **)&overrun_buf,
  269                                      BUS_DMA_NOWAIT,
  270                                      &overrun_dmamap) != 0) {
  271                         bus_dma_tag_destroy(overrun_dmat);
  272                         adv_free(adv);
  273                         goto bad;
  274                 }
  275                 /* And permanently map it in */  
  276                 bus_dmamap_load(overrun_dmat, overrun_dmamap,
  277                                 overrun_buf, ADV_OVERRUN_BSIZE,
  278                                 adv_map, &overrun_physbase,
  279                                 /*flags*/0);
  280         }
  281         
  282         /*
  283          * Now that we know we own the resources we need, do the 
  284          * card initialization.
  285          */
  286 
  287         /*
  288          * Stop the chip.
  289          */
  290         ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
  291         ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
  292 
  293         adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
  294                           + ADV_CHIP_MIN_VER_EISA - 1;
  295 
  296         if (adv_init(adv) != 0) {
  297                 adv_free(adv);
  298                 if (adv_b != NULL)
  299                         adv_free(adv_b);
  300                 return(-1);
  301         }
  302 
  303         adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
  304         adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
  305 
  306         if (adv_b != NULL) {
  307                 /*
  308                  * Stop the chip.
  309                  */
  310                 ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT);
  311                 ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0);
  312 
  313                 adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
  314                                     + ADV_CHIP_MIN_VER_EISA - 1;
  315 
  316                 if (adv_init(adv_b) != 0) {
  317                         adv_free(adv_b);
  318                 } else {
  319                         adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
  320                         adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
  321                 }
  322         }
  323 
  324         /*
  325          * Enable our interrupt handler.
  326          */
  327         bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, adv_intr, 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);

Cache object: 10b01233dc6d06eb15c999d4ed0081e5


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