mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
pci: property encoding helpers
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com> git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@784 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
committed by
Blue Swirl
parent
e8306d2724
commit
091947776c
129
drivers/pci.c
129
drivers/pci.c
@@ -52,7 +52,21 @@ enum {
|
|||||||
MEMORY_SPACE_64 = 3,
|
MEMORY_SPACE_64 = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void pci_encode_phys_addr(u32 *phys, int flags, int space_code,
|
static int encode_int32_cells(int num_cells, u32 *prop, ucell val)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
/* hi ... lo */
|
||||||
|
for (i=0; i < num_cells; ++i) {
|
||||||
|
prop[num_cells - i - 1] = val;
|
||||||
|
val >>= 16;
|
||||||
|
val >>= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int pci_encode_phys_addr(u32 *phys, int flags, int space_code,
|
||||||
pci_addr dev, uint8_t reg, uint64_t addr)
|
pci_addr dev, uint8_t reg, uint64_t addr)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -67,8 +81,44 @@ static inline void pci_encode_phys_addr(u32 *phys, int flags, int space_code,
|
|||||||
/* phys.lo */
|
/* phys.lo */
|
||||||
|
|
||||||
phys[2] = addr;
|
phys[2] = addr;
|
||||||
|
|
||||||
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int pci_encode_size(u32 *prop, uint64_t size)
|
||||||
|
{
|
||||||
|
return encode_int32_cells(2, prop, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int host_address_cells(void)
|
||||||
|
{
|
||||||
|
return get_int_property(find_dev("/"), "#address-cells", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int host_encode_phys_addr(u32 *prop, ucell addr)
|
||||||
|
{
|
||||||
|
return encode_int32_cells(host_address_cells(), prop, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int host_size_cells(void)
|
||||||
|
{
|
||||||
|
return get_int_property(find_dev("/"), "#size-cells", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static int parent_address_cells(void)
|
||||||
|
{
|
||||||
|
phandle_t parent_ph = ih_to_phandle(my_parent());
|
||||||
|
return get_int_property(parent_ph, "#address-cells", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parent_size_cells(void)
|
||||||
|
{
|
||||||
|
phandle_t parent_ph = ih_to_phandle(my_parent());
|
||||||
|
return get_int_property(parent_ph, "#size-cells", NULL);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ob_pci_open(int *idx)
|
ob_pci_open(int *idx)
|
||||||
{
|
{
|
||||||
@@ -318,14 +368,23 @@ static void pci_host_set_interrupt_map(const pci_config_t *config)
|
|||||||
|
|
||||||
static void pci_host_set_reg(const pci_config_t *config)
|
static void pci_host_set_reg(const pci_config_t *config)
|
||||||
{
|
{
|
||||||
phandle_t dev = get_cur_dev();
|
phandle_t dev = get_cur_dev();
|
||||||
u32 props[2];
|
/* at most 2 integers for address and size */
|
||||||
|
u32 props[4];
|
||||||
|
int ncells = 0;
|
||||||
|
|
||||||
props[0] = arch->cfg_base;
|
ncells += encode_int32_cells(host_address_cells(), props + ncells,
|
||||||
props[1] = arch->cfg_len;
|
arch->cfg_base);
|
||||||
set_property(dev, "reg", (char *)props, 2 * sizeof(props[0]));
|
|
||||||
|
ncells += encode_int32_cells(host_size_cells(), props + ncells,
|
||||||
|
arch->cfg_len);
|
||||||
|
|
||||||
|
set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* child-phys : parent-phys : size */
|
||||||
|
/* 3 cells for PCI : 2 cells for 64bit parent : 2 cells for PCI */
|
||||||
|
|
||||||
static void pci_host_set_ranges(const pci_config_t *config)
|
static void pci_host_set_ranges(const pci_config_t *config)
|
||||||
{
|
{
|
||||||
phandle_t dev = get_cur_dev();
|
phandle_t dev = get_cur_dev();
|
||||||
@@ -333,29 +392,31 @@ static void pci_host_set_ranges(const pci_config_t *config)
|
|||||||
int ncells;
|
int ncells;
|
||||||
|
|
||||||
ncells = 0;
|
ncells = 0;
|
||||||
|
/* first encode PCI configuration space */
|
||||||
|
{
|
||||||
|
ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
|
||||||
|
config->dev, 0, 0);
|
||||||
|
ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr);
|
||||||
|
ncells += pci_encode_size(props + ncells, arch->cfg_len);
|
||||||
|
}
|
||||||
|
|
||||||
if (arch->io_base) {
|
if (arch->io_base) {
|
||||||
pci_encode_phys_addr(props + ncells, 0, IO_SPACE,
|
ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE,
|
||||||
config->dev, 0, 0);
|
config->dev, 0, 0);
|
||||||
ncells += 3;
|
ncells += host_encode_phys_addr(props + ncells, arch->io_base);
|
||||||
props[ncells++] = arch->io_base;
|
ncells += pci_encode_size(props + ncells, arch->io_len);
|
||||||
props[ncells++] = 0x00000000;
|
|
||||||
props[ncells++] = arch->io_len;
|
|
||||||
}
|
}
|
||||||
if (arch->rbase) {
|
if (arch->rbase) {
|
||||||
pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
|
ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
|
||||||
config->dev, 0, 0);
|
config->dev, 0, 0);
|
||||||
ncells += 3;
|
ncells += host_encode_phys_addr(props + ncells, arch->rbase);
|
||||||
props[ncells++] = arch->rbase;
|
ncells += pci_encode_size(props + ncells, arch->rlen);
|
||||||
props[ncells++] = 0x00000000;
|
|
||||||
props[ncells++] = arch->rlen;
|
|
||||||
}
|
}
|
||||||
if (arch->mem_base) {
|
if (arch->mem_base) {
|
||||||
pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
|
ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
|
||||||
config->dev, 0, arch->mem_base);
|
config->dev, 0, arch->mem_base);
|
||||||
ncells += 3;
|
ncells += host_encode_phys_addr(props + ncells, arch->mem_base);
|
||||||
props[ncells++] = arch->mem_base;
|
ncells += pci_encode_size(props + ncells, arch->mem_len);
|
||||||
props[ncells++] = 0x00000000;
|
|
||||||
props[ncells++] = arch->mem_len;
|
|
||||||
}
|
}
|
||||||
set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
|
set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
|
||||||
}
|
}
|
||||||
@@ -548,11 +609,10 @@ static void pci_set_assigned_addresses(const pci_config_t *config, int num_bars)
|
|||||||
pci_decode_pci_addr(config->assigned[i],
|
pci_decode_pci_addr(config->assigned[i],
|
||||||
&flags, &space_code, &mask);
|
&flags, &space_code, &mask);
|
||||||
|
|
||||||
pci_encode_phys_addr(props + ncells,
|
ncells += pci_encode_phys_addr(props + ncells,
|
||||||
flags, space_code, config->dev,
|
flags, space_code, config->dev,
|
||||||
PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
|
PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
|
||||||
config->assigned[i] & ~mask);
|
config->assigned[i] & ~mask);
|
||||||
ncells += 3;
|
|
||||||
|
|
||||||
props[ncells++] = 0x00000000;
|
props[ncells++] = 0x00000000;
|
||||||
props[ncells++] = config->sizes[i];
|
props[ncells++] = config->sizes[i];
|
||||||
@@ -571,13 +631,13 @@ static void pci_set_reg(const pci_config_t *config, int num_bars)
|
|||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
int space_code, flags;
|
int space_code, flags;
|
||||||
|
|
||||||
ncells = 0;
|
ncells = 0;
|
||||||
pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
|
|
||||||
config->dev, 0, 0);
|
|
||||||
ncells += 3;
|
|
||||||
|
|
||||||
props[ncells++] = 0x00000000;
|
/* first (addr, size) pair is the beginning of configuration address space */
|
||||||
props[ncells++] = 0x00000000;
|
ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
|
||||||
|
config->dev, 0, 0);
|
||||||
|
|
||||||
|
ncells += pci_encode_size(props + ncells, 0);
|
||||||
|
|
||||||
for (i = 0; i < num_bars; i++) {
|
for (i = 0; i < num_bars; i++) {
|
||||||
if (!config->assigned[i] || !config->sizes[i])
|
if (!config->assigned[i] || !config->sizes[i])
|
||||||
@@ -586,17 +646,15 @@ static void pci_set_reg(const pci_config_t *config, int num_bars)
|
|||||||
pci_decode_pci_addr(config->regions[i],
|
pci_decode_pci_addr(config->regions[i],
|
||||||
&flags, &space_code, &mask);
|
&flags, &space_code, &mask);
|
||||||
|
|
||||||
pci_encode_phys_addr(props + ncells,
|
ncells += pci_encode_phys_addr(props + ncells,
|
||||||
flags, space_code, config->dev,
|
flags, space_code, config->dev,
|
||||||
PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
|
PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
|
||||||
config->regions[i] & ~mask);
|
config->regions[i] & ~mask);
|
||||||
ncells += 3;
|
|
||||||
|
|
||||||
/* set size */
|
/* set size */
|
||||||
|
ncells += pci_encode_size(props + ncells, config->sizes[i]);
|
||||||
props[ncells++] = 0x00000000;
|
|
||||||
props[ncells++] = config->sizes[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
|
set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,10 +682,9 @@ static void pci_set_ranges(const pci_config_t *config)
|
|||||||
|
|
||||||
pci_decode_pci_addr(config->assigned[i],
|
pci_decode_pci_addr(config->assigned[i],
|
||||||
&flags, &space_code, &mask);
|
&flags, &space_code, &mask);
|
||||||
pci_encode_phys_addr(props + ncells, flags, space_code,
|
ncells += pci_encode_phys_addr(props + ncells, flags, space_code,
|
||||||
config->dev, 0x10 + i * 4,
|
config->dev, 0x10 + i * 4,
|
||||||
config->assigned[i] & ~mask);
|
config->assigned[i] & ~mask);
|
||||||
ncells += 3;
|
|
||||||
|
|
||||||
/* size */
|
/* size */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user