- First stab at getting the ppc ports building and working.
- The sandpointx3+altimus has been consolidated into one directory for now. - Added support for having different versions of the pci access functions on a per bus basis if needed. Hopefully I have not broken something inadvertently. git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1786 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
@@ -315,7 +315,6 @@ static void build_lb_mem_range(void *gp, struct device *dev, struct resource *re
|
||||
static struct lb_memory *build_lb_mem(struct lb_header *head)
|
||||
{
|
||||
struct lb_memory *mem;
|
||||
struct device *dev;
|
||||
|
||||
/* Record where the lb memory ranges will live */
|
||||
mem = lb_memory(head);
|
||||
@@ -343,7 +342,7 @@ unsigned long write_linuxbios_table(
|
||||
struct lb_record *rec_dest, *rec_src;
|
||||
/* Write the option config table... */
|
||||
rec_dest = lb_new_record(head);
|
||||
rec_src = (struct lb_record *)&option_table;
|
||||
rec_src = (struct lb_record *)(void *)&option_table;
|
||||
memcpy(rec_dest, rec_src, rec_src->size);
|
||||
}
|
||||
/* Record where RAM is located */
|
||||
|
@@ -1,18 +1,9 @@
|
||||
#ifndef ARCH_I386_PCI_OPS_H
|
||||
#define ARCH_I386_PCI_OPS_H
|
||||
|
||||
struct pci_ops {
|
||||
uint8_t (*read8) (uint8_t bus, int devfn, int where);
|
||||
uint16_t (*read16) (uint8_t bus, int devfn, int where);
|
||||
uint32_t (*read32) (uint8_t bus, int devfn, int where);
|
||||
void (*write8) (uint8_t bus, int devfn, int where, uint8_t val);
|
||||
void (*write16) (uint8_t bus, int devfn, int where, uint16_t val);
|
||||
void (*write32) (uint8_t bus, int devfn, int where, uint32_t val);
|
||||
};
|
||||
extern const struct pci_ops *conf;
|
||||
const struct pci_bus_operations pci_cf8_conf1;
|
||||
const struct pci_bus_operations pci_cf8_conf2;
|
||||
|
||||
void pci_set_method_conf1(void);
|
||||
void pci_set_method_conf2(void);
|
||||
void pci_set_method(void);
|
||||
void pci_set_method(device_t dev);
|
||||
|
||||
#endif /* ARCH_I386_PCI_OPS_H */
|
||||
|
@@ -6,7 +6,7 @@
|
||||
#option CONFIG_PCIBIOS_IRQ=0
|
||||
object c_start.S
|
||||
object cpu.c
|
||||
object pci_ops.c
|
||||
#object pci_ops.c
|
||||
object pci_ops_conf1.c
|
||||
object pci_ops_conf2.c
|
||||
object pci_ops_auto.c
|
||||
|
@@ -420,7 +420,7 @@ void x86_exception(struct eregs *info)
|
||||
if ( parse_ulong(&ptr, &addr) &&
|
||||
(*ptr++ == ',') &&
|
||||
parse_ulong(&ptr, &length)) {
|
||||
copy_to_hex(out_buffer, addr, length);
|
||||
copy_to_hex(out_buffer, (void *)addr, length);
|
||||
} else {
|
||||
memcpy(out_buffer, "E01", 4);
|
||||
}
|
||||
|
@@ -1,60 +0,0 @@
|
||||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <arch/pciconf.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <device/pci_ops.h>
|
||||
|
||||
const struct pci_ops *conf = 0;
|
||||
|
||||
/*
|
||||
* Direct access to PCI hardware...
|
||||
*/
|
||||
|
||||
uint8_t pci_read_config8(device_t dev, unsigned where)
|
||||
{
|
||||
uint8_t value;
|
||||
value = conf->read8(dev->bus->secondary, dev->path.u.pci.devfn, where);
|
||||
printk_spew("Read config 8 bus %d,devfn 0x%x,reg 0x%x,val 0x%x\n",
|
||||
dev->bus->secondary, dev->path.u.pci.devfn, where, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint16_t pci_read_config16(device_t dev, unsigned where)
|
||||
{
|
||||
uint16_t value;
|
||||
value = conf->read16(dev->bus->secondary, dev->path.u.pci.devfn, where);
|
||||
printk_spew( "Read config 16 bus %d,devfn 0x%x,reg 0x%x,val 0x%x\n",
|
||||
dev->bus->secondary, dev->path.u.pci.devfn, where, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t pci_read_config32(device_t dev, unsigned where)
|
||||
{
|
||||
uint32_t value;
|
||||
value = conf->read32(dev->bus->secondary, dev->path.u.pci.devfn, where);
|
||||
printk_spew( "Read config 32 bus %d,devfn 0x%x,reg 0x%x,val 0x%x\n",
|
||||
dev->bus->secondary, dev->path.u.pci.devfn, where, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
void pci_write_config8(device_t dev, unsigned where, uint8_t val)
|
||||
{
|
||||
printk_spew( "Write config 8 bus %d, devfn 0x%x, reg 0x%x, val 0x%x\n",
|
||||
dev->bus->secondary, dev->path.u.pci.devfn, where, val);
|
||||
conf->write8(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
|
||||
}
|
||||
|
||||
void pci_write_config16(device_t dev, unsigned where, uint16_t val)
|
||||
{
|
||||
printk_spew( "Write config 16 bus %d, devfn 0x%x, reg 0x%x, val 0x%x\n",
|
||||
dev->bus->secondary, dev->path.u.pci.devfn, where, val);
|
||||
conf->write16(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
|
||||
}
|
||||
|
||||
void pci_write_config32(device_t dev, unsigned where, uint32_t val)
|
||||
{
|
||||
printk_spew( "Write config 32 bus %d, devfn 0x%x, reg 0x%x, val 0x%x\n",
|
||||
dev->bus->secondary, dev->path.u.pci.devfn, where, val);
|
||||
conf->write32(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
|
||||
}
|
@@ -1,3 +1,4 @@
|
||||
#include <stddef.h>
|
||||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <arch/pciconf.h>
|
||||
@@ -15,11 +16,12 @@
|
||||
* This should be close to trivial, but it isn't, because there are buggy
|
||||
* chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
|
||||
*/
|
||||
static int pci_sanity_check(const struct pci_ops *o)
|
||||
static int pci_sanity_check(const struct pci_bus_operations *o)
|
||||
{
|
||||
uint16_t class, vendor;
|
||||
uint8_t bus;
|
||||
unsigned bus;
|
||||
int devfn;
|
||||
struct bus pbus; /* Dummy device */
|
||||
#define PCI_CLASS_BRIDGE_HOST 0x0600
|
||||
#define PCI_CLASS_DISPLAY_VGA 0x0300
|
||||
#define PCI_VENDOR_ID_COMPAQ 0x0e11
|
||||
@@ -27,8 +29,8 @@ static int pci_sanity_check(const struct pci_ops *o)
|
||||
#define PCI_VENDOR_ID_MOTOROLA 0x1057
|
||||
|
||||
for (bus = 0, devfn = 0; devfn < 0x100; devfn++) {
|
||||
class = o->read16(bus, devfn, PCI_CLASS_DEVICE);
|
||||
vendor = o->read16(bus, devfn, PCI_VENDOR_ID);
|
||||
class = o->read16(&pbus, bus, devfn, PCI_CLASS_DEVICE);
|
||||
vendor = o->read16(&pbus, bus, devfn, PCI_VENDOR_ID);
|
||||
if (((class == PCI_CLASS_BRIDGE_HOST) || (class == PCI_CLASS_DISPLAY_VGA)) ||
|
||||
((vendor == PCI_VENDOR_ID_INTEL) || (vendor == PCI_VENDOR_ID_COMPAQ) ||
|
||||
(vendor == PCI_VENDOR_ID_MOTOROLA))) {
|
||||
@@ -39,7 +41,7 @@ static int pci_sanity_check(const struct pci_ops *o)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_check_direct(void)
|
||||
const struct pci_bus_operations *pci_check_direct(void)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
@@ -50,13 +52,12 @@ static void pci_check_direct(void)
|
||||
outb(0x01, 0xCFB);
|
||||
tmp = inl(0xCF8);
|
||||
outl(0x80000000, 0xCF8);
|
||||
if (inl(0xCF8) == 0x80000000) {
|
||||
pci_set_method_conf1();
|
||||
if (pci_sanity_check(conf)) {
|
||||
outl(tmp, 0xCF8);
|
||||
printk_debug("PCI: Using configuration type 1\n");
|
||||
return;
|
||||
}
|
||||
if ((inl(0xCF8) == 0x80000000) &&
|
||||
pci_sanity_check(&pci_cf8_conf1))
|
||||
{
|
||||
outl(tmp, 0xCF8);
|
||||
printk_debug("PCI: Using configuration type 1\n");
|
||||
return &pci_cf8_conf1;
|
||||
}
|
||||
outl(tmp, 0xCF8);
|
||||
}
|
||||
@@ -68,25 +69,23 @@ static void pci_check_direct(void)
|
||||
outb(0x00, 0xCFB);
|
||||
outb(0x00, 0xCF8);
|
||||
outb(0x00, 0xCFA);
|
||||
if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00) {
|
||||
pci_set_method_conf2();
|
||||
if (pci_sanity_check(conf)) {
|
||||
printk_debug("PCI: Using configuration type 2\n");
|
||||
}
|
||||
if ((inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00) &&
|
||||
pci_sanity_check(&pci_cf8_conf2))
|
||||
{
|
||||
printk_debug("PCI: Using configuration type 2\n");
|
||||
return &pci_cf8_conf2;
|
||||
}
|
||||
}
|
||||
|
||||
printk_debug("pci_check_direct failed\n");
|
||||
conf = 0;
|
||||
|
||||
return;
|
||||
die("pci_check_direct failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Set the method to be used for PCI, type I or type II
|
||||
*/
|
||||
void pci_set_method(void)
|
||||
void pci_set_method(device_t dev)
|
||||
{
|
||||
printk_info("Finding PCI configuration type.\n");
|
||||
pci_check_direct();
|
||||
dev->ops->ops_pci_bus = pci_check_direct();
|
||||
post_code(0x5f);
|
||||
}
|
||||
|
@@ -10,37 +10,37 @@
|
||||
|
||||
#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3))
|
||||
|
||||
static uint8_t pci_conf1_read_config8(unsigned char bus, int devfn, int where)
|
||||
static uint8_t pci_conf1_read_config8(struct bus *pbus, unsigned char bus, int devfn, int where)
|
||||
{
|
||||
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
|
||||
return inb(0xCFC + (where & 3));
|
||||
}
|
||||
|
||||
static uint16_t pci_conf1_read_config16(unsigned char bus, int devfn, int where)
|
||||
static uint16_t pci_conf1_read_config16(struct bus *pbus, unsigned char bus, int devfn, int where)
|
||||
{
|
||||
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
|
||||
return inw(0xCFC + (where & 2));
|
||||
}
|
||||
|
||||
static uint32_t pci_conf1_read_config32(unsigned char bus, int devfn, int where)
|
||||
static uint32_t pci_conf1_read_config32(struct bus *pbus, unsigned char bus, int devfn, int where)
|
||||
{
|
||||
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
|
||||
return inl(0xCFC);
|
||||
}
|
||||
|
||||
static void pci_conf1_write_config8(unsigned char bus, int devfn, int where, uint8_t value)
|
||||
static void pci_conf1_write_config8(struct bus *pbus, unsigned char bus, int devfn, int where, uint8_t value)
|
||||
{
|
||||
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
|
||||
outb(value, 0xCFC + (where & 3));
|
||||
}
|
||||
|
||||
static void pci_conf1_write_config16(unsigned char bus, int devfn, int where, uint16_t value)
|
||||
static void pci_conf1_write_config16(struct bus *pbus, unsigned char bus, int devfn, int where, uint16_t value)
|
||||
{
|
||||
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
|
||||
outw(value, 0xCFC + (where & 2));
|
||||
}
|
||||
|
||||
static void pci_conf1_write_config32(unsigned char bus, int devfn, int where, uint32_t value)
|
||||
static void pci_conf1_write_config32(struct bus *pbus, unsigned char bus, int devfn, int where, uint32_t value)
|
||||
{
|
||||
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
|
||||
outl(value, 0xCFC);
|
||||
@@ -48,7 +48,7 @@ static void pci_conf1_write_config32(unsigned char bus, int devfn, int where, ui
|
||||
|
||||
#undef CONFIG_CMD
|
||||
|
||||
static const struct pci_ops pci_direct_conf1 =
|
||||
const struct pci_bus_operations pci_cf8_conf1 =
|
||||
{
|
||||
.read8 = pci_conf1_read_config8,
|
||||
.read16 = pci_conf1_read_config16,
|
||||
@@ -57,8 +57,3 @@ static const struct pci_ops pci_direct_conf1 =
|
||||
.write16 = pci_conf1_write_config16,
|
||||
.write32 = pci_conf1_write_config32,
|
||||
};
|
||||
|
||||
void pci_set_method_conf1(void)
|
||||
{
|
||||
conf = &pci_direct_conf1;
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
#define FUNC(devfn) (((devfn & 7) << 1) | 0xf0)
|
||||
#define SET(bus,devfn) outb(FUNC(devfn), 0xCF8); outb(bus, 0xCFA);
|
||||
|
||||
static uint8_t pci_conf2_read_config8(unsigned char bus, int devfn, int where)
|
||||
static uint8_t pci_conf2_read_config8(struct bus *pbus, unsigned char bus, int devfn, int where)
|
||||
{
|
||||
uint8_t value;
|
||||
SET(bus, devfn);
|
||||
@@ -21,7 +21,7 @@ static uint8_t pci_conf2_read_config8(unsigned char bus, int devfn, int where)
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint16_t pci_conf2_read_config16(unsigned char bus, int devfn, int where)
|
||||
static uint16_t pci_conf2_read_config16(struct bus *pbus, unsigned char bus, int devfn, int where)
|
||||
{
|
||||
uint16_t value;
|
||||
SET(bus, devfn);
|
||||
@@ -30,7 +30,7 @@ static uint16_t pci_conf2_read_config16(unsigned char bus, int devfn, int where)
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint32_t pci_conf2_read_config32(unsigned char bus, int devfn, int where)
|
||||
static uint32_t pci_conf2_read_config32(struct bus *pbus, unsigned char bus, int devfn, int where)
|
||||
{
|
||||
uint32_t value;
|
||||
SET(bus, devfn);
|
||||
@@ -39,21 +39,21 @@ static uint32_t pci_conf2_read_config32(unsigned char bus, int devfn, int where)
|
||||
return value;
|
||||
}
|
||||
|
||||
static void pci_conf2_write_config8(unsigned char bus, int devfn, int where, uint8_t value)
|
||||
static void pci_conf2_write_config8(struct bus *pbus, unsigned char bus, int devfn, int where, uint8_t value)
|
||||
{
|
||||
SET(bus, devfn);
|
||||
outb(value, IOADDR(devfn, where));
|
||||
outb(0, 0xCF8);
|
||||
}
|
||||
|
||||
static void pci_conf2_write_config16(unsigned char bus, int devfn, int where, uint16_t value)
|
||||
static void pci_conf2_write_config16(struct bus *pbus, unsigned char bus, int devfn, int where, uint16_t value)
|
||||
{
|
||||
SET(bus, devfn);
|
||||
outw(value, IOADDR(devfn, where));
|
||||
outb(0, 0xCF8);
|
||||
}
|
||||
|
||||
static void pci_conf2_write_config32(unsigned char bus, int devfn, int where, uint32_t value)
|
||||
static void pci_conf2_write_config32(struct bus *pbus, unsigned char bus, int devfn, int where, uint32_t value)
|
||||
{
|
||||
SET(bus, devfn);
|
||||
outl(value, IOADDR(devfn, where));
|
||||
@@ -64,7 +64,7 @@ static void pci_conf2_write_config32(unsigned char bus, int devfn, int where, ui
|
||||
#undef IOADDR
|
||||
#undef FUNC
|
||||
|
||||
static const struct pci_ops pci_direct_conf2 =
|
||||
const struct pci_bus_operations pci_cf8_conf2 =
|
||||
{
|
||||
.read8 = pci_conf2_read_config8,
|
||||
.read16 = pci_conf2_read_config16,
|
||||
@@ -74,7 +74,3 @@ static const struct pci_ops pci_direct_conf2 =
|
||||
.write32 = pci_conf2_write_config32,
|
||||
};
|
||||
|
||||
void pci_set_method_conf2(void)
|
||||
{
|
||||
conf = &pci_direct_conf2;
|
||||
}
|
||||
|
@@ -1,3 +1,60 @@
|
||||
#ifndef ARCH_CPU_H
|
||||
#define ARCH_CPU_H
|
||||
/*
|
||||
* this should probably integrate code from src/arch/ppc/lib/cpuid.c
|
||||
*/
|
||||
|
||||
struct cpu_device_id {
|
||||
unsigned pvr;
|
||||
};
|
||||
|
||||
struct cpu_driver {
|
||||
struct device_operations *ops;
|
||||
struct cpu_device_id *id_table;
|
||||
};
|
||||
|
||||
#ifndef STACK_SIZE
|
||||
#error STACK_SIZE not defined
|
||||
#endif
|
||||
|
||||
/* The basic logic comes from the Linux kernel.
|
||||
* The invariant is that (1 << 31 - STACK_BITS) == STACK_SIZE
|
||||
* I wish there was simpler way to support multiple stack sizes.
|
||||
* Oh well.
|
||||
*/
|
||||
#if STACK_SIZE == 4096
|
||||
#define STACK_BITS "19"
|
||||
#elif STACK_SIZE == 8192
|
||||
#define STACK_BITS "18"
|
||||
#elif STACK_SIZE == 16384
|
||||
#define STACK_BITS "17"
|
||||
#elif STACK_SIZE == 32768
|
||||
#define STACK_BITS "16"
|
||||
#elif STACK_SIZE == 65536
|
||||
#define STACK_BITS "15"
|
||||
#else
|
||||
#error Unimplemented stack size
|
||||
#endif
|
||||
|
||||
|
||||
struct cpu_info {
|
||||
struct device *cpu;
|
||||
unsigned long index;
|
||||
};
|
||||
|
||||
|
||||
static inline struct cpu_info *cpu_info(void)
|
||||
{
|
||||
struct cpu_info *ci;
|
||||
__asm__("rlwinm %0,1,0,0," STACK_BITS : "=r"(ci));
|
||||
return ci;
|
||||
}
|
||||
|
||||
static inline unsigned long cpu_index(void)
|
||||
{
|
||||
struct cpu_info *ci;
|
||||
ci = cpu_info();
|
||||
return ci->index;
|
||||
}
|
||||
|
||||
#endif /* ARCH_CPU_H */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#ifndef ARCH_I386_PCI_OPS_H
|
||||
#define ARCH_I386_PCI_OPS_H
|
||||
#ifndef ARCH_PPC_PCI_OPS_H
|
||||
#define ARCH_PPC_PCI_OPS_H
|
||||
|
||||
void pci_set_method(void);
|
||||
const struct pci_bus_operations pci_ppc_conf1;
|
||||
|
||||
#endif /* ARCH_I386_PCI_OPS_H */
|
||||
#endif /* ARCH_PPC_PCI_OPS_H */
|
||||
|
@@ -1,15 +1,17 @@
|
||||
object c_start.S
|
||||
object setup.o
|
||||
object pci_ops.o
|
||||
object pci_ppc_conf1_ops.o
|
||||
object pci_dev.o
|
||||
object timer.o
|
||||
object cpuid.o
|
||||
object cpu.o
|
||||
object timebase.S
|
||||
object floats.S
|
||||
object div64.S
|
||||
initobject pci_dev.o
|
||||
initobject printk_init.o
|
||||
initobject timebase.S
|
||||
initobject timer.o
|
||||
initobject setup.o
|
||||
initobject floats.S
|
||||
initobject div64.S
|
||||
|
@@ -17,6 +17,8 @@
|
||||
_start:
|
||||
/*
|
||||
* init stack pointer to real ram now that memory is on
|
||||
* Note: We use the last 8 bytes on the stack to hold struct cpu_info,
|
||||
* Which are initialized to zero as we clear the stack.
|
||||
*/
|
||||
li r0, 0
|
||||
lis r1, _estack@ha
|
||||
|
@@ -1,12 +1,32 @@
|
||||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <string.h>
|
||||
#include <device/device.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <cpu/ppc/cpuid.h>
|
||||
#include "ppc.h"
|
||||
#include "ppcreg.h"
|
||||
|
||||
#error "FIXME what should call cpu_initialize?"
|
||||
#if 0
|
||||
static void set_cpu_ops(struct device *cpu)
|
||||
{
|
||||
struct cpu_driver *driver;
|
||||
cpu->ops = 0;
|
||||
for (driver = cpu_drivers; driver < ecpu_drivers; driver++) {
|
||||
struct cpu_device_id *id;
|
||||
for(id = driver->id_table; id->pvr != 0; id++) {
|
||||
if (cpu->device == id->pvr)
|
||||
{
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
die("Unknown cpu");
|
||||
return;
|
||||
found:
|
||||
cpu->ops = driver->ops;
|
||||
}
|
||||
#endif
|
||||
|
||||
void cpu_initialize(void)
|
||||
{
|
||||
@@ -27,7 +47,7 @@ void cpu_initialize(void)
|
||||
}
|
||||
|
||||
/* Find what type of cpu we are dealing with */
|
||||
cpu->vendor 0; /* PPC cpus do not have a vendor field */
|
||||
cpu->vendor = 0; /* PPC cpus do not have a vendor field */
|
||||
cpu->device = ppc_getpvr();
|
||||
display_cpuid(cpu);
|
||||
|
||||
@@ -44,7 +64,6 @@ void cpu_initialize(void)
|
||||
#endif
|
||||
/* Turn on caching if we haven't already */
|
||||
|
||||
printk_info("CPU #%d Initialized\n", processor_id);
|
||||
return processor_id;
|
||||
printk_info("CPU #%d Initialized\n", info->index);
|
||||
return;
|
||||
}
|
||||
|
||||
|
58
src/arch/ppc/lib/div64.S
Normal file
58
src/arch/ppc/lib/div64.S
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Divide a 64-bit unsigned number by a 32-bit unsigned number.
|
||||
* This routine assumes that the top 32 bits of the dividend are
|
||||
* non-zero to start with.
|
||||
* On entry, r3 points to the dividend, which get overwritten with
|
||||
* the 64-bit quotient, and r4 contains the divisor.
|
||||
* On exit, r3 contains the remainder.
|
||||
*
|
||||
* Copyright (C) 2002 Paul Mackerras, IBM Corp.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
.globl __div64_32
|
||||
__div64_32:
|
||||
lwz r5,0(r3) # get the dividend into r5/r6
|
||||
lwz r6,4(r3)
|
||||
cmplw r5,r4
|
||||
li r7,0
|
||||
li r8,0
|
||||
blt 1f
|
||||
divwu r7,r5,r4 # if dividend.hi >= divisor,
|
||||
mullw r0,r7,r4 # quotient.hi = dividend.hi / divisor
|
||||
subf. r5,r0,r5 # dividend.hi %= divisor
|
||||
beq 3f
|
||||
1: mr r11,r5 # here dividend.hi != 0
|
||||
andis. r0,r5,0xc000
|
||||
bne 2f
|
||||
cntlzw r0,r5 # we are shifting the dividend right
|
||||
li r10,-1 # to make it < 2^32, and shifting
|
||||
srw r10,r10,r0 # the divisor right the same amount,
|
||||
add r9,r4,r10 # rounding up (so the estimate cannot
|
||||
andc r11,r6,r10 # ever be too large, only too small)
|
||||
andc r9,r9,r10
|
||||
or r11,r5,r11
|
||||
rotlw r9,r9,r0
|
||||
rotlw r11,r11,r0
|
||||
divwu r11,r11,r9 # then we divide the shifted quantities
|
||||
2: mullw r10,r11,r4 # to get an estimate of the quotient,
|
||||
mulhwu r9,r11,r4 # multiply the estimate by the divisor,
|
||||
subfc r6,r10,r6 # take the product from the divisor,
|
||||
add r8,r8,r11 # and add the estimate to the accumulated
|
||||
subfe. r5,r9,r5 # quotient
|
||||
bne 1b
|
||||
3: cmplw r6,r4
|
||||
blt 4f
|
||||
divwu r0,r6,r4 # perform the remaining 32-bit division
|
||||
mullw r10,r0,r4 # and get the remainder
|
||||
add r8,r8,r0
|
||||
subf r6,r10,r6
|
||||
4: stw r7,0(r3) # return the quotient in *r3
|
||||
stw r8,4(r3)
|
||||
mr r3,r6 # return the remainder in r3
|
||||
blr
|
@@ -1,105 +0,0 @@
|
||||
#include <console/console.h>
|
||||
#include <arch/pciconf.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <device/pci_ops.h>
|
||||
|
||||
static const struct pci_ops *conf;
|
||||
struct pci_ops {
|
||||
uint8_t (*read8) (uint8_t bus, int devfn, int where);
|
||||
uint16_t (*read16) (uint8_t bus, int devfn, int where);
|
||||
uint32_t (*read32) (uint8_t bus, int devfn, int where);
|
||||
int (*write8) (uint8_t bus, int devfn, int where, uint8_t val);
|
||||
int (*write16) (uint8_t bus, int devfn, int where, uint16_t val);
|
||||
int (*write32) (uint8_t bus, int devfn, int where, uint32_t val);
|
||||
};
|
||||
|
||||
struct pci_ops pci_direct_ppc;
|
||||
|
||||
/*
|
||||
* Before we decide to use direct hardware access mechanisms, we try to do some
|
||||
* trivial checks to ensure it at least _seems_ to be working -- we just test
|
||||
* whether bus 00 contains a host bridge (this is similar to checking
|
||||
* techniques used in XFree86, but ours should be more reliable since we
|
||||
* attempt to make use of direct access hints provided by the PCI BIOS).
|
||||
*
|
||||
* This should be close to trivial, but it isn't, because there are buggy
|
||||
* chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
|
||||
*/
|
||||
static int pci_sanity_check(const struct pci_ops *o)
|
||||
{
|
||||
uint16_t class, vendor;
|
||||
uint8_t bus;
|
||||
int devfn;
|
||||
#define PCI_CLASS_BRIDGE_HOST 0x0600
|
||||
#define PCI_CLASS_DISPLAY_VGA 0x0300
|
||||
#define PCI_VENDOR_ID_COMPAQ 0x0e11
|
||||
#define PCI_VENDOR_ID_INTEL 0x8086
|
||||
#define PCI_VENDOR_ID_MOTOROLA 0x1057
|
||||
#define PCI_VENDOR_ID_IBM 0x1014
|
||||
|
||||
for (bus = 0, devfn = 0; devfn < 0x100; devfn++) {
|
||||
class = o->read16(bus, devfn, PCI_CLASS_DEVICE);
|
||||
vendor = o->read16(bus, devfn, PCI_VENDOR_ID);
|
||||
if (((class == PCI_CLASS_BRIDGE_HOST) ||
|
||||
(class == PCI_CLASS_DISPLAY_VGA)) ||
|
||||
((vendor == PCI_VENDOR_ID_INTEL) ||
|
||||
(vendor == PCI_VENDOR_ID_COMPAQ) ||
|
||||
(vendor == PCI_VENDOR_ID_MOTOROLA) ||
|
||||
(vendor == PCI_VENDOR_ID_IBM))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printk_err("PCI: Sanity check failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t pci_read_config8(device_t dev, unsigned where)
|
||||
{
|
||||
return conf->read8(dev->bus->secondary, dev->path.u.pci.devfn, where);
|
||||
}
|
||||
|
||||
uint16_t pci_read_config16(struct device *dev, unsigned where)
|
||||
{
|
||||
return conf->read16(dev->bus->secondary, dev->path.u.pci.devfn, where);
|
||||
}
|
||||
|
||||
uint32_t pci_read_config32(struct device *dev, unsigned where)
|
||||
{
|
||||
return conf->read32(dev->bus->secondary, dev->path.u.pci.devfn, where);
|
||||
}
|
||||
|
||||
void pci_write_config8(struct device *dev, unsigned where, uint8_t val)
|
||||
{
|
||||
conf->write8(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
|
||||
}
|
||||
|
||||
void pci_write_config16(struct device *dev, unsigned where, uint16_t val)
|
||||
{
|
||||
conf->write16(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
|
||||
}
|
||||
|
||||
void pci_write_config32(struct device *dev, unsigned where, uint32_t val)
|
||||
{
|
||||
conf->write32(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
|
||||
}
|
||||
|
||||
/** Set the method to be used for PCI
|
||||
*/
|
||||
void pci_set_method(void)
|
||||
{
|
||||
conf = &pci_direct_ppc;
|
||||
pci_sanity_check(conf);
|
||||
}
|
||||
|
||||
struct pci_ops pci_direct_ppc =
|
||||
{
|
||||
pci_ppc_read_config8,
|
||||
pci_ppc_read_config16,
|
||||
pci_ppc_read_config32,
|
||||
pci_ppc_write_config8,
|
||||
pci_ppc_write_config16,
|
||||
pci_ppc_write_config32
|
||||
};
|
||||
|
46
src/arch/ppc/lib/pci_ppc_conf1_ops.c
Normal file
46
src/arch/ppc/lib/pci_ppc_conf1_ops.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <console/console.h>
|
||||
#include <arch/pciconf.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <device/pci_ops.h>
|
||||
|
||||
static uint8_t ppc_conf1_read_config8(struct bus *pbus, unsigned char bus, int devfn, int where)
|
||||
{
|
||||
return pci_ppc_read_config8(bus, devfn, where);
|
||||
}
|
||||
|
||||
static uint16_t ppc_conf1_read_config16(struct bus *pbus, unsigned char bus, int devfn, int where)
|
||||
{
|
||||
return pci_ppc_read_config16(bus, devfn, where);
|
||||
}
|
||||
|
||||
static uint32_t ppc_conf1_read_config32(struct bus *pbus, unsigned char bus, int devfn, int where)
|
||||
{
|
||||
return pci_ppc_read_config32(bus, devfn, where);
|
||||
}
|
||||
|
||||
static void ppc_conf1_write_config8(struct bus *pbus, unsigned char bus, int devfn, int where, uint8_t val)
|
||||
{
|
||||
pci_ppc_write_config8(bus, devfn, where, val);
|
||||
}
|
||||
|
||||
static void ppc_conf1_write_config16(struct bus *pbus, unsigned char bus, int devfn, int where, uint16_t val)
|
||||
{
|
||||
pci_ppc_write_config16(bus, devfn, where, val);
|
||||
}
|
||||
|
||||
static void ppc_conf1_write_config32(struct bus *pbus, unsigned char bus, int devfn, int where, uint32_t val)
|
||||
{
|
||||
pci_ppc_write_config32(bus, devfn, where, val);
|
||||
}
|
||||
|
||||
const struct pci_bus_operations pci_ppc_conf1 =
|
||||
{
|
||||
.read8 = ppc_conf1_read_config8,
|
||||
.read16 = ppc_conf1_read_config16,
|
||||
.read32 = ppc_conf1_read_config32,
|
||||
.write8 = ppc_conf1_write_config8,
|
||||
.write16 = ppc_conf1_write_config16,
|
||||
.write32 = ppc_conf1_write_config32,
|
||||
};
|
Reference in New Issue
Block a user