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

Cache object: 140b9b99236dedacaf759e432cdd8fa9


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