/* * Copyright 2010 Stefan Lankes, Chair for Operating Systems, * RWTH Aachen University * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of MetalSVM. */ #include #include #include #include #ifdef CONFIG_PCI #include #include "pcihdr.h" /* * PCI configuration registers */ #define PCI_CFID 0x00 /* Configuration ID */ #define PCI_CFCS 0x04 /* Configurtion Command/Status */ #define PCI_CFRV 0x08 /* Configuration Revision */ #define PCI_CFLT 0x0c /* Configuration Latency Timer */ #define PCI_CBIO 0x10 /* Configuration Base IO Address */ #define PCI_CBMA 0x14 /* Configuration Base Memory Address */ #define PCI_CFIT 0x3c /* Configuration Interrupt */ #define PCI_CFDA 0x40 /* Configuration Driver Area */ #define PHYS_IO_MEM_START 0 #define PCI_MEM 0 #define PCI_INTA 0 #define PCI_NSLOTS 22 #define PCI_NBUS 0 #define PCI_CONF_ADDR_REG 0xcf8 #define PCI_CONF_FRWD_REG 0xcf8 #define PCI_CONF_DATA_REG 0xcfc #define PCI_IO_CONF_START 0xc000 #define MAX_BUS 16 #define MAX_SLOTS 32 static int mechanism = 0; static int initialized = 0; static int adapters[MAX_BUS][MAX_SLOTS]; static void pci_conf_write(int bus, int slot, int off, int val) { if (mechanism == 1) { outportl(PCI_CONF_FRWD_REG, bus); outportl(PCI_CONF_ADDR_REG, 0xf0); outportl(PCI_IO_CONF_START | (slot << 8) | off, val); } else { outportl(PCI_CONF_ADDR_REG, (0x80000000 | (bus << 16) | (slot << 11) | off)); outportl(PCI_CONF_DATA_REG, val); } } static int pci_conf_read(int bus, int slot, int off) { unsigned int data = -1; outportl(PCI_CONF_ADDR_REG, (0x80000000 | (bus << 16) | (slot << 11) | off)); data = inportl(PCI_CONF_DATA_REG); if ((data == 0xffffffff) && (slot < 0x10)) { outportl(PCI_CONF_FRWD_REG, bus); outportl(PCI_CONF_ADDR_REG, 0xf0); data = inportl(PCI_IO_CONF_START | (slot << 8) | off); if (data == 0xffffffff) return (data); if (!mechanism) mechanism = 1; } else if (!mechanism) mechanism = 2; return (data); } static int pci_what_irq(int bus, int slot, int intx) { return pci_conf_read(bus, slot, PCI_CFIT) & 0xff; } static int find_pci_adapters(void) { int slot, bus; if (initialized) return 0; initialized = 1; for (bus = 0; bus < MAX_BUS; bus++) for (slot = 0; slot < MAX_SLOTS; slot++) adapters[bus][slot] = pci_conf_read(bus, slot, PCI_CFID); return 0; } int pci_init(void) { memset(adapters, -1, MAX_BUS*MAX_SLOTS*sizeof(int)); return find_pci_adapters(); } int print_pci_adapters(void) { int slot, bus; int i, counter = 0; if (!initialized) return -1; for (bus = 0; bus < MAX_BUS; bus++) { for (slot = 0; slot < MAX_SLOTS; slot++) { if (adapters[bus][slot] != -1) { counter++; kprintf("%d) Vendor ID: 0x%x Device Id: 0x%x\n", counter, adapters[bus][slot] & 0xffff, (adapters[bus][slot] & 0xffff0000) >> 16); for (i = 0; i < PCI_VENTABLE_LEN; i++) { if ((adapters[bus][slot] & 0xffff) == (int)PciVenTable[i].VenId) kprintf("\tVendor is %s\n", PciVenTable[i].VenShort); } for (i = 0; i < PCI_DEVTABLE_LEN; i++) { if ((adapters[bus][slot] & 0xffff) == (int)PciDevTable[i].VenId) { if (((adapters[bus][slot] & 0xffff0000) >> 16) == PciDevTable[i].DevId) { kprintf ("\tChip: %s ChipDesc: %s\n", PciDevTable[i].Chip, PciDevTable[i].ChipDesc); } } } } } } return 0; } #endif