allocating resource for legacy VGA frame buffer, it is not 100%

correct but it works anyway.


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1811 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Li-Ta Lo 2004-12-03 22:39:34 +00:00
parent 845e8df673
commit 3a81285409
6 changed files with 131 additions and 101 deletions

View File

@ -37,6 +37,15 @@ it with the version available from LANL.
#include <part/init_timer.h> #include <part/init_timer.h>
#include <boot/elf.h> #include <boot/elf.h>
/**
* @brief Main function of the DRAM part of LinuxBIOS.
*
* LinuxBIOS is divided into Pre-DRAM part and DRAM part.
*
*
* Device Enumeration:
* In the dev_enumerate() phase,
*/
void hardwaremain(int boot_complete) void hardwaremain(int boot_complete)
{ {
struct lb_memory *lb_mem; struct lb_memory *lb_mem;
@ -48,8 +57,8 @@ void hardwaremain(int boot_complete)
post_code(0x39); post_code(0x39);
printk_notice("LinuxBIOS-%s%s %s %s...\n", printk_notice("LinuxBIOS-%s%s %s %s...\n",
linuxbios_version, linuxbios_extra_version, linuxbios_build, linuxbios_version, linuxbios_extra_version, linuxbios_build,
(boot_complete)?"rebooting":"booting"); (boot_complete)?"rebooting":"booting");
post_code(0x40); post_code(0x40);

View File

@ -56,10 +56,12 @@ device_t alloc_dev(struct bus *parent, struct device_path *path)
int link; int link;
spin_lock(&dev_lock); spin_lock(&dev_lock);
/* Find the last child of our parent */ /* Find the last child of our parent */
for(child = parent->children; child && child->sibling; ) { for (child = parent->children; child && child->sibling; ) {
child = child->sibling; child = child->sibling;
} }
dev = malloc(sizeof(*dev)); dev = malloc(sizeof(*dev));
if (dev == 0) { if (dev == 0) {
die("DEV: out of memory.\n"); die("DEV: out of memory.\n");
@ -67,13 +69,12 @@ device_t alloc_dev(struct bus *parent, struct device_path *path)
memset(dev, 0, sizeof(*dev)); memset(dev, 0, sizeof(*dev));
memcpy(&dev->path, path, sizeof(*path)); memcpy(&dev->path, path, sizeof(*path));
/* Initialize the back pointers in the link fields */ /* Initialize the back pointers in the link fields */
for(link = 0; link < MAX_LINKS; link++) { for (link = 0; link < MAX_LINKS; link++) {
dev->link[link].dev = dev; dev->link[link].dev = dev;
dev->link[link].link = link; dev->link[link].link = link;
} }
/* By default devices are enabled */ /* By default devices are enabled */
dev->enabled = 1; dev->enabled = 1;
@ -118,10 +119,10 @@ static void read_resources(struct bus *bus)
struct device *curdev; struct device *curdev;
printk_spew("%s read_resources bus %d link: %d\n", printk_spew("%s read_resources bus %d link: %d\n",
dev_path(bus->dev), bus->secondary, bus->link); dev_path(bus->dev), bus->secondary, bus->link);
/* Walk through all of the devices and find which resources they need. */ /* Walk through all of the devices and find which resources they need. */
for(curdev = bus->children; curdev; curdev = curdev->sibling) { for (curdev = bus->children; curdev; curdev = curdev->sibling) {
unsigned links; unsigned links;
int i; int i;
if (curdev->have_resources) { if (curdev->have_resources) {
@ -139,7 +140,7 @@ static void read_resources(struct bus *bus)
curdev->have_resources = 1; curdev->have_resources = 1;
/* Read in subtractive resources behind the current device */ /* Read in subtractive resources behind the current device */
links = 0; links = 0;
for(i = 0; i < curdev->resources; i++) { for (i = 0; i < curdev->resources; i++) {
struct resource *resource; struct resource *resource;
unsigned link; unsigned link;
resource = &curdev->resource[i]; resource = &curdev->resource[i];
@ -148,7 +149,7 @@ static void read_resources(struct bus *bus)
link = IOINDEX_SUBTRACTIVE_LINK(resource->index); link = IOINDEX_SUBTRACTIVE_LINK(resource->index);
if (link > MAX_LINKS) { if (link > MAX_LINKS) {
printk_err("%s subtractive index on link: %d\n", printk_err("%s subtractive index on link: %d\n",
dev_path(curdev), link); dev_path(curdev), link);
continue; continue;
} }
if (!(links & (1 << link))) { if (!(links & (1 << link))) {
@ -159,7 +160,7 @@ static void read_resources(struct bus *bus)
} }
} }
printk_spew("%s read_resources bus %d link: %d done\n", printk_spew("%s read_resources bus %d link: %d done\n",
dev_path(bus->dev), bus->secondary, bus->link); dev_path(bus->dev), bus->secondary, bus->link);
} }
struct pick_largest_state { struct pick_largest_state {
@ -190,9 +191,9 @@ static void pick_largest_resource(void *gp,
return; return;
} }
if (!state->result || if (!state->result ||
(state->result->align < resource->align) || (state->result->align < resource->align) ||
((state->result->align == resource->align) && ((state->result->align == resource->align) &&
(state->result->size < resource->size))) { (state->result->size < resource->size))) {
state->result_dev = dev; state->result_dev = dev;
state->result = resource; state->result = resource;
} }
@ -257,11 +258,10 @@ void compute_allocate_resource(
base = bridge->base; base = bridge->base;
printk_spew("%s compute_allocate_%s: base: %08Lx size: %08Lx align: %d gran: %d\n", printk_spew("%s compute_allocate_%s: base: %08Lx size: %08Lx align: %d gran: %d\n",
dev_path(bus->dev), dev_path(bus->dev),
(bridge->flags & IORESOURCE_IO)? "io": (bridge->flags & IORESOURCE_IO)? "io":
(bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem", (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem",
base, bridge->size, bridge->align, bridge->gran); base, bridge->size, bridge->align, bridge->gran);
/* We want different minimum alignments for different kinds of /* We want different minimum alignments for different kinds of
* resources. These minimums are not device type specific * resources. These minimums are not device type specific
@ -283,14 +283,13 @@ void compute_allocate_resource(
/* Walk through all the devices on the current bus and /* Walk through all the devices on the current bus and
* compute the addresses. * compute the addresses.
*/ */
while((dev = largest_resource(bus, &resource, type_mask, type))) { while ((dev = largest_resource(bus, &resource, type_mask, type))) {
resource_t size; resource_t size;
/* Do NOT I repeat do not ignore resources which have zero size. /* Do NOT I repeat do not ignore resources which have zero size.
* If they need to be ignored dev->read_resources should not even * If they need to be ignored dev->read_resources should not even
* return them. Some resources must be set even when they have * return them. Some resources must be set even when they have
* no size. PCI bridge resources are a good example of this. * no size. PCI bridge resources are a good example of this.
*/ */
/* Propogate the resource alignment to the bridge register */ /* Propogate the resource alignment to the bridge register */
if (resource->align > bridge->align) { if (resource->align > bridge->align) {
bridge->align = resource->align; bridge->align = resource->align;
@ -339,14 +338,13 @@ void compute_allocate_resource(
resource->flags &= ~IORESOURCE_STORED; resource->flags &= ~IORESOURCE_STORED;
base += size; base += size;
printk_spew( printk_spew("%s %02x * [0x%08Lx - 0x%08Lx] %s\n",
"%s %02x * [0x%08Lx - 0x%08Lx] %s\n", dev_path(dev),
dev_path(dev), resource->index,
resource->index, resource->base,
resource->base, resource->base + resource->size - 1,
resource->base + resource->size - 1, (resource->flags & IORESOURCE_IO)? "io":
(resource->flags & IORESOURCE_IO)? "io": (resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem");
(resource->flags & IORESOURCE_PREFETCH)? "prefmem": "mem");
} }
} }
/* A pci bridge resource does not need to be a power /* A pci bridge resource does not need to be a power
@ -358,10 +356,10 @@ void compute_allocate_resource(
bridge->size = round(base, bridge->gran) - bridge->base; bridge->size = round(base, bridge->gran) - bridge->base;
printk_spew("%s compute_allocate_%s: base: %08Lx size: %08Lx align: %d gran: %d done\n", printk_spew("%s compute_allocate_%s: base: %08Lx size: %08Lx align: %d gran: %d done\n",
dev_path(bus->dev), dev_path(bus->dev),
(bridge->flags & IORESOURCE_IO)? "io": (bridge->flags & IORESOURCE_IO)? "io":
(bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem", (bridge->flags & IORESOURCE_PREFETCH)? "prefmem" : "mem",
base, bridge->size, bridge->align, bridge->gran); base, bridge->size, bridge->align, bridge->gran);
} }
@ -380,10 +378,6 @@ static void allocate_vga_resource(void)
if (((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) && if (((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
((dev->class >> 8) != PCI_CLASS_DISPLAY_OTHER)) { ((dev->class >> 8) != PCI_CLASS_DISPLAY_OTHER)) {
if (!vga) { if (!vga) {
printk_debug("Allocating VGA resource %s\n",
dev_path(dev));
printk_debug("parent of the vga device %s\n",
dev_path(dev->bus->dev));
vga = dev; vga = dev;
} }
if (vga == dev) { if (vga == dev) {
@ -400,8 +394,6 @@ static void allocate_vga_resource(void)
} }
/* Now walk up the bridges setting the VGA enable */ /* Now walk up the bridges setting the VGA enable */
while (bus) { while (bus) {
printk_info("Enabling VGA forward on bus connect to %s\n",
dev_path(bus->dev));
bus->bridge_ctrl |= PCI_BRIDGE_CTL_VGA; bus->bridge_ctrl |= PCI_BRIDGE_CTL_VGA;
bus = (bus == bus->dev->bus)? 0 : bus->dev->bus; bus = (bus == bus->dev->bus)? 0 : bus->dev->bus;
} }
@ -545,7 +537,7 @@ void dev_configure(void)
printk_info("Reading resources...\n"); printk_info("Reading resources...\n");
root->ops->read_resources(root); root->ops->read_resources(root);
printk_info("Done\n"); printk_info("Done reading resources.\n");
/* Get the resources */ /* Get the resources */
io = &root->resource[0]; io = &root->resource[0];
@ -567,13 +559,13 @@ void dev_configure(void)
/* Store the computed resource allocations into device registers ... */ /* Store the computed resource allocations into device registers ... */
printk_info("Setting resources...\n"); printk_info("Setting resources...\n");
root->ops->set_resources(root); root->ops->set_resources(root);
printk_info("Done\n"); printk_info("Done setting resources.\n");
#if 0 #if 0
mem->flags |= IORESOURCE_STORED; mem->flags |= IORESOURCE_STORED;
report_resource_stored(root, mem, ""); report_resource_stored(root, mem, "");
#endif #endif
printk_info("done.\n"); printk_info("Done allocating resources.\n");
} }
/** /**

View File

@ -117,7 +117,7 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
/* If it is a 64bit resource look at the high half as well */ /* If it is a 64bit resource look at the high half as well */
if (((attr & PCI_BASE_ADDRESS_SPACE_IO) == 0) && if (((attr & PCI_BASE_ADDRESS_SPACE_IO) == 0) &&
((attr & PCI_BASE_ADDRESS_MEM_LIMIT_MASK) == PCI_BASE_ADDRESS_MEM_LIMIT_64)) ((attr & PCI_BASE_ADDRESS_MEM_LIMIT_MASK) == PCI_BASE_ADDRESS_MEM_LIMIT_64))
{ {
/* Find the high bits that move */ /* Find the high bits that move */
moving |= ((resource_t)pci_moving_config32(dev, index + 4)) << 32; moving |= ((resource_t)pci_moving_config32(dev, index + 4)) << 32;
@ -611,13 +611,14 @@ static void set_pci_ops(struct device *dev)
* @brief See if we have already allocated a device structure for a given devfn. * @brief See if we have already allocated a device structure for a given devfn.
* *
* Given a linked list of PCI device structures and a devfn number, find the * Given a linked list of PCI device structures and a devfn number, find the
* device structure correspond to the devfn, if present. * device structure correspond to the devfn, if present. This function also
* removes the device structure from the linked list.
* *
* @param list the device structure list * @param list the device structure list
* @param devfn a device/function number * @param devfn a device/function number
* *
* @return pointer to the device structure found or null of we have not allocated * @return pointer to the device structure found or null of we have not
* a device for this devfn yet. * allocated a device for this devfn yet.
*/ */
static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn) static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn)
{ {
@ -626,7 +627,7 @@ static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn)
for(; *list; list = &(*list)->sibling) { for(; *list; list = &(*list)->sibling) {
if ((*list)->path.type != DEVICE_PATH_PCI) { if ((*list)->path.type != DEVICE_PATH_PCI) {
printk_err("child %s not a pci device\n", printk_err("child %s not a pci device\n",
dev_path(*list)); dev_path(*list));
continue; continue;
} }
if ((*list)->path.u.pci.devfn == devfn) { if ((*list)->path.u.pci.devfn == devfn) {
@ -637,15 +638,15 @@ static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn)
break; break;
} }
} }
/* Just like alloc_dev add the device to the /* Just like alloc_dev add the device to the list of device on the bus.
* list of device on the bus. When the list of devices was formed * When the list of devices was formed we removed all of the parents
* we removed all of the parents children, and now we are interleaving * children, and now we are interleaving static and dynamic devices in
* static and dynamic devices in order on the bus. * order on the bus.
*/ */
if (dev) { if (dev) {
device_t child; device_t child;
/* Find the last child of our parent */ /* Find the last child of our parent */
for(child = dev->bus->children; child && child->sibling; ) { for (child = dev->bus->children; child && child->sibling; ) {
child = child->sibling; child = child->sibling;
} }
/* Place the device on the list of children of it's parent. */ /* Place the device on the list of children of it's parent. */
@ -854,6 +855,8 @@ unsigned int pci_scan_bridge(struct device *dev, unsigned int max)
uint32_t buses; uint32_t buses;
uint16_t cr; uint16_t cr;
printk_spew("%s for %s\n", __func__, dev_path(dev));
bus = &dev->link[0]; bus = &dev->link[0];
bus->dev = dev; bus->dev = dev;
dev->links = 1; dev->links = 1;
@ -882,15 +885,15 @@ unsigned int pci_scan_bridge(struct device *dev, unsigned int max)
*/ */
buses &= 0xff000000; buses &= 0xff000000;
buses |= (((unsigned int) (dev->bus->secondary) << 0) | buses |= (((unsigned int) (dev->bus->secondary) << 0) |
((unsigned int) (bus->secondary) << 8) | ((unsigned int) (bus->secondary) << 8) |
((unsigned int) (bus->subordinate) << 16)); ((unsigned int) (bus->subordinate) << 16));
pci_write_config32(dev, PCI_PRIMARY_BUS, buses); pci_write_config32(dev, PCI_PRIMARY_BUS, buses);
/* Now we can scan all subordinate buses /* Now we can scan all subordinate buses
* i.e. the bus behind the bridge. * i.e. the bus behind the bridge.
*/ */
max = pci_scan_bus(bus, 0x00, 0xff, max); max = pci_scan_bus(bus, 0x00, 0xff, max);
/* We know the number of buses behind this bridge. Set the subordinate /* We know the number of buses behind this bridge. Set the subordinate
* bus number to its real value. * bus number to its real value.
*/ */
@ -899,7 +902,7 @@ unsigned int pci_scan_bridge(struct device *dev, unsigned int max)
((unsigned int) (bus->subordinate) << 16); ((unsigned int) (bus->subordinate) << 16);
pci_write_config32(dev, PCI_PRIMARY_BUS, buses); pci_write_config32(dev, PCI_PRIMARY_BUS, buses);
pci_write_config16(dev, PCI_COMMAND, cr); pci_write_config16(dev, PCI_COMMAND, cr);
printk_spew("%s returns max %d\n", __func__, max); printk_spew("%s returns max %d\n", __func__, max);
return max; return max;
} }

View File

@ -89,9 +89,8 @@ unsigned int scan_static_bus(device_t root, unsigned int max)
if (child->ops && child->ops->enable) { if (child->ops && child->ops->enable) {
child->ops->enable(child); child->ops->enable(child);
} }
printk_debug("%s %s\n", printk_debug("%s %s\n", dev_path(child),
dev_path(child), child->enabled?"enabled": "disabled");
child->enabled?"enabled": "disabled");
} }
} }
for (link = 0; link < root->links; link++) { for (link = 0; link < root->links; link++) {

View File

@ -22,7 +22,7 @@ static device_t __f1_dev[FX_DEVS];
static void debug_fx_devs(void) static void debug_fx_devs(void)
{ {
int i; int i;
for(i = 0; i < FX_DEVS; i++) { for (i = 0; i < FX_DEVS; i++) {
device_t dev; device_t dev;
dev = __f0_dev[i]; dev = __f0_dev[i];
if (dev) { if (dev) {
@ -44,7 +44,7 @@ static void get_fx_devs(void)
if (__f1_dev[0]) { if (__f1_dev[0]) {
return; return;
} }
for(i = 0; i < FX_DEVS; i++) { for (i = 0; i < FX_DEVS; i++) {
__f0_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 0)); __f0_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 0));
__f1_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 1)); __f1_dev[i] = dev_find_slot(0, PCI_DEVFN(0x18 + i, 1));
} }
@ -63,7 +63,7 @@ static void f1_write_config32(unsigned reg, uint32_t value)
{ {
int i; int i;
get_fx_devs(); get_fx_devs();
for(i = 0; i < FX_DEVS; i++) { for (i = 0; i < FX_DEVS; i++) {
device_t dev; device_t dev;
dev = __f1_dev[i]; dev = __f1_dev[i];
if (dev && dev->enabled) { if (dev && dev->enabled) {
@ -84,9 +84,9 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
nodeid = amdk8_nodeid(dev); nodeid = amdk8_nodeid(dev);
#if 0 #if 0
printk_debug("%s amdk8_scan_chains max: %d starting...\n", printk_debug("%s amdk8_scan_chains max: %d starting...\n",
dev_path(dev), max); dev_path(dev), max);
#endif #endif
for(link = 0; link < dev->links; link++) { for (link = 0; link < dev->links; link++) {
uint32_t link_type; uint32_t link_type;
uint32_t busses, config_busses; uint32_t busses, config_busses;
unsigned free_reg, config_reg; unsigned free_reg, config_reg;
@ -103,9 +103,10 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
if (!(link_type & NonCoherent)) { if (!(link_type & NonCoherent)) {
continue; continue;
} }
/* See if there is an available configuration space mapping register in function 1. */ /* See if there is an available configuration space mapping
* register in function 1. */
free_reg = 0; free_reg = 0;
for(config_reg = 0xe0; config_reg <= 0xec; config_reg += 4) { for (config_reg = 0xe0; config_reg <= 0xec; config_reg += 4) {
uint32_t config; uint32_t config;
config = f1_read_config32(config_reg); config = f1_read_config32(config_reg);
if (!free_reg && ((config & 3) == 0)) { if (!free_reg && ((config & 3) == 0)) {
@ -113,22 +114,23 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
continue; continue;
} }
if (((config & 3) == 3) && if (((config & 3) == 3) &&
(((config >> 4) & 7) == nodeid) && (((config >> 4) & 7) == nodeid) &&
(((config >> 8) & 3) == link)) { (((config >> 8) & 3) == link)) {
break; break;
} }
} }
if (free_reg && (config_reg > 0xec)) { if (free_reg && (config_reg > 0xec)) {
config_reg = free_reg; config_reg = free_reg;
} }
/* If we can't find an available configuration space mapping register skip this bus */ /* If we can't find an available configuration space mapping
* register skip this bus */
if (config_reg > 0xec) { if (config_reg > 0xec) {
continue; continue;
} }
/* Set up the primary, secondary and subordinate bus numbers. We have /* Set up the primary, secondary and subordinate bus numbers.
* no idea how many busses are behind this bridge yet, so we set the subordinate * We have no idea how many busses are behind this bridge yet,
* bus number to 0xff for the moment. * so we set the subordinate bus number to 0xff for the moment.
*/ */
dev->link[link].secondary = ++max; dev->link[link].secondary = ++max;
dev->link[link].subordinate = 0xff; dev->link[link].subordinate = 0xff;
@ -138,15 +140,15 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
*/ */
busses = pci_read_config32(dev, dev->link[link].cap + 0x14); busses = pci_read_config32(dev, dev->link[link].cap + 0x14);
config_busses = f1_read_config32(config_reg); config_busses = f1_read_config32(config_reg);
/* Configure the bus numbers for this bridge: the configuration /* Configure the bus numbers for this bridge: the configuration
* transactions will not be propagates by the bridge if it is not * transactions will not be propagates by the bridge if it is
* correctly configured * not correctly configured
*/ */
busses &= 0xff000000; busses &= 0xff000000;
busses |= (((unsigned int)(dev->bus->secondary) << 0) | busses |= (((unsigned int)(dev->bus->secondary) << 0) |
((unsigned int)(dev->link[link].secondary) << 8) | ((unsigned int)(dev->link[link].secondary) << 8) |
((unsigned int)(dev->link[link].subordinate) << 16)); ((unsigned int)(dev->link[link].subordinate) << 16));
pci_write_config32(dev, dev->link[link].cap + 0x14, busses); pci_write_config32(dev, dev->link[link].cap + 0x14, busses);
config_busses &= 0x000fc88; config_busses &= 0x000fc88;
@ -161,29 +163,31 @@ static unsigned int amdk8_scan_chains(device_t dev, unsigned int max)
#if 0 #if 0
printk_debug("%s Hyper transport scan link: %d max: %d\n", printk_debug("%s Hyper transport scan link: %d max: %d\n",
dev_path(dev), link, max); dev_path(dev), link, max);
#endif #endif
/* Now we can scan all of the subordinate busses i.e. the chain on the hypertranport link */ /* Now we can scan all of the subordinate busses i.e. the
* chain on the hypertranport link */
max = hypertransport_scan_chain(&dev->link[link], max); max = hypertransport_scan_chain(&dev->link[link], max);
#if 0 #if 0
printk_debug("%s Hyper transport scan link: %d new max: %d\n", printk_debug("%s Hyper transport scan link: %d new max: %d\n",
dev_path(dev), link, max); dev_path(dev), link, max);
#endif #endif
/* We know the number of busses behind this bridge. Set the subordinate /* We know the number of busses behind this bridge. Set the
* bus number to it's real value * subordinate bus number to it's real value
*/ */
dev->link[link].subordinate = max; dev->link[link].subordinate = max;
busses = (busses & 0xff00ffff) | busses = (busses & 0xff00ffff) |
((unsigned int) (dev->link[link].subordinate) << 16); ((unsigned int) (dev->link[link].subordinate) << 16);
pci_write_config32(dev, dev->link[link].cap + 0x14, busses); pci_write_config32(dev, dev->link[link].cap + 0x14, busses);
config_busses = (config_busses & 0x00ffffff) | (dev->link[link].subordinate << 24); config_busses = (config_busses & 0x00ffffff) |
(dev->link[link].subordinate << 24);
f1_write_config32(config_reg, config_busses); f1_write_config32(config_reg, config_busses);
#if 0 #if 0
printk_debug("%s Hypertransport scan link: %d done\n", printk_debug("%s Hypertransport scan link: %d done\n",
dev_path(dev), link); dev_path(dev), link);
#endif #endif
} }
#if 0 #if 0
printk_debug("%s amdk8_scan_chains max: %d done\n", printk_debug("%s amdk8_scan_chains max: %d done\n",
@ -199,39 +203,38 @@ static int reg_useable(unsigned reg,
unsigned nodeid, link; unsigned nodeid, link;
int result; int result;
res = 0; res = 0;
for(nodeid = 0; !res && (nodeid < 8); nodeid++) { for (nodeid = 0; !res && (nodeid < 8); nodeid++) {
device_t dev; device_t dev;
dev = __f0_dev[nodeid]; dev = __f0_dev[nodeid];
for(link = 0; !res && (link < 3); link++) { for (link = 0; !res && (link < 3); link++) {
res = probe_resource(dev, 0x100 + (reg | link)); res = probe_resource(dev, 0x100 + (reg | link));
} }
} }
result = 2; result = 2;
if (res) { if (res) {
result = 0; result = 0;
if ( (goal_link == (link - 1)) && if ((goal_link == (link - 1)) &&
(goal_nodeid == (nodeid - 1)) && (goal_nodeid == (nodeid - 1)) &&
(res->flags <= 1)) { (res->flags <= 1)) {
result = 1; result = 1;
} }
} }
#if 0 #if 0
printk_debug("reg: %02x result: %d gnodeid: %u glink: %u nodeid: %u link: %u\n", printk_debug("reg: %02x result: %d gnodeid: %u glink: %u nodeid: %u link: %u\n",
reg, result, reg, result,
goal_nodeid, goal_link, goal_nodeid, goal_link,
nodeid, link); nodeid, link);
#endif #endif
return result; return result;
} }
static struct resource *amdk8_find_iopair(device_t dev, unsigned nodeid, unsigned link) static struct resource *amdk8_find_iopair(device_t dev, unsigned nodeid, unsigned link)
{ {
struct resource *resource; struct resource *resource;
unsigned free_reg, reg; unsigned free_reg, reg;
resource = 0; resource = 0;
free_reg = 0; free_reg = 0;
for(reg = 0xc0; reg <= 0xd8; reg += 0x8) { for (reg = 0xc0; reg <= 0xd8; reg += 0x8) {
int result; int result;
result = reg_useable(reg, dev, nodeid, link); result = reg_useable(reg, dev, nodeid, link);
if (result == 1) { if (result == 1) {
@ -258,7 +261,7 @@ static struct resource *amdk8_find_mempair(device_t dev, unsigned nodeid, unsign
unsigned free_reg, reg; unsigned free_reg, reg;
resource = 0; resource = 0;
free_reg = 0; free_reg = 0;
for(reg = 0x80; reg <= 0xb8; reg += 0x8) { for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
int result; int result;
result = reg_useable(reg, dev, nodeid, link); result = reg_useable(reg, dev, nodeid, link);
if (result == 1) { if (result == 1) {
@ -278,6 +281,7 @@ static struct resource *amdk8_find_mempair(device_t dev, unsigned nodeid, unsign
} }
return resource; return resource;
} }
static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link) static void amdk8_link_read_bases(device_t dev, unsigned nodeid, unsigned link)
{ {
struct resource *resource; struct resource *resource;
@ -328,7 +332,7 @@ static void amdk8_read_resources(device_t dev)
{ {
unsigned nodeid, link; unsigned nodeid, link;
nodeid = amdk8_nodeid(dev); nodeid = amdk8_nodeid(dev);
for(link = 0; link < dev->links; link++) { for (link = 0; link < dev->links; link++) {
if (dev->link[link].children) { if (dev->link[link].children) {
amdk8_link_read_bases(dev, nodeid, link); amdk8_link_read_bases(dev, nodeid, link);
} }
@ -416,6 +420,26 @@ static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned
report_resource_stored(dev, resource, buf); report_resource_stored(dev, resource, buf);
} }
static void amdk8_create_vga_resource(device_t dev, unsigned nodeid)
{
struct resource *resource;
unsigned link;
for (link = 0; link < dev->links; link++) {
if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
printk_info("%s: bridge on link %d has VGA device\n",
dev_path(dev), link);
printk_info("creating MEM pair for VGA memory\n");
/* Initialize the io space constraints on the current bus */
resource = amdk8_find_mempair(dev, nodeid, link);
printk_info("MEM pair register %x\n", resource->index - 0x100);
resource->base = 0xa0000;
resource->size = 0x00000;
resource->gran = 16;
resource->align = 16;
resource->flags = IORESOURCE_PREFETCH | IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_ASSIGNED;
}
}
}
static void amdk8_set_resources(device_t dev) static void amdk8_set_resources(device_t dev)
{ {
unsigned nodeid, link; unsigned nodeid, link;
@ -424,8 +448,10 @@ static void amdk8_set_resources(device_t dev)
/* Find the nodeid */ /* Find the nodeid */
nodeid = amdk8_nodeid(dev); nodeid = amdk8_nodeid(dev);
amdk8_create_vga_resource(dev, nodeid);
/* Set each resource we have found */ /* Set each resource we have found */
for(i = 0; i < dev->resources; i++) { for (i = 0; i < dev->resources; i++) {
amdk8_set_resource(dev, &dev->resource[i], nodeid); amdk8_set_resource(dev, &dev->resource[i], nodeid);
} }

View File

@ -84,7 +84,7 @@ static void setup_ioapic(void)
return; return;
} }
printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n",
a->reg, a->value_low, a->value_high); a->reg, a->value_low, a->value_high);
} }
} }
@ -176,15 +176,16 @@ static void amd8111_lpc_enable_resources(device_t dev)
enable_childrens_resources(dev); enable_childrens_resources(dev);
} }
static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device) static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
{ {
pci_write_config32(dev, 0x70, pci_write_config32(dev, 0x70,
((device & 0xffff) << 16) | (vendor & 0xffff)); ((device & 0xffff) << 16) | (vendor & 0xffff));
} }
static struct pci_operations lops_pci = { static struct pci_operations lops_pci = {
.set_subsystem = lpci_set_subsystem, .set_subsystem = lpci_set_subsystem,
}; };
static struct device_operations lpc_ops = { static struct device_operations lpc_ops = {
.read_resources = amd8111_lpc_read_resources, .read_resources = amd8111_lpc_read_resources,
.set_resources = pci_dev_set_resources, .set_resources = pci_dev_set_resources,