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.0/sys/dev/advansys/adv_eisa.c 104707 2002-10-09 08:50:26Z peter $
   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(/*parent*/NULL, /*alignment*/1,
  175                                            /*boundary*/0,
  176                                            /*lowaddr*/ADV_EISA_MAX_DMA_ADDR,
  177                                            /*highaddr*/BUS_SPACE_MAXADDR,
  178                                            /*filter*/NULL, /*filterarg*/NULL,
  179                                            /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
  180                                            /*nsegments*/~0,
  181                                            /*maxsegsz*/ADV_EISA_MAX_DMA_COUNT,
  182                                            /*flags*/0,
  183                                            &adv_b->parent_dmat);
  184  
  185                 if (error != 0) {
  186                         printf("%s: Could not allocate DMA tag - error %d\n",
  187                                adv_name(adv_b), error);
  188                         adv_free(adv_b);
  189                         goto bad;
  190                 }
  191 
  192                 adv_b->init_level++;
  193 
  194                 /* FALLTHROUGH */
  195         case EISA_DEVICE_ID_ADVANSYS_740:
  196                 adv = adv_alloc(dev, rman_get_bustag(io),
  197                                 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1);
  198                 if (adv == NULL) {
  199                         if (adv_b != NULL)
  200                                 adv_free(adv_b);
  201                         goto bad;
  202                 }
  203 
  204                 /*
  205                  * Allocate a parent dmatag for all tags created
  206                  * by the MI portions of the advansys driver
  207                  */
  208                 /* XXX Should be a child of the PCI bus dma tag */
  209                 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1,
  210                                            /*boundary*/0,
  211                                            /*lowaddr*/ADV_EISA_MAX_DMA_ADDR,
  212                                            /*highaddr*/BUS_SPACE_MAXADDR,
  213                                            /*filter*/NULL, /*filterarg*/NULL,
  214                                            /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
  215                                            /*nsegments*/~0,
  216                                            /*maxsegsz*/ADV_EISA_MAX_DMA_COUNT,
  217                                            /*flags*/0,
  218                                            &adv->parent_dmat);
  219  
  220                 if (error != 0) {
  221                         printf("%s: Could not allocate DMA tag - error %d\n",
  222                                adv_name(adv), error);
  223                         adv_free(adv);
  224                         goto bad;
  225                 }
  226 
  227                 adv->init_level++;
  228                 break;
  229         default: 
  230                 printf("adveisaattach: Unknown device type!\n");
  231                 goto bad;
  232                 break;
  233         }
  234 
  235         if (overrun_buf == NULL) {
  236                 /* Need to allocate our overrun buffer */
  237                 if (bus_dma_tag_create(adv->parent_dmat,
  238                                        /*alignment*/8,
  239                                        /*boundary*/0,
  240                                        ADV_EISA_MAX_DMA_ADDR,
  241                                        BUS_SPACE_MAXADDR,
  242                                        /*filter*/NULL,
  243                                        /*filterarg*/NULL,
  244                                        ADV_OVERRUN_BSIZE,
  245                                        /*nsegments*/1,
  246                                        BUS_SPACE_MAXSIZE_32BIT,
  247                                        /*flags*/0,
  248                                        &overrun_dmat) != 0) {
  249                         adv_free(adv);
  250                         goto bad;
  251                 }
  252                 if (bus_dmamem_alloc(overrun_dmat,
  253                                      (void **)&overrun_buf,
  254                                      BUS_DMA_NOWAIT,
  255                                      &overrun_dmamap) != 0) {
  256                         bus_dma_tag_destroy(overrun_dmat);
  257                         adv_free(adv);
  258                         goto bad;
  259                 }
  260                 /* And permanently map it in */  
  261                 bus_dmamap_load(overrun_dmat, overrun_dmamap,
  262                                 overrun_buf, ADV_OVERRUN_BSIZE,
  263                                 adv_map, &overrun_physbase,
  264                                 /*flags*/0);
  265         }
  266         
  267         /*
  268          * Now that we know we own the resources we need, do the 
  269          * card initialization.
  270          */
  271 
  272         /*
  273          * Stop the chip.
  274          */
  275         ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
  276         ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
  277 
  278         adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
  279                           + ADV_CHIP_MIN_VER_EISA - 1;
  280 
  281         if (adv_init(adv) != 0) {
  282                 adv_free(adv);
  283                 if (adv_b != NULL)
  284                         adv_free(adv_b);
  285                 return(-1);
  286         }
  287 
  288         adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
  289         adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
  290 
  291         if (adv_b != NULL) {
  292                 /*
  293                  * Stop the chip.
  294                  */
  295                 ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT);
  296                 ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0);
  297 
  298                 adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
  299                                     + ADV_CHIP_MIN_VER_EISA - 1;
  300 
  301                 if (adv_init(adv_b) != 0) {
  302                         adv_free(adv_b);
  303                 } else {
  304                         adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
  305                         adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
  306                 }
  307         }
  308 
  309         /*
  310          * Enable our interrupt handler.
  311          */
  312         bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, adv_intr, adv, &ih);
  313 
  314         /* Attach sub-devices - always succeeds */
  315         adv_attach(adv);
  316         if (adv_b != NULL)
  317                 adv_attach(adv_b);
  318 
  319         return 0;
  320 
  321  bad:
  322         bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
  323         bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
  324         return -1;
  325 }
  326 
  327 static device_method_t adv_eisa_methods[] = {
  328         /* Device interface */
  329         DEVMETHOD(device_probe,         adv_eisa_probe),
  330         DEVMETHOD(device_attach,        adv_eisa_attach),
  331         { 0, 0 }
  332 };
  333 
  334 static driver_t adv_eisa_driver = {
  335         "adv", adv_eisa_methods, sizeof(struct adv_softc)
  336 };
  337 
  338 static devclass_t adv_eisa_devclass;
  339 DRIVER_MODULE(adv, eisa, adv_eisa_driver, adv_eisa_devclass, 0, 0);

Cache object: 90e0ccf29ad646aa811584c828ea137d


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