metalsvm/arch/x86/kernel/pci.c
stefan 7294c47c98 - add code to detect pci interfaces
- code restructuring
- remove some typos in debug messages



git-svn-id: http://svn.lfbs.rwth-aachen.de/svn/scc/trunk/MetalSVM@42 315a16e6-25f9-4109-90ae-ca3045a26c18
2010-08-05 11:53:02 +00:00

165 lines
4 KiB
C

/*
* 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 <metalsvm/stdio.h>
#include <metalsvm/string.h>
#include <asm/irqflags.h>
#include <asm/io.h>
#ifdef CONFIG_PCI
#include <asm/pci.h>
#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