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/isa/pcibus.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 <sys/types.h>
   31 #include <sys/systm.h>
   32 
   33 #include <pci/pcivar.h>
   34 #include <i386/isa/pcibus.h>
   35 
   36 #ifdef PCI_COMPAT
   37 /* XXX this is a terrible hack, which keeps the Tekram AMD SCSI driver happy */
   38 #define cfgmech pci_mechanism
   39 int cfgmech;
   40 #else
   41 static int cfgmech;
   42 #endif /* PCI_COMPAT */
   43 static int devmax;
   44 
   45 /* enable configuration space accesses and return data port address */
   46 
   47 static int
   48 pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
   49 {
   50         int dataport = 0;
   51 
   52         if (bus <= PCI_BUSMAX
   53             && slot < devmax
   54             && func <= PCI_FUNCMAX
   55             && reg <= PCI_REGMAX
   56             && bytes != 3
   57             && (unsigned) bytes <= 4
   58             && (reg & (bytes -1)) == 0) {
   59                 switch (cfgmech) {
   60                 case 1:
   61                         outl(CONF1_ADDR_PORT, (1 << 31)
   62                              | (bus << 16) | (slot << 11) 
   63                              | (func << 8) | (reg & ~0x03));
   64                         dataport = CONF1_DATA_PORT + (reg & 0x03);
   65                         break;
   66                 case 2:
   67                         outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
   68                         outb(CONF2_FORWARD_PORT, bus);
   69                         dataport = 0xc000 | (slot << 8) | reg;
   70                         break;
   71                 }
   72         }
   73         return (dataport);
   74 }
   75 
   76 /* disable configuration space accesses */
   77 
   78 static void
   79 pci_cfgdisable(void)
   80 {
   81         switch (cfgmech) {
   82         case 1:
   83                 outl(CONF1_ADDR_PORT, 0);
   84                 break;
   85         case 2:
   86                 outb(CONF2_ENABLE_PORT, 0);
   87                 outb(CONF2_FORWARD_PORT, 0);
   88                 break;
   89         }
   90 }
   91 
   92 /* read configuration space register */
   93 
   94 int
   95 pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
   96 {
   97         int data = -1;
   98         int port;
   99 
  100         port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
  101 
  102         if (port != 0) {
  103                 switch (bytes) {
  104                 case 1:
  105                         data = inb(port);
  106                         break;
  107                 case 2:
  108                         data = inw(port);
  109                         break;
  110                 case 4:
  111                         data = inl(port);
  112                         break;
  113                 }
  114                 pci_cfgdisable();
  115         }
  116         return (data);
  117 }
  118 
  119 /* write configuration space register */
  120 
  121 void
  122 pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
  123 {
  124         int port;
  125 
  126         port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
  127         if (port != 0) {
  128                 switch (bytes) {
  129                 case 1:
  130                         outb(port, data);
  131                         break;
  132                 case 2:
  133                         outw(port, data);
  134                         break;
  135                 case 4:
  136                         outl(port, data);
  137                         break;
  138                 }
  139                 pci_cfgdisable();
  140         }
  141 }
  142 
  143 /* check whether the configuration mechanism has been correct identified */
  144 
  145 static int
  146 pci_cfgcheck(int maxdev)
  147 {
  148         u_char device;
  149 
  150         if (bootverbose) 
  151                 printf("pci_cfgcheck:\tdevice ");
  152 
  153         for (device = 0; device < maxdev; device++) {
  154                 unsigned id, class, header;
  155                 if (bootverbose) 
  156                         printf("%d ", device);
  157 
  158                 id = inl(pci_cfgenable(0, device, 0, 0, 4));
  159                 if (id == 0 || id == -1)
  160                         continue;
  161 
  162                 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8;
  163                 if (bootverbose)
  164                         printf("[class=%06x] ", class);
  165                 if (class == 0 || (class & 0xf870ff) != 0)
  166                         continue;
  167 
  168                 header = inb(pci_cfgenable(0, device, 0, 14, 1));
  169                 if (bootverbose) 
  170                         printf("[hdr=%02x] ", header);
  171                 if ((header & 0x7e) != 0)
  172                         continue;
  173 
  174                 if (bootverbose)
  175                         printf("is there (id=%08x)\n", id);
  176 
  177                 pci_cfgdisable();
  178                 return (1);
  179         }
  180         if (bootverbose) 
  181                 printf("-- nothing found\n");
  182 
  183         pci_cfgdisable();
  184         return (0);
  185 }
  186 
  187 int
  188 pci_cfgopen(void)
  189 {
  190         unsigned long mode1res,oldval1;
  191         unsigned char mode2res,oldval2;
  192 
  193         oldval1 = inl(CONF1_ADDR_PORT);
  194 
  195         if (bootverbose) {
  196                 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n",
  197                        oldval1);
  198         }
  199 
  200         if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
  201 
  202                 cfgmech = 1;
  203                 devmax = 32;
  204 
  205                 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK);
  206                 outb(CONF1_ADDR_PORT +3, 0);
  207                 mode1res = inl(CONF1_ADDR_PORT);
  208                 outl(CONF1_ADDR_PORT, oldval1);
  209 
  210                 if (bootverbose)
  211                         printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 
  212                                mode1res, CONF1_ENABLE_CHK);
  213 
  214                 if (mode1res) {
  215                         if (pci_cfgcheck(32)) 
  216                                 return (cfgmech);
  217                 }
  218 
  219                 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1);
  220                 mode1res = inl(CONF1_ADDR_PORT);
  221                 outl(CONF1_ADDR_PORT, oldval1);
  222 
  223                 if (bootverbose)
  224                         printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 
  225                                mode1res, CONF1_ENABLE_CHK1);
  226 
  227                 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) {
  228                         if (pci_cfgcheck(32)) 
  229                                 return (cfgmech);
  230                 }
  231         }
  232 
  233         oldval2 = inb(CONF2_ENABLE_PORT);
  234 
  235         if (bootverbose) {
  236                 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n",
  237                        oldval2);
  238         }
  239 
  240         if ((oldval2 & 0xf0) == 0) {
  241 
  242                 cfgmech = 2;
  243                 devmax = 16;
  244 
  245                 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK);
  246                 mode2res = inb(CONF2_ENABLE_PORT);
  247                 outb(CONF2_ENABLE_PORT, oldval2);
  248 
  249                 if (bootverbose)
  250                         printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 
  251                                mode2res, CONF2_ENABLE_CHK);
  252 
  253                 if (mode2res == CONF2_ENABLE_RES) {
  254                         if (bootverbose)
  255                                 printf("pci_open(2a):\tnow trying mechanism 2\n");
  256 
  257                         if (pci_cfgcheck(16)) 
  258                                 return (cfgmech);
  259                 }
  260         }
  261 
  262         cfgmech = 0;
  263         devmax = 0;
  264         return (cfgmech);
  265 }

Cache object: dc9d45d5a43e3ca28cbeeaa1928bd034


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