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/pci/pci_compat.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) 1997, Stefan Esser <se@freebsd.org>
    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 unmodified, this list of conditions, and the following
   10  *    disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  *
   28  */
   29 
   30 #include "opt_bus.h"
   31 
   32 /* for compatibility to FreeBSD-2.2 version of PCI code */
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/malloc.h>
   37 
   38 #include <vm/vm.h>
   39 #include <vm/pmap.h>
   40 #include <sys/interrupt.h>
   41 
   42 #include <sys/bus.h>
   43 #include <machine/bus.h>
   44 #include <sys/rman.h>
   45 #include <machine/resource.h>
   46 
   47 #include <pci/pcireg.h>
   48 #include <pci/pcivar.h>
   49 
   50 #ifdef APIC_IO
   51 #include <machine/smp.h>
   52 #endif
   53 
   54 #ifdef PCI_COMPAT
   55 
   56 /* ------------------------------------------------------------------------- */
   57 
   58 u_long
   59 pci_conf_read(pcici_t cfg, u_long reg)
   60 {
   61         return (pci_read_config(cfg->dev, reg, 4));
   62 }
   63 
   64 void
   65 pci_conf_write(pcici_t cfg, u_long reg, u_long data)
   66 {
   67         pci_write_config(cfg->dev, reg, data, 4);
   68 }
   69 
   70 int
   71 pci_map_port(pcici_t cfg, u_long reg, pci_port_t* pa)
   72 {
   73         int rid;
   74         struct resource *res;
   75 
   76         rid = reg;
   77         res = bus_alloc_resource(cfg->dev, SYS_RES_IOPORT, &rid,
   78                                  0, ~0, 1, RF_ACTIVE);
   79         if (res) {
   80                 *pa = rman_get_start(res);
   81                 return (1);
   82         }
   83         return (0);
   84 }
   85 
   86 int
   87 pci_map_mem(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa)
   88 {
   89         int rid;
   90         struct resource *res;
   91 
   92         rid = reg;
   93         res = bus_alloc_resource(cfg->dev, SYS_RES_MEMORY, &rid,
   94                                  0, ~0, 1, RF_ACTIVE);
   95         if (res) {
   96                 *pa = rman_get_start(res);
   97                 *va = (vm_offset_t) rman_get_virtual(res);
   98                 return (1);
   99         }
  100         return (0);
  101 }
  102 
  103 int
  104 pci_map_int(pcici_t cfg, pci_inthand_t *handler, void *arg, intrmask_t *maskptr)
  105 {
  106         return (pci_map_int_right(cfg, handler, arg, maskptr, 0));
  107 }
  108 
  109 int
  110 pci_map_int_right(pcici_t cfg, pci_inthand_t *handler, void *arg,
  111                   intrmask_t *maskptr, u_int intflags)
  112 {
  113         int error;
  114 #ifdef APIC_IO
  115         int nextpin, muxcnt;
  116 #endif
  117         if (cfg->intpin != 0) {
  118                 int irq = cfg->intline;
  119                 int rid = 0;
  120                 struct resource *res;
  121                 int flags = 0;
  122                 int resflags = RF_SHAREABLE|RF_ACTIVE;
  123                 void *ih;
  124 
  125 #ifdef INTR_FAST
  126                 if (intflags & INTR_FAST)
  127                         flags |= INTR_TYPE_FAST;
  128                 if (intflags & INTR_EXCL)
  129                         resflags &= ~RF_SHAREABLE;
  130 #endif
  131 
  132                 res = bus_alloc_resource(cfg->dev, SYS_RES_IRQ, &rid,
  133                                          irq, irq, 1, resflags);
  134                 if (!res) {
  135                         printf("pci_map_int: can't allocate interrupt\n");
  136                         return 0;
  137                 }
  138 
  139                 /*
  140                  * This is ugly. Translate the mask into an interrupt type.
  141                  */
  142                 if (maskptr == &tty_imask)
  143                         flags |= INTR_TYPE_TTY;
  144                 else if (maskptr == &bio_imask)
  145                         flags |= INTR_TYPE_BIO;
  146                 else if (maskptr == &net_imask)
  147                         flags |= INTR_TYPE_NET;
  148                 else if (maskptr == &cam_imask)
  149                         flags |= INTR_TYPE_CAM;
  150 
  151                 error = BUS_SETUP_INTR(device_get_parent(cfg->dev), cfg->dev,
  152                                        res, flags, handler, arg, &ih);
  153                 if (error != 0)
  154                         return 0;
  155 
  156 #ifdef NEW_BUS_PCI
  157                 /*
  158                  * XXX this apic stuff looks totally busted.  It should
  159                  * move to the nexus code which actually registers the
  160                  * interrupt.
  161                  */
  162 #endif
  163 
  164 #ifdef APIC_IO
  165                 nextpin = next_apic_irq(irq);
  166                 
  167                 if (nextpin < 0)
  168                         return 1;
  169 
  170                 /* 
  171                  * Attempt handling of some broken mp tables.
  172                  *
  173                  * It's OK to yell (since the mp tables are broken).
  174                  * 
  175                  * Hanging in the boot is not OK
  176                  */
  177 
  178                 muxcnt = 2;
  179                 nextpin = next_apic_irq(nextpin);
  180                 while (muxcnt < 5 && nextpin >= 0) {
  181                         muxcnt++;
  182                         nextpin = next_apic_irq(nextpin);
  183                 }
  184                 if (muxcnt >= 5) {
  185                         printf("bogus MP table, more than 4 IO APIC pins connected to the same PCI device or ISA/EISA interrupt\n");
  186                         return 0;
  187                 }
  188                 
  189                 printf("bogus MP table, %d IO APIC pins connected to the same PCI device or ISA/EISA interrupt\n", muxcnt);
  190 
  191                 nextpin = next_apic_irq(irq);
  192                 while (nextpin >= 0) {
  193                         rid = 0;
  194                         res = bus_alloc_resource(cfg->dev, SYS_RES_IRQ, &rid,
  195                                                  nextpin, nextpin, 1,
  196                                                  resflags);
  197                         if (!res) {
  198                                 printf("pci_map_int: can't allocate extra interrupt\n");
  199                                 return 0;
  200                         }
  201                         error = BUS_SETUP_INTR(device_get_parent(cfg->dev),
  202                                                cfg->dev, res, flags,
  203                                                handler, arg, &ih);
  204                         if (error != 0) {
  205                                 printf("pci_map_int: BUS_SETUP_INTR failed\n");
  206                                 return 0;
  207                         }
  208                         printf("Registered extra interrupt handler for int %d (in addition to int %d)\n", nextpin, irq);
  209                         nextpin = next_apic_irq(nextpin);
  210                 }
  211 #endif
  212         }
  213         return (1);
  214 }
  215 
  216 int
  217 pci_unmap_int(pcici_t cfg)
  218 {
  219         return (0); /* not supported, yet, since cfg doesn't know about idesc */
  220 }
  221 
  222 pcici_t
  223 pci_get_parent_from_tag(pcici_t tag)
  224 {
  225         return (pcici_t)pci_devlist_get_parent(tag);
  226 }
  227 
  228 int
  229 pci_get_bus_from_tag(pcici_t tag)
  230 {
  231         return tag->bus;
  232 }
  233 
  234 #endif /* PCI_COMPAT */

Cache object: 3df66810c9b715ac3d724a8fd2b81296


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