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/mca/mca_bus.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  * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD: releng/5.0/sys/dev/mca/mca_bus.c 104015 2002-09-26 18:40:06Z jhb $
   27  */
   28 
   29 /*
   30  * References:
   31  *              The CMU Mach3 microkernel
   32  *              NetBSD MCA patches by Scott Telford
   33  *              Linux MCA code.
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/queue.h>
   39 #include <sys/malloc.h>
   40 #include <sys/kernel.h>
   41 #include <sys/module.h>
   42 #include <sys/bus.h>
   43  
   44 #include <machine/limits.h>
   45 #include <machine/bus.h>              
   46 #include <machine/resource.h>
   47 #include <sys/rman.h>
   48 
   49 #include <dev/mca/mca_busreg.h>
   50 #include <dev/mca/mca_busvar.h>
   51 
   52 #include <sys/interrupt.h>
   53 
   54 #define MAX_COL  79
   55 
   56 static void     mca_reg_print   (device_t, char *, char *, int *);
   57 
   58 struct mca_device {
   59         struct resource_list rl;        /* Resources */
   60 
   61         mca_id_t        id;
   62         u_int8_t        slot;
   63         u_int8_t        enabled;
   64         u_int8_t        pos[8];         /* Programable Option Select Regs. */
   65 };
   66 
   67 /* Not supposed to use this function! */
   68 void
   69 mca_pos_set (dev, reg, data)
   70         device_t        dev;
   71         u_int8_t        reg;
   72         u_int8_t        data;
   73 {
   74         struct mca_device *     m_dev = device_get_ivars(dev);
   75         u_int8_t                slot = mca_get_slot(dev);
   76 
   77         if ((slot > MCA_MAX_ADAPTERS) || (reg > MCA_POS7))
   78                 return;
   79 
   80         /* Disable motherboard setup */
   81         outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
   82 
   83         /* Select adapter setup regs */
   84         outb(MCA_ADAP_SETUP_REG, ((slot & 0x0f) | MCA_ADAP_SET));
   85 
   86         /* Write the register */
   87         outb(MCA_POS_REG(reg), data); 
   88 
   89         /* Disable adapter setup */
   90         outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
   91 
   92         /* Update the IVAR copy */
   93         m_dev->pos[reg] = data;
   94 
   95         return;
   96 }
   97 
   98 u_int8_t
   99 mca_pos_get (dev, reg)
  100         device_t        dev;
  101         u_int8_t        reg;
  102 {
  103         u_int8_t        slot = mca_get_slot(dev);
  104         u_int8_t        data = 0;
  105 
  106         if ((slot > MCA_MAX_ADAPTERS) || (reg > MCA_POS7))
  107                 return (0);
  108 
  109         /* Disable motherboard setup */
  110         outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
  111 
  112         switch (slot) {
  113                 case MCA_MB_SCSI_SLOT:
  114 
  115                         /* Disable adapter setup */
  116                         outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
  117 
  118                         /* Select motherboard video setup regs */
  119                         outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_SCSI);
  120 
  121                         /* read the register */
  122                         data = inb(MCA_POS_REG(reg));
  123 
  124                         /* Disable motherboard setup */
  125                         outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
  126 
  127                         break;
  128                 case MCA_MB_VIDEO_SLOT:
  129                         /* Disable adapter setup */
  130                         outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
  131 
  132                         /* Select motherboard scsi setup regs */
  133                         outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_VIDEO);
  134 
  135                         /* read the register */
  136                         data = inb(MCA_POS_REG(reg));
  137 
  138                         /* Disable motherboard setup */
  139                         outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
  140                         break;
  141                 default:
  142 
  143                         /* Select adapter setup regs */
  144                         outb(MCA_ADAP_SETUP_REG,
  145                              ((slot & 0x0f) | MCA_ADAP_SET));
  146 
  147                         /* read the register */
  148                         data = inb(MCA_POS_REG(reg));
  149 
  150                         /* Disable adapter setup */
  151                         outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
  152                         break;
  153         }
  154 
  155         return (data);
  156 }
  157 
  158 const char *
  159 mca_match_id (id, mca_devs)
  160         u_int16_t               id;
  161         struct mca_ident *      mca_devs;
  162 {
  163         struct mca_ident *      m = mca_devs;
  164         while(m->name != NULL) {
  165                 if (id == m->id)
  166                         return (m->name);
  167                 m++;
  168         }
  169         return (NULL);
  170 }
  171 
  172 u_int8_t
  173 mca_pos_read (dev, reg)
  174         device_t                dev;
  175         u_int8_t                reg;
  176 {
  177         struct mca_device *     m_dev = device_get_ivars(dev);
  178 
  179         if (reg > MCA_POS7)
  180                 return (0);
  181 
  182         return (m_dev->pos[reg]);
  183 }
  184 
  185 void
  186 mca_add_irq (dev, irq)
  187         device_t                dev;
  188         int                     irq;
  189 {
  190         struct mca_device *     m_dev = device_get_ivars(dev);
  191         int                     rid = 0;
  192 
  193         while (resource_list_find(&(m_dev->rl), SYS_RES_IRQ, rid)) rid++;
  194         resource_list_add(&(m_dev->rl), SYS_RES_IRQ, rid, irq, irq, 1);
  195 
  196         return;
  197 }
  198 
  199 void
  200 mca_add_drq (dev, drq)
  201         device_t                dev;
  202         int                     drq;
  203 {
  204         struct mca_device *     m_dev = device_get_ivars(dev);
  205         int                     rid = 0;
  206 
  207         while (resource_list_find(&(m_dev->rl), SYS_RES_DRQ, rid)) rid++;
  208         resource_list_add(&(m_dev->rl), SYS_RES_DRQ, rid, drq, drq, 1);
  209 
  210         return;
  211 }
  212 
  213 void
  214 mca_add_mspace (dev, mbase, msize) 
  215         device_t                dev;
  216         u_long                  mbase;
  217         u_long                  msize;
  218 {
  219         struct mca_device *     m_dev = device_get_ivars(dev);
  220         int                     rid = 0;
  221 
  222         while (resource_list_find(&(m_dev->rl), SYS_RES_MEMORY, rid)) rid++;
  223         resource_list_add(&(m_dev->rl), SYS_RES_MEMORY, rid,
  224                 mbase, (mbase + msize), msize);
  225 
  226         return;
  227 }
  228 
  229 void
  230 mca_add_iospace (dev, iobase, iosize) 
  231         device_t                dev;
  232         u_long                  iobase;
  233         u_long                  iosize;
  234 {
  235         struct mca_device *     m_dev = device_get_ivars(dev);
  236         int                     rid = 0;
  237 
  238         while (resource_list_find(&(m_dev->rl), SYS_RES_IOPORT, rid)) rid++;
  239         resource_list_add(&(m_dev->rl), SYS_RES_IOPORT, rid,
  240                 iobase, (iobase + iosize), iosize);
  241 
  242         return;
  243 }
  244 
  245 static int
  246 mca_probe (device_t dev)
  247 {
  248         device_t                child;
  249         struct mca_device *     m_dev = NULL;
  250         int                     devices_found = 0;
  251         u_int8_t                slot;
  252         u_int8_t                reg;
  253 
  254         device_set_desc(dev, "MCA bus");
  255 
  256         /* Disable adapter setup */
  257         outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
  258         /* Disable motherboard setup */
  259         outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
  260 
  261         if (bootverbose) {
  262                 printf("POS REG     00 01 02 03 04 05 06 07\n");
  263                 printf("-----------------------------------\n");
  264         }
  265 
  266         for (slot = 0; slot < MCA_MAX_SLOTS; slot++) {
  267 
  268                 if (!m_dev) {
  269                         m_dev = (struct mca_device *)malloc(sizeof(*m_dev),
  270                                                             M_DEVBUF, M_NOWAIT);
  271                         if (!m_dev) {
  272                                 device_printf(dev, "cannot malloc mca_device");
  273                                 break;
  274                         }
  275                 }
  276                 bzero(m_dev, sizeof(*m_dev));
  277 
  278                 /* Select adapter setup regs */
  279                 outb(MCA_ADAP_SETUP_REG, ((slot & 0x0f) | MCA_ADAP_SET));
  280 
  281                 /* Read the POS registers */
  282                 for (reg = MCA_POS0; reg <= MCA_POS7; reg++) {
  283                         m_dev->pos[reg] = inb(MCA_POS_REG(reg));
  284                 }
  285 
  286                 /* Disable adapter setup */
  287                 outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
  288 
  289                 if (bootverbose) {
  290                         printf("mca slot %d:", slot + 1);       
  291                         for (reg = MCA_POS0; reg <= MCA_POS7; reg++) {
  292                                 printf(" %02x", m_dev->pos[reg]);
  293                         }
  294                         printf("\n");
  295                 }
  296 
  297                 m_dev->id = (u_int16_t)m_dev->pos[MCA_POS0] |
  298                             ((u_int16_t)m_dev->pos[MCA_POS1] << 8);
  299 
  300                 if (m_dev->id == 0xffff) {
  301                         continue;
  302                 }
  303 
  304                 devices_found++;
  305 
  306                 m_dev->enabled = (m_dev->pos[MCA_POS2] & MCA_POS2_ENABLE);
  307                 m_dev->slot = slot;
  308 
  309                 resource_list_init(&(m_dev->rl));
  310 
  311                 child = device_add_child(dev, NULL, -1);
  312                 device_set_ivars(child, m_dev);
  313 
  314                 m_dev = NULL;
  315         }
  316 
  317         if (m_dev) {
  318                 free(m_dev, M_DEVBUF);
  319         }
  320 
  321         return (devices_found ? 0 : ENXIO);
  322 }
  323 
  324 static void
  325 mca_reg_print (dev, string, separator, column)
  326         device_t        dev;
  327         char *          string;
  328         char *          separator;
  329         int *           column;
  330 {
  331         int             length = strlen(string);
  332 
  333         length += (separator ? 2 : 1);
  334 
  335         if (((*column) + length) >= MAX_COL) {
  336                 printf("\n");
  337                 (*column) = 0;
  338         } else if ((*column) != 0) {
  339                 if (separator) {
  340                         printf("%c", *separator);
  341                         (*column)++;
  342                 }
  343                 printf(" ");
  344                 (*column)++;
  345         }
  346 
  347         if ((*column) == 0) {
  348                 (*column) += device_printf(dev, "%s", string);
  349         } else {
  350                 (*column) += printf("%s", string);
  351         }
  352 
  353         return;
  354 }
  355 
  356 static int
  357 mca_print_child (device_t dev, device_t child)
  358 {
  359         char                            buf[MAX_COL+1];
  360         struct mca_device *             m_dev = device_get_ivars(child);
  361         int                             rid;
  362         struct resource_list_entry *    rle;
  363         char                            separator = ',';
  364         int                             column = 0;
  365         int                             retval = 0;
  366 
  367         if (device_get_desc(child)) {
  368                 snprintf(buf, sizeof(buf), "<%s>", device_get_desc(child));
  369                 mca_reg_print(child, buf, NULL, &column);
  370         }
  371 
  372         rid = 0;
  373         while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_IOPORT, rid++))) {
  374                 if (rle->count == 1) {
  375                         snprintf(buf, sizeof(buf), "%s%lx",
  376                                 ((rid == 1) ? "io 0x" : "0x"),
  377                                 rle->start);
  378                 } else {
  379                         snprintf(buf, sizeof(buf), "%s%lx-0x%lx",
  380                                 ((rid == 1) ? "io 0x" : "0x"),
  381                                 rle->start,
  382                                 (rle->start + rle->count));
  383                 }
  384                 mca_reg_print(child, buf,
  385                         ((rid == 2) ? &separator : NULL), &column);
  386         }
  387 
  388         rid = 0;
  389         while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_MEMORY, rid++))) {
  390                 if (rle->count == 1) {
  391                         snprintf(buf, sizeof(buf), "%s%lx",
  392                                 ((rid == 1) ? "mem 0x" : "0x"),
  393                                 rle->start);
  394                 } else {
  395                         snprintf(buf, sizeof(buf), "%s%lx-0x%lx",
  396                                 ((rid == 1) ? "mem 0x" : "0x"),
  397                                 rle->start,
  398                                 (rle->start + rle->count));
  399                 }
  400                 mca_reg_print(child, buf,
  401                         ((rid == 2) ? &separator : NULL), &column);
  402         }
  403 
  404         rid = 0;
  405         while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_IRQ, rid++))) {
  406                 snprintf(buf, sizeof(buf), "irq %ld", rle->start);
  407                 mca_reg_print(child, buf,
  408                         ((rid == 1) ? &separator : NULL), &column);
  409         }
  410 
  411         rid = 0;
  412         while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_DRQ, rid++))) {
  413                 snprintf(buf, sizeof(buf), "drq %lx", rle->start);
  414                 mca_reg_print(child, buf,
  415                         ((rid == 1) ? &separator : NULL), &column);
  416         }
  417 
  418         snprintf(buf, sizeof(buf), "on %s id %04x slot %d\n",
  419                 device_get_nameunit(dev),
  420                 mca_get_id(child), mca_get_slot(child)+1);
  421         mca_reg_print(child, buf, NULL, &column);
  422 
  423         return (retval);
  424 }
  425 
  426 static void
  427 mca_probe_nomatch (device_t dev, device_t child)
  428 {
  429         mca_id_t        mca_id = mca_get_id(child);
  430         u_int8_t        slot = mca_get_slot(child);
  431         u_int8_t        enabled = mca_get_enabled(child);
  432 
  433         device_printf(dev, "unknown card (id 0x%04x, %s) at slot %d\n",
  434                 mca_id,
  435                 (enabled ? "enabled" : "disabled"),
  436                 slot + 1);
  437 
  438         return;
  439 }
  440 
  441 static int
  442 mca_read_ivar (device_t dev, device_t child, int which, u_long * result)
  443 {
  444         struct mca_device *             m_dev = device_get_ivars(child);
  445 
  446         switch (which) {
  447                 case MCA_IVAR_SLOT:
  448                         *result = m_dev->slot;
  449                         break;
  450                 case MCA_IVAR_ID:
  451                         *result = m_dev->id;
  452                         break;
  453                 case MCA_IVAR_ENABLED:
  454                         *result = m_dev->enabled;
  455                         break;
  456                 default:
  457                         return (ENOENT);
  458                         break;
  459         }
  460 
  461         return (0);
  462 }
  463 
  464 static struct resource *
  465 mca_alloc_resource (device_t dev, device_t child, int type, int *rid,
  466                     u_long start, u_long end, u_long count, u_int flags)
  467 {
  468         struct mca_device *             m_dev = device_get_ivars(child);
  469         struct resource_list_entry *    rle;
  470         int                             isdefault;
  471         int                             passthrough;
  472 
  473         isdefault = (start == 0UL && end == ~0UL);
  474         passthrough = (device_get_parent(child) != dev);
  475 
  476         if (!passthrough && !isdefault) {
  477                 rle = resource_list_find(&(m_dev->rl), type, *rid);
  478                 if (!rle) {
  479                         resource_list_add(&(m_dev->rl), type, *rid,
  480                                           start, end, count);
  481                 }
  482         }
  483 
  484         if (type == SYS_RES_IRQ) {
  485                 flags |= RF_SHAREABLE;
  486         }
  487 
  488         return (resource_list_alloc(&(m_dev->rl), dev, child, type, rid,
  489                                     start, end, count, flags));
  490 }
  491 
  492 static struct resource_list *
  493 mca_get_resource_list (device_t dev, device_t child)
  494 {
  495         struct mca_device *     m_dev = device_get_ivars(child); 
  496         struct resource_list *  rl = &m_dev->rl;
  497  
  498         if (!rl)
  499                 return (NULL);
  500  
  501         return (rl);
  502 }
  503 
  504 static device_method_t mca_methods[] = {
  505         /* Device interface */
  506         DEVMETHOD(device_probe,         mca_probe),
  507         DEVMETHOD(device_attach,        bus_generic_attach),
  508         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  509         DEVMETHOD(device_suspend,       bus_generic_suspend),
  510         DEVMETHOD(device_resume,        bus_generic_resume),
  511 
  512         /* Bus interface */
  513         DEVMETHOD(bus_print_child,      mca_print_child),
  514         DEVMETHOD(bus_probe_nomatch,    mca_probe_nomatch),
  515         DEVMETHOD(bus_read_ivar,        mca_read_ivar),
  516         DEVMETHOD(bus_write_ivar,       bus_generic_write_ivar),
  517         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
  518         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
  519         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),     
  520 
  521         DEVMETHOD(bus_get_resource_list,mca_get_resource_list),
  522         DEVMETHOD(bus_alloc_resource,   mca_alloc_resource),
  523         DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
  524         DEVMETHOD(bus_set_resource,     bus_generic_rl_set_resource),
  525         DEVMETHOD(bus_get_resource,     bus_generic_rl_get_resource),
  526         DEVMETHOD(bus_delete_resource,  bus_generic_rl_delete_resource),
  527         DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
  528         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
  529 
  530         { 0, 0 }
  531 };
  532 
  533 static driver_t mca_driver = {       
  534         "mca",
  535         mca_methods,
  536         1,              /* no softc */
  537 };
  538 
  539 static devclass_t mca_devclass;
  540 
  541 DRIVER_MODULE(mca, legacy, mca_driver, mca_devclass, 0, 0);

Cache object: 7bdded951712e2f9b4cc948a5959e76d


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