Fixed some crashing bugs in the pci code - the kernel now boots again.

Added trace methods.
Cleaned up some code.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@759 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2002-08-14 02:09:45 +00:00
parent 6057f25bc6
commit 9b458ca3e7
+140 -53
View File
@@ -2,6 +2,7 @@
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <kernel.h>
#include <console.h>
#include <debug.h>
@@ -23,8 +24,13 @@
#include <PCI.h>
#include <bus.h>
/* Change to 1 to see more debugging :) */
#define THE_FULL_MONTY 0
#define TRACE_PCI 0
#if TRACE_PCI
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
struct pci_device {
struct pci_device *next;
@@ -98,12 +104,15 @@ static void write_pci_config (uchar, uchar, uchar, uchar, uchar, uint32);
restore_interrupts(cpu_status); \
}
/* decode_class
* DEBUG DEBUG DEBUG
* Provide a string that describes the class and sub-class.
* This could/should (?) be expanded to use the api as well.
*/
static char *decode_class(uint8 base, uint8 sub_class)
static char *
decode_class(uint8 base, uint8 sub_class)
{
switch(base) {
case PCI_early:
@@ -208,9 +217,11 @@ static char *decode_class(uint8 base, uint8 sub_class)
}
}
static void show_pci_details(struct pci_info *p)
static void
show_pci_details(struct pci_info *p)
{
#if THE_FULL_MONTY
#if TRACE_PCI
uint16 ss_vend, ss_dev;
#endif
uint8 irq = 0;
@@ -230,7 +241,7 @@ static void show_pci_details(struct pci_info *p)
p->class_api);
dprintf(" => %s\n", decode_class(p->class_base, p->class_sub));
#if THE_FULL_MONTY
#if TRACE_PCI
dprintf("\trevision : %02x\n", p->revision);
dprintf("\tstatus : %04x\n",
read_pci_config(p->bus, p->device, p->function, PCI_status, 2));
@@ -298,7 +309,9 @@ static void show_pci_details(struct pci_info *p)
#define CONFIG_ADDR_2(dev, reg) \
(uint16)(0xC00 | (dev << 8) | reg)
static uint32 read_pci_config(uchar bus, uchar device, uchar function, uchar reg, uchar size)
static uint32
read_pci_config(uchar bus, uchar device, uchar function, uchar reg, uchar size)
{
int cpu_status;
uint32 val = 0;
@@ -363,8 +376,9 @@ static uint32 read_pci_config(uchar bus, uchar device, uchar function, uchar reg
return val;
}
static void write_pci_config(uchar bus, uchar device, uchar function, uchar reg,
uchar size, uint32 value)
static void
write_pci_config(uchar bus, uchar device, uchar function, uchar reg, uchar size, uint32 value)
{
int cpu_status;
@@ -424,13 +438,15 @@ static void write_pci_config(uchar bus, uchar device, uchar function, uchar reg,
return;
}
/* pci_get_capability
* Try to get the offset and value of the specified capability from the
* devices capability list.
* returns 0 if unable, 1 if succesful
*/
static int pci_get_capability(uint8 bus, uint8 dev, uint8 func, uint8 cap,
uint8 *offs)
static int
pci_get_capability(uint8 bus, uint8 dev, uint8 func, uint8 cap, uint8 *offs)
{
uint16 status;
uint8 cap_data;
@@ -489,6 +505,7 @@ static int pci_get_capability(uint8 bus, uint8 dev, uint8 func, uint8 cap,
return 0;
}
/* pci_set_power_state
* This attempts to set the device into one of the 4 power management
* modes, where PCI_pm_state_d0 is "Full Power" and _d3 is the lowest.
@@ -504,7 +521,9 @@ static int pci_get_capability(uint8 bus, uint8 dev, uint8 func, uint8 cap,
* EIO if the device doesn't support the power management state requested
*
*/
static int pci_set_power_state(uint8 bus, uint8 dev, uint8 func, int state)
static int
pci_set_power_state(uint8 bus, uint8 dev, uint8 func, int state)
{
uint8 pm_reg, cur_state;
uint16 cur_status;
@@ -545,12 +564,15 @@ static int pci_set_power_state(uint8 bus, uint8 dev, uint8 func, int state)
return 0;
}
/* This used to be fixup_host_bridges, but some PCI-PCI bridges need
* to be adjusted as well so I'll make it more general.
*
* Partially borrowed from NetBSD.
*/
static void fixup_bridge(uint8 bus, uint8 dev, uint8 func)
static void
fixup_bridge(uint8 bus, uint8 dev, uint8 func)
{
uint16 vendor, device;
@@ -595,6 +617,7 @@ static void fixup_bridge(uint8 bus, uint8 dev, uint8 func)
}
}
/* Given a vendor/device pairing, do we need to scan through
* the entire set of funtions? normally the return will be 0,
* implying we don't need to, but for some it will be 1 which
@@ -603,7 +626,9 @@ static void fixup_bridge(uint8 bus, uint8 dev, uint8 func)
* functions we don't need to and shoudl reduce the possibility of
* duplicates being detected.
*/
static int pci_quirk_multifunction(uint16 vendor, uint16 device)
static int
pci_quirk_multifunction(uint16 vendor, uint16 device)
{
switch (vendor) {
case PCI_VENDOR_INTEL:
@@ -618,6 +643,7 @@ static int pci_quirk_multifunction(uint16 vendor, uint16 device)
return 0;
}
/* set_pci_mechanism()
* Try to determine which configuration mechanism the PCI Host Bridge
* wants to deal with.
@@ -625,7 +651,9 @@ static int pci_quirk_multifunction(uint16 vendor, uint16 device)
* exists, and this code then becomes the fallback. For now we'll
* just use this.
*/
static int set_pci_mechanism(void)
static int
set_pci_mechanism(void)
{
uint32 ckval = 0x80000000;
/* Start by looking for the older and more limited mechanism 2
@@ -668,6 +696,7 @@ static int set_pci_mechanism(void)
return -1;
}
/* check_pci()
* Basically PCI bus #0 "should" contain a PCI Host Bridge.
* This can be identified by the 8 bit pci class base of 0x06.
@@ -683,7 +712,9 @@ static int set_pci_mechanism(void)
* returns 0 if PCI seems to be OK
* -1 if PCI fails the test
*/
static int check_pci(void)
static int
check_pci(void)
{
int dev = 0;
@@ -763,7 +794,9 @@ struct pir_table {
*
* Returns NULL if we fail to find a suitable table.
*/
static struct pir_table *find_pir_table(void)
static struct pir_table *
find_pir_table(void)
{
uint32 mem_addr = (uint32)pci_bios_ptr;
int range = 0x10000;
@@ -786,20 +819,22 @@ static struct pir_table *find_pir_table(void)
return NULL;
}
#if TRACE_PCI
/* print_pir_table
* Print out the table to debug output
*/
#if THE_FULL_MONTY
static void print_pir_table(struct pir_table *tbl)
static void
print_pir_table(struct pir_table *tbl)
{
int i, j;
int entries = (tbl->hdr.tbl_sz - sizeof(struct pir_header)) / sizeof(struct pir_slot);
for (i=0; i < entries; i++) {
for (i = 0; i < entries; i++) {
dprintf("PIR slot %d: bus %d, device %d\n",
tbl->slot[i].slot, tbl->slot[i].bus,
PIR_DEVICE(tbl->slot[i].devfunc));
for (j=0; j < 4; j++)
for (j = 0; j < 4; j++)
dprintf("\tINT%c: pin %d possible_irq's %04x\n",
'A'+j, tbl->slot[i].linkmap[j].pin,
tbl->slot[i].linkmap[j].possible_irq);
@@ -826,8 +861,8 @@ static void print_pir_table(struct pir_table *tbl)
* but will need to eventually.
*/
/* pci_bridge()
* The values passed in specify the "device" on the bus being searched
/** The values passed in specify the "device" on the bus being searched
* that has been identified as a PCI-PCI bridge. We now setup that bridge
* and scan the bus it defines.
* The bus is initially taken off-line, scanned and then put back on-line
@@ -840,7 +875,9 @@ static void print_pir_table(struct pir_table *tbl)
* once we've scanned the bus on the other side of the bridge. See the URL
* above for information on why this is done.
*/
static void pci_bridge(uint8 bus, uint8 dev, uint8 func)
static void
pci_bridge(uint8 bus, uint8 dev, uint8 func)
{
uint16 command;
uint8 mybus;
@@ -848,11 +885,12 @@ static void pci_bridge(uint8 bus, uint8 dev, uint8 func)
struct pci_bus *pcib;
pci_info *pcii;
TRACE(("pci_bridge()\n"));
command = read_pci_config(bus, dev, func, PCI_command, 2);
command &= ~ 0x03;
write_pci_config(bus, dev, func, PCI_command, 2, command);
/* Keep Marcus happy */
pci_max_bus += 1;
mybus = pci_max_bus;
@@ -882,7 +920,11 @@ static void pci_bridge(uint8 bus, uint8 dev, uint8 func)
pcid->info = pcii;
pcid->type = PCI_BRIDGE;
pcid->next = NULL;
pcib->info = pcii;
pcib->next = NULL;
pcii->bus = bus;
pcii->device = dev;
pcii->function = func;
@@ -929,15 +971,16 @@ static void pci_bridge(uint8 bus, uint8 dev, uint8 func)
show_pci_details(pcii);
pci_bridge_skip_infolist:
command |= 0x03;
write_pci_config(bus, dev, func, PCI_command, 2, command);
return;
}
/* This is a very, very brief 2 liner for a device... */
static void debug_show_device(pci_info *pcii)
/** This is a very, very brief 2 liner for a device... */
static void
debug_show_device(pci_info *pcii)
{
uint16 status = read_pci_config(pcii->bus, pcii->device, pcii->function, PCI_status, 2);
@@ -965,13 +1008,17 @@ static void debug_show_device(pci_info *pcii)
dprintf("\t(No capabilities exist for this device)\n");
}
static void pci_device_probe(uint8 bus, uint8 dev, uint8 func)
static void
pci_device_probe(uint8 bus, uint8 dev, uint8 func)
{
uint8 base_class, sub_class;
uint8 type;
pci_info *pcii;
struct pci_device *pcid;
TRACE(("pci_device_probe()\n"));
if (func > 0) {
uint16 vend = read_pci_config(bus, dev, func, PCI_vendor_id, 2);
if (vend == 0xffff)
@@ -990,6 +1037,7 @@ static void pci_device_probe(uint8 bus, uint8 dev, uint8 func)
return;
}
}
/* If we get here then it's not a bridge, so we add it... */
pcii = (pci_info*)kmalloc(sizeof(pci_info));
if (!pcii)
@@ -1002,6 +1050,8 @@ static void pci_device_probe(uint8 bus, uint8 dev, uint8 func)
pcid->info = pcii;
pcid->type = PCI_DEVICE;
pcid->next = NULL;
pcii->bus = bus;
pcii->device = dev;
pcii->function = func;
@@ -1034,8 +1084,8 @@ static void pci_device_probe(uint8 bus, uint8 dev, uint8 func)
debug_show_device(pcii);
}
/* pci_bus()
* Scan a bus for PCI devices. For each device that's a possible
/** Scan a bus for PCI devices. For each device that's a possible
* we get the vendor_id. If it's 0xffff then it's not a valid
* device so we move on.
* Valid devices then have their header_type checked to detrmine how
@@ -1045,11 +1095,15 @@ static void pci_device_probe(uint8 bus, uint8 dev, uint8 func)
* If it's a multifunction device we scan all 8 possible functions,
* otherwise we just probe the first one.
*/
static void pci_scan_bus(uint8 bus)
static void
pci_scan_bus(uint8 bus)
{
uint8 dev = 0, func = 0;
uint16 vend = 0;
TRACE(("pci_scan_bus()\n"));
for (dev = 0; dev < 32; dev++) {
vend = read_pci_config(bus, dev, 0, PCI_vendor_id, 2);
if (vend != 0xffff) {
@@ -1059,8 +1113,8 @@ static void pci_scan_bus(uint8 bus)
type &= PCI_header_type_mask;
if ((type & PCI_multifunction) == 0 &&
!pci_quirk_multifunction(vend, device))
if ((type & PCI_multifunction) == 0
&& !pci_quirk_multifunction(vend, device))
nfunc = 1;
for (func = 0; func < nfunc; func++)
@@ -1069,14 +1123,18 @@ static void pci_scan_bus(uint8 bus)
}
}
static void scan_pci(void)
static void
scan_pci(void)
{
int bus, dev, func;
TRACE(("scan_pci()\n"));
/* We can have up to 255 busses */
for(bus = 0; bus < 255; bus++) {
for (bus = 0; bus < 255; bus++) {
/* Each bus can have up to 'bus_max_devices' devices on it */
for(dev = 0; dev <= bus_max_devices; dev++) {
for (dev = 0; dev <= bus_max_devices; dev++) {
/* Each device can have up to 8 functions */
uint16 sv_vendor_id = 0, sv_device_id = 0;
@@ -1139,7 +1197,9 @@ static void scan_pci(void)
}
}
static void fill_basic_pci_structure(pci_info *pcii)
static void
fill_basic_pci_structure(pci_info *pcii)
{
uint8 bus = pcii->bus, dev = pcii->device, func = pcii->function;
uint8 int_line = 0, int_pin = 0;
@@ -1164,8 +1224,11 @@ static void fill_basic_pci_structure(pci_info *pcii)
int_pin &= PCI_pin_mask;
}
/* XXX - check the return values from this function. */
static long get_nth_pci_info(long index, pci_info *copyto)
static long
get_nth_pci_info(long index, pci_info *copyto)
{
/* We copy the index and then decrement it.
* We also set the start found_pci_device pointer to
@@ -1175,6 +1238,8 @@ static long get_nth_pci_info(long index, pci_info *copyto)
long iter = index;
struct pci_device *pd = pci_devices;
TRACE(("pci_nth_pci_info()\n"));
/* iterate through the list until we have iter == 0
* NB we go in "reverse" as the devices are inserted into the
* list at the start, so going "forward" would give us the last
@@ -1203,36 +1268,49 @@ static long get_nth_pci_info(long index, pci_info *copyto)
}
/* I/O routines */
static uint8 pci_read_io_8(int mapped_io_addr)
static uint8
pci_read_io_8(int mapped_io_addr)
{
return in8(mapped_io_addr);
}
static void pci_write_io_8(int mapped_io_addr, uint8 value)
static void
pci_write_io_8(int mapped_io_addr, uint8 value)
{
out8(value, mapped_io_addr);
}
static uint16 pci_read_io_16(int mapped_io_addr)
static uint16
pci_read_io_16(int mapped_io_addr)
{
return in16(mapped_io_addr);
}
static void pci_write_io_16(int mapped_io_addr, uint16 value)
static void
pci_write_io_16(int mapped_io_addr, uint16 value)
{
out16(value, mapped_io_addr);
}
static uint32 pci_read_io_32(int mapped_io_addr )
static uint32
pci_read_io_32(int mapped_io_addr )
{
return in32(mapped_io_addr);
}
static void pci_write_io_32(int mapped_io_addr, uint32 value)
static void
pci_write_io_32(int mapped_io_addr, uint32 value)
{
out32(value, mapped_io_addr);
}
/* pci_module_init
* This is where we start all the PCI work, or not as the case may be.
* We start by trying to detect and set the correct configuration mechanism
@@ -1251,10 +1329,14 @@ static void pci_write_io_32(int mapped_io_addr, uint32 value)
*
* Finally we scan for devices starting at bus 0.
*/
static void pci_module_init(void)
static void
pci_module_init(void)
{
struct pir_table *pirt = NULL;
TRACE(("pci_module_init()\n"));
if (set_pci_mechanism() == -1) {
return;
}
@@ -1271,7 +1353,7 @@ static void pci_module_init(void)
pirt = find_pir_table();
if (pirt) {
dprintf("PCI IRQ Routing table found\n");
#if THE_FULL_MONTY
#if TRACE_PCI
print_pir_table(pirt);
#endif
}
@@ -1279,16 +1361,20 @@ static void pci_module_init(void)
pci_scan_bus(0);
}
/* pci_module_uninit
* Finish the module by releasing the memory we grabbed for
/** Finish the module by releasing the memory we grabbed for
* the pci_bios :)
*/
static void pci_module_uninit(void)
static void
pci_module_uninit(void)
{
vm_delete_region(vm_get_kernel_aspace_id(), pci_region);
}
static int std_ops(int32 op, ...)
static int
std_ops(int32 op, ...)
{
switch(op) {
case B_MODULE_INIT:
@@ -1305,6 +1391,7 @@ static int std_ops(int32 op, ...)
return B_OK;
}
struct pci_module_info pci_module = {
{
{
@@ -1312,7 +1399,7 @@ struct pci_module_info pci_module = {
B_KEEP_LOADED,
std_ops
},
NULL// &pci_rescan
NULL // &pci_rescan
},
&pci_read_io_8,
@@ -1324,7 +1411,7 @@ struct pci_module_info pci_module = {
&get_nth_pci_info,
&read_pci_config,
&write_pci_config,
NULL,// &ram_address
NULL, // &ram_address
};
module_info *modules[] = {