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:
@@ -2,6 +2,7 @@
|
|||||||
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <console.h>
|
#include <console.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -23,8 +24,13 @@
|
|||||||
#include <PCI.h>
|
#include <PCI.h>
|
||||||
#include <bus.h>
|
#include <bus.h>
|
||||||
|
|
||||||
/* Change to 1 to see more debugging :) */
|
#define TRACE_PCI 0
|
||||||
#define THE_FULL_MONTY 0
|
#if TRACE_PCI
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
|
#else
|
||||||
|
# define TRACE(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct pci_device {
|
struct pci_device {
|
||||||
struct pci_device *next;
|
struct pci_device *next;
|
||||||
@@ -98,12 +104,15 @@ static void write_pci_config (uchar, uchar, uchar, uchar, uchar, uint32);
|
|||||||
restore_interrupts(cpu_status); \
|
restore_interrupts(cpu_status); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* decode_class
|
/* decode_class
|
||||||
* DEBUG DEBUG DEBUG
|
* DEBUG DEBUG DEBUG
|
||||||
* Provide a string that describes the class and sub-class.
|
* Provide a string that describes the class and sub-class.
|
||||||
* This could/should (?) be expanded to use the api as well.
|
* 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) {
|
switch(base) {
|
||||||
case PCI_early:
|
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;
|
uint16 ss_vend, ss_dev;
|
||||||
#endif
|
#endif
|
||||||
uint8 irq = 0;
|
uint8 irq = 0;
|
||||||
@@ -230,7 +241,7 @@ static void show_pci_details(struct pci_info *p)
|
|||||||
p->class_api);
|
p->class_api);
|
||||||
dprintf(" => %s\n", decode_class(p->class_base, p->class_sub));
|
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("\trevision : %02x\n", p->revision);
|
||||||
dprintf("\tstatus : %04x\n",
|
dprintf("\tstatus : %04x\n",
|
||||||
read_pci_config(p->bus, p->device, p->function, PCI_status, 2));
|
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) \
|
#define CONFIG_ADDR_2(dev, reg) \
|
||||||
(uint16)(0xC00 | (dev << 8) | 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;
|
int cpu_status;
|
||||||
uint32 val = 0;
|
uint32 val = 0;
|
||||||
@@ -363,8 +376,9 @@ static uint32 read_pci_config(uchar bus, uchar device, uchar function, uchar reg
|
|||||||
return val;
|
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;
|
int cpu_status;
|
||||||
|
|
||||||
@@ -424,13 +438,15 @@ static void write_pci_config(uchar bus, uchar device, uchar function, uchar reg,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* pci_get_capability
|
/* pci_get_capability
|
||||||
* Try to get the offset and value of the specified capability from the
|
* Try to get the offset and value of the specified capability from the
|
||||||
* devices capability list.
|
* devices capability list.
|
||||||
* returns 0 if unable, 1 if succesful
|
* 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;
|
uint16 status;
|
||||||
uint8 cap_data;
|
uint8 cap_data;
|
||||||
@@ -489,6 +505,7 @@ static int pci_get_capability(uint8 bus, uint8 dev, uint8 func, uint8 cap,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* pci_set_power_state
|
/* pci_set_power_state
|
||||||
* This attempts to set the device into one of the 4 power management
|
* 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.
|
* 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
|
* 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;
|
uint8 pm_reg, cur_state;
|
||||||
uint16 cur_status;
|
uint16 cur_status;
|
||||||
@@ -545,12 +564,15 @@ static int pci_set_power_state(uint8 bus, uint8 dev, uint8 func, int state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This used to be fixup_host_bridges, but some PCI-PCI bridges need
|
/* 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.
|
* to be adjusted as well so I'll make it more general.
|
||||||
*
|
*
|
||||||
* Partially borrowed from NetBSD.
|
* 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;
|
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
|
/* Given a vendor/device pairing, do we need to scan through
|
||||||
* the entire set of funtions? normally the return will be 0,
|
* 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
|
* 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
|
* functions we don't need to and shoudl reduce the possibility of
|
||||||
* duplicates being detected.
|
* duplicates being detected.
|
||||||
*/
|
*/
|
||||||
static int pci_quirk_multifunction(uint16 vendor, uint16 device)
|
|
||||||
|
static int
|
||||||
|
pci_quirk_multifunction(uint16 vendor, uint16 device)
|
||||||
{
|
{
|
||||||
switch (vendor) {
|
switch (vendor) {
|
||||||
case PCI_VENDOR_INTEL:
|
case PCI_VENDOR_INTEL:
|
||||||
@@ -618,6 +643,7 @@ static int pci_quirk_multifunction(uint16 vendor, uint16 device)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* set_pci_mechanism()
|
/* set_pci_mechanism()
|
||||||
* Try to determine which configuration mechanism the PCI Host Bridge
|
* Try to determine which configuration mechanism the PCI Host Bridge
|
||||||
* wants to deal with.
|
* 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
|
* exists, and this code then becomes the fallback. For now we'll
|
||||||
* just use this.
|
* just use this.
|
||||||
*/
|
*/
|
||||||
static int set_pci_mechanism(void)
|
|
||||||
|
static int
|
||||||
|
set_pci_mechanism(void)
|
||||||
{
|
{
|
||||||
uint32 ckval = 0x80000000;
|
uint32 ckval = 0x80000000;
|
||||||
/* Start by looking for the older and more limited mechanism 2
|
/* Start by looking for the older and more limited mechanism 2
|
||||||
@@ -668,6 +696,7 @@ static int set_pci_mechanism(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* check_pci()
|
/* check_pci()
|
||||||
* Basically PCI bus #0 "should" contain a PCI Host Bridge.
|
* Basically PCI bus #0 "should" contain a PCI Host Bridge.
|
||||||
* This can be identified by the 8 bit pci class base of 0x06.
|
* 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
|
* returns 0 if PCI seems to be OK
|
||||||
* -1 if PCI fails the test
|
* -1 if PCI fails the test
|
||||||
*/
|
*/
|
||||||
static int check_pci(void)
|
|
||||||
|
static int
|
||||||
|
check_pci(void)
|
||||||
{
|
{
|
||||||
int dev = 0;
|
int dev = 0;
|
||||||
|
|
||||||
@@ -763,7 +794,9 @@ struct pir_table {
|
|||||||
*
|
*
|
||||||
* Returns NULL if we fail to find a suitable 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;
|
uint32 mem_addr = (uint32)pci_bios_ptr;
|
||||||
int range = 0x10000;
|
int range = 0x10000;
|
||||||
@@ -786,20 +819,22 @@ static struct pir_table *find_pir_table(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TRACE_PCI
|
||||||
/* print_pir_table
|
/* print_pir_table
|
||||||
* Print out the table to debug output
|
* 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 i, j;
|
||||||
int entries = (tbl->hdr.tbl_sz - sizeof(struct pir_header)) / sizeof(struct pir_slot);
|
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",
|
dprintf("PIR slot %d: bus %d, device %d\n",
|
||||||
tbl->slot[i].slot, tbl->slot[i].bus,
|
tbl->slot[i].slot, tbl->slot[i].bus,
|
||||||
PIR_DEVICE(tbl->slot[i].devfunc));
|
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",
|
dprintf("\tINT%c: pin %d possible_irq's %04x\n",
|
||||||
'A'+j, tbl->slot[i].linkmap[j].pin,
|
'A'+j, tbl->slot[i].linkmap[j].pin,
|
||||||
tbl->slot[i].linkmap[j].possible_irq);
|
tbl->slot[i].linkmap[j].possible_irq);
|
||||||
@@ -826,21 +861,23 @@ static void print_pir_table(struct pir_table *tbl)
|
|||||||
* but will need to eventually.
|
* 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
|
* that has been identified as a PCI-PCI bridge. We now setup that bridge
|
||||||
* and scan the bus it defines.
|
* and scan the bus it defines.
|
||||||
* The bus is initially taken off-line, scanned and then put back on-line
|
* The bus is initially taken off-line, scanned and then put back on-line
|
||||||
*
|
*
|
||||||
* NB We increment the pci_max_bus value before we use mybus in the following
|
* NB We increment the pci_max_bus value before we use mybus in the following
|
||||||
* code and pci_max_bus is incremented before we recurse to preserve the
|
* code and pci_max_bus is incremented before we recurse to preserve the
|
||||||
* correct relationships with nubering.
|
* correct relationships with nubering.
|
||||||
*
|
*
|
||||||
* We initally set the subordinate_bus to 0xff and then adjust it to the max
|
* We initally set the subordinate_bus to 0xff and then adjust it to the max
|
||||||
* once we've scanned the bus on the other side of the bridge. See the URL
|
* once we've scanned the bus on the other side of the bridge. See the URL
|
||||||
* above for information on why this is done.
|
* 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;
|
uint16 command;
|
||||||
uint8 mybus;
|
uint8 mybus;
|
||||||
@@ -848,11 +885,12 @@ static void pci_bridge(uint8 bus, uint8 dev, uint8 func)
|
|||||||
struct pci_bus *pcib;
|
struct pci_bus *pcib;
|
||||||
pci_info *pcii;
|
pci_info *pcii;
|
||||||
|
|
||||||
|
TRACE(("pci_bridge()\n"));
|
||||||
|
|
||||||
command = read_pci_config(bus, dev, func, PCI_command, 2);
|
command = read_pci_config(bus, dev, func, PCI_command, 2);
|
||||||
command &= ~ 0x03;
|
command &= ~ 0x03;
|
||||||
write_pci_config(bus, dev, func, PCI_command, 2, command);
|
write_pci_config(bus, dev, func, PCI_command, 2, command);
|
||||||
|
|
||||||
/* Keep Marcus happy */
|
|
||||||
pci_max_bus += 1;
|
pci_max_bus += 1;
|
||||||
mybus = pci_max_bus;
|
mybus = pci_max_bus;
|
||||||
|
|
||||||
@@ -882,7 +920,11 @@ static void pci_bridge(uint8 bus, uint8 dev, uint8 func)
|
|||||||
|
|
||||||
pcid->info = pcii;
|
pcid->info = pcii;
|
||||||
pcid->type = PCI_BRIDGE;
|
pcid->type = PCI_BRIDGE;
|
||||||
|
pcid->next = NULL;
|
||||||
|
|
||||||
pcib->info = pcii;
|
pcib->info = pcii;
|
||||||
|
pcib->next = NULL;
|
||||||
|
|
||||||
pcii->bus = bus;
|
pcii->bus = bus;
|
||||||
pcii->device = dev;
|
pcii->device = dev;
|
||||||
pcii->function = func;
|
pcii->function = func;
|
||||||
@@ -929,15 +971,16 @@ static void pci_bridge(uint8 bus, uint8 dev, uint8 func)
|
|||||||
show_pci_details(pcii);
|
show_pci_details(pcii);
|
||||||
|
|
||||||
pci_bridge_skip_infolist:
|
pci_bridge_skip_infolist:
|
||||||
|
|
||||||
command |= 0x03;
|
command |= 0x03;
|
||||||
write_pci_config(bus, dev, func, PCI_command, 2, command);
|
write_pci_config(bus, dev, func, PCI_command, 2, command);
|
||||||
return;
|
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);
|
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");
|
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 base_class, sub_class;
|
||||||
uint8 type;
|
uint8 type;
|
||||||
pci_info *pcii;
|
pci_info *pcii;
|
||||||
struct pci_device *pcid;
|
struct pci_device *pcid;
|
||||||
|
|
||||||
|
TRACE(("pci_device_probe()\n"));
|
||||||
|
|
||||||
if (func > 0) {
|
if (func > 0) {
|
||||||
uint16 vend = read_pci_config(bus, dev, func, PCI_vendor_id, 2);
|
uint16 vend = read_pci_config(bus, dev, func, PCI_vendor_id, 2);
|
||||||
if (vend == 0xffff)
|
if (vend == 0xffff)
|
||||||
@@ -990,6 +1037,7 @@ static void pci_device_probe(uint8 bus, uint8 dev, uint8 func)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we get here then it's not a bridge, so we add it... */
|
/* If we get here then it's not a bridge, so we add it... */
|
||||||
pcii = (pci_info*)kmalloc(sizeof(pci_info));
|
pcii = (pci_info*)kmalloc(sizeof(pci_info));
|
||||||
if (!pcii)
|
if (!pcii)
|
||||||
@@ -1002,6 +1050,8 @@ static void pci_device_probe(uint8 bus, uint8 dev, uint8 func)
|
|||||||
|
|
||||||
pcid->info = pcii;
|
pcid->info = pcii;
|
||||||
pcid->type = PCI_DEVICE;
|
pcid->type = PCI_DEVICE;
|
||||||
|
pcid->next = NULL;
|
||||||
|
|
||||||
pcii->bus = bus;
|
pcii->bus = bus;
|
||||||
pcii->device = dev;
|
pcii->device = dev;
|
||||||
pcii->function = func;
|
pcii->function = func;
|
||||||
@@ -1034,22 +1084,26 @@ static void pci_device_probe(uint8 bus, uint8 dev, uint8 func)
|
|||||||
debug_show_device(pcii);
|
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
|
* we get the vendor_id. If it's 0xffff then it's not a valid
|
||||||
* device so we move on.
|
* device so we move on.
|
||||||
* Valid devices then have their header_type checked to detrmine how
|
* Valid devices then have their header_type checked to detrmine how
|
||||||
* many functions we need to check. However, some devices that support
|
* many functions we need to check. However, some devices that support
|
||||||
* multiple functions have a header_type of 0 (generic) so we also check
|
* multiple functions have a header_type of 0 (generic) so we also check
|
||||||
* for these using pci_quirk_multifunction().
|
* for these using pci_quirk_multifunction().
|
||||||
* If it's a multifunction device we scan all 8 possible functions,
|
* If it's a multifunction device we scan all 8 possible functions,
|
||||||
* otherwise we just probe the first one.
|
* 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;
|
uint8 dev = 0, func = 0;
|
||||||
uint16 vend = 0;
|
uint16 vend = 0;
|
||||||
|
|
||||||
|
TRACE(("pci_scan_bus()\n"));
|
||||||
|
|
||||||
for (dev = 0; dev < 32; dev++) {
|
for (dev = 0; dev < 32; dev++) {
|
||||||
vend = read_pci_config(bus, dev, 0, PCI_vendor_id, 2);
|
vend = read_pci_config(bus, dev, 0, PCI_vendor_id, 2);
|
||||||
if (vend != 0xffff) {
|
if (vend != 0xffff) {
|
||||||
@@ -1059,8 +1113,8 @@ static void pci_scan_bus(uint8 bus)
|
|||||||
|
|
||||||
type &= PCI_header_type_mask;
|
type &= PCI_header_type_mask;
|
||||||
|
|
||||||
if ((type & PCI_multifunction) == 0 &&
|
if ((type & PCI_multifunction) == 0
|
||||||
!pci_quirk_multifunction(vend, device))
|
&& !pci_quirk_multifunction(vend, device))
|
||||||
nfunc = 1;
|
nfunc = 1;
|
||||||
|
|
||||||
for (func = 0; func < nfunc; func++)
|
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;
|
int bus, dev, func;
|
||||||
|
|
||||||
|
TRACE(("scan_pci()\n"));
|
||||||
|
|
||||||
/* We can have up to 255 busses */
|
/* 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 */
|
/* 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 */
|
/* Each device can have up to 8 functions */
|
||||||
uint16 sv_vendor_id = 0, sv_device_id = 0;
|
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 bus = pcii->bus, dev = pcii->device, func = pcii->function;
|
||||||
uint8 int_line = 0, int_pin = 0;
|
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;
|
int_pin &= PCI_pin_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* XXX - check the return values from this function. */
|
/* 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 copy the index and then decrement it.
|
||||||
* We also set the start found_pci_device pointer to
|
* 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;
|
long iter = index;
|
||||||
struct pci_device *pd = pci_devices;
|
struct pci_device *pd = pci_devices;
|
||||||
|
|
||||||
|
TRACE(("pci_nth_pci_info()\n"));
|
||||||
|
|
||||||
/* iterate through the list until we have iter == 0
|
/* iterate through the list until we have iter == 0
|
||||||
* NB we go in "reverse" as the devices are inserted into the
|
* NB we go in "reverse" as the devices are inserted into the
|
||||||
* list at the start, so going "forward" would give us the last
|
* 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 */
|
/* 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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
out32(value, mapped_io_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* pci_module_init
|
/* pci_module_init
|
||||||
* This is where we start all the PCI work, or not as the case may be.
|
* 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
|
* 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.
|
* 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;
|
struct pir_table *pirt = NULL;
|
||||||
|
|
||||||
|
TRACE(("pci_module_init()\n"));
|
||||||
|
|
||||||
if (set_pci_mechanism() == -1) {
|
if (set_pci_mechanism() == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1271,7 +1353,7 @@ static void pci_module_init(void)
|
|||||||
pirt = find_pir_table();
|
pirt = find_pir_table();
|
||||||
if (pirt) {
|
if (pirt) {
|
||||||
dprintf("PCI IRQ Routing table found\n");
|
dprintf("PCI IRQ Routing table found\n");
|
||||||
#if THE_FULL_MONTY
|
#if TRACE_PCI
|
||||||
print_pir_table(pirt);
|
print_pir_table(pirt);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1279,16 +1361,20 @@ static void pci_module_init(void)
|
|||||||
pci_scan_bus(0);
|
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 :)
|
* 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);
|
vm_delete_region(vm_get_kernel_aspace_id(), pci_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int std_ops(int32 op, ...)
|
|
||||||
|
static int
|
||||||
|
std_ops(int32 op, ...)
|
||||||
{
|
{
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case B_MODULE_INIT:
|
case B_MODULE_INIT:
|
||||||
@@ -1305,6 +1391,7 @@ static int std_ops(int32 op, ...)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct pci_module_info pci_module = {
|
struct pci_module_info pci_module = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -1312,7 +1399,7 @@ struct pci_module_info pci_module = {
|
|||||||
B_KEEP_LOADED,
|
B_KEEP_LOADED,
|
||||||
std_ops
|
std_ops
|
||||||
},
|
},
|
||||||
NULL// &pci_rescan
|
NULL // &pci_rescan
|
||||||
},
|
},
|
||||||
|
|
||||||
&pci_read_io_8,
|
&pci_read_io_8,
|
||||||
@@ -1324,7 +1411,7 @@ struct pci_module_info pci_module = {
|
|||||||
&get_nth_pci_info,
|
&get_nth_pci_info,
|
||||||
&read_pci_config,
|
&read_pci_config,
|
||||||
&write_pci_config,
|
&write_pci_config,
|
||||||
NULL,// &ram_address
|
NULL, // &ram_address
|
||||||
};
|
};
|
||||||
|
|
||||||
module_info *modules[] = {
|
module_info *modules[] = {
|
||||||
|
|||||||
Reference in New Issue
Block a user