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

Cache object: 72b81af930f20ac11a2d48d73f19cbc8


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