Annotation of qemu/roms/qemu-palcode/pci.c, revision 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.