Annotation of qemu/roms/qemu-palcode/pci.c, revision 1.1.1.1

1.1       root        1: /* Simplistic PCI support.
                      2: 
                      3:    Copyright (C) 2011 Richard Henderson
                      4: 
                      5:    This file is part of QEMU PALcode.
                      6: 
                      7:    This program is free software; you can redistribute it and/or modify
                      8:    it under the terms of the GNU General Public License as published by
                      9:    the Free Software Foundation; either version 2 of the License or
                     10:    (at your option) any later version.
                     11: 
                     12:    This program is distributed in the hope that it will be useful,
                     13:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the text
                     15:    of the GNU General Public License for more details.
                     16: 
                     17:    You should have received a copy of the GNU General Public License
                     18:    along with this program; see the file COPYING.  If not see
                     19:    <http://www.gnu.org/licenses/>.  */
                     20: 
                     21: /* We don't bother supporting PCI bridges, because the device model we're
                     22:    currently using for QEMU doesn't build any.
                     23: 
                     24:    We don't bother to build real datastructures in memory, because it's
                     25:    fairly quick under emulation simply to access configuration space again.
                     26:    This helps when running kernels under the emulator that might have
                     27:    re-organized the BARs out from under us.  */
                     28: 
                     29: #include "protos.h"
                     30: #include "pci.h"
                     31: #include "pci_regs.h"
                     32: 
                     33: 
                     34: #define PCI_DEVFN(slot, func)  ((((slot) & 0x1f) << 3) | ((func) & 0x07))
                     35: #define PCI_BUS(devfn)         ((devfn) >> 8)
                     36: #define PCI_SLOT(devfn)                (((devfn) >> 3) & 0x1f)
                     37: #define PCI_FUNC(devfn)                ((devfn) & 0x07)
                     38: #define PCI_SLOT_MAX           32
                     39: #define PCI_FUNC_MAX           8
                     40: #define PCI_REGION_ROM         6
                     41: #define PCI_REGIONS_MAX                7
                     42: 
                     43: 
                     44: void
                     45: pci_config_maskw(int bdf, int addr, uint16_t off, uint16_t on)
                     46: {
                     47:   uint16_t val = pci_config_readw(bdf, addr);
                     48:   val = (val & ~off) | on;
                     49:   pci_config_writew(bdf, addr, val);
                     50: }
                     51: 
                     52: int
                     53: pci_next(int bdf, int *pmax)
                     54: {
                     55:   int max;
                     56: 
                     57:   if (PCI_FUNC(bdf) == 1)
                     58:     {
                     59:       /* If the last device was not a multi-function device, skip to next.  */
                     60:       if ((pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0)
                     61:         bdf += 7;
                     62:     }
                     63: 
                     64:   max = *pmax;
                     65:   while (1)
                     66:     {
                     67:       uint16_t vendor;
                     68: 
                     69:       /* ??? Support multiple PCI busses here at some point.  */
                     70:       if (bdf >= max)
                     71:        return -1;
                     72: 
                     73:       /* Check if there is a device present at the location.  */
                     74:       vendor = pci_config_readw(bdf, PCI_VENDOR_ID);
                     75:       if (vendor != 0x0000 && vendor != 0xffff)
                     76:        return bdf;
                     77: 
                     78:       bdf += (PCI_FUNC(bdf) == 0 ? 8 : 1);
                     79:     }
                     80: }
                     81: 
                     82: static void
                     83: pci_setup_device(int bdf, uint32_t *p_io_base, uint32_t *p_mem_base)
                     84: {
                     85:   int vendor_id, device_id, class_id, region;
                     86: 
                     87:   vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
                     88:   device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
                     89:   class_id = pci_config_readw(bdf, PCI_CLASS_DEVICE);
                     90: 
                     91:   printf("PCI: %02x:%02x:%x class %04x id %04x:%04x\r\n",
                     92:         PCI_BUS(bdf), PCI_SLOT(bdf), PCI_FUNC(bdf),
                     93:          class_id, vendor_id, device_id);
                     94: 
                     95:   for (region = 0; region < PCI_REGION_ROM; region++)
                     96:     {
                     97:       int ofs = PCI_BASE_ADDRESS_0 + region * 4;
                     98:       uint32_t old, mask, val, size, align;
                     99:       uint32_t *p_base;
                    100: 
                    101:       old = pci_config_readl(bdf, ofs);
                    102:       if (old & PCI_BASE_ADDRESS_SPACE_IO)
                    103:        {
                    104:          mask = PCI_BASE_ADDRESS_IO_MASK;
                    105:          p_base = p_io_base;
                    106:        }
                    107:       else
                    108:        {
                    109:          mask = PCI_BASE_ADDRESS_MEM_MASK;
                    110:          p_base = p_mem_base;
                    111:        }
                    112: 
                    113:       pci_config_writel(bdf, ofs, -1);
                    114:       val = pci_config_readl(bdf, ofs);
                    115:       pci_config_writel(bdf, ofs, old);
                    116: 
                    117:       align = size = ~(val & mask) + 1;
                    118:       if (val != 0)
                    119:        {
                    120:          uint32_t addr = *p_base;
                    121:          addr = (addr + align - 1) & ~(align - 1);
                    122:          *p_base = addr + size;
                    123:          pci_config_writel(bdf, ofs, addr);
                    124: 
                    125:          printf("PCI:   region %d: %08x\r\n", region, addr);
                    126: 
                    127:          if ((val & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
                    128:              == PCI_BASE_ADDRESS_MEM_TYPE_64)
                    129:            {
                    130:              pci_config_writel(bdf, ofs + 4, 0);
                    131:              region++;
                    132:            }
                    133:        }
                    134:     }
                    135: 
                    136:   pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
                    137: 
                    138:   /* Map the interrupt.  */
                    139: }
                    140: 
                    141: void
                    142: pci_setup(void)
                    143: {
                    144:   uint32_t io_base = 0xc000;
                    145:   uint32_t mem_base = 256 * 1024 * 1024;
                    146:   int bdf, max;
                    147: 
                    148:   foreachpci (bdf, max)
                    149:     pci_setup_device(bdf, &io_base, &mem_base);
                    150: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.