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

Cache object: d93629e777d7a91ad0e8e88764cf1f93


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