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

Cache object: 0ef1f89403e775eed98a127e3e795d0e


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