Skip to content

Commit 38e2a1f

Browse files
authored
Merge pull request #695 from rizlik/fix-pci
Pci: fixes and unit testings
2 parents bd02eea + b9ecbca commit 38e2a1f

File tree

3 files changed

+1729
-199
lines changed

3 files changed

+1729
-199
lines changed

include/pci.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@
5050
#define PCI_PREFETCH_LIMIT_OFF 0x26
5151
#define PCI_MMIO_BASE_OFF 0x20
5252
#define PCI_MMIO_LIMIT_OFF 0x22
53-
#define PCI_IO_BASE_OFF 0x30
54-
#define PCI_IO_LIMIT_OFF 0x32
53+
#define PCI_IO_BASE_OFF 0x1C
54+
#define PCI_IO_LIMIT_OFF 0x1D
5555
#define PCI_PWR_MGMT_CTRL_STATUS 0x84
5656
#define PCI_POWER_STATE_MASK 0x3
5757
/* Shifts & masks for CONFIG_ADDRESS register */
@@ -117,9 +117,8 @@ void pci_config_write16(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off,
117117
uint8_t pci_config_read8(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off);
118118
void pci_config_write8(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off,
119119
uint8_t value);
120-
uint64_t pci_get_mmio_addr(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t bar);
121120

122-
uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info);
121+
int pci_enum_bus(uint8_t bus, struct pci_enum_info *info);
123122

124123
int pci_enum_do(void);
125124
int pci_pre_enum(void);

src/pci.c

Lines changed: 69 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@
8080
#define PCI_ENUM_TYPE_64bit (0x1 << 1)
8181
#define PCI_ENUM_TYPE_32bit (0x1)
8282
#define PCI_ENUM_IS_PREFETCH (0x1 << 3)
83-
#define PCI_ENUM_MM_BAR_MASK ~(0xf)
84-
#define PCI_ENUM_IO_BAR_MASK ~(0x3)
83+
#define PCI_ENUM_MM_BAR_MASK (~0xfU)
84+
#define PCI_ENUM_IO_BAR_MASK (~0x3U)
8585

8686
#define CAPID0_A_0_0_0_PCI (0xE4)
8787
#define DEVICE_ENABLE (0x54)
@@ -139,8 +139,8 @@ static uint32_t pci_align32_address(uint32_t addr, int *aligned)
139139
static uint32_t pci_config_ecam_make_address(uint8_t bus, uint8_t dev,
140140
uint8_t func, uint8_t off)
141141
{
142-
return (PCI_ECAM_BASE +
143-
((bus&0xff) << 20) |
142+
return PCI_ECAM_BASE +
143+
(((bus&0xff) << 20) |
144144
((dev&0x1f) << 15) |
145145
((func&0x07) << 12) |
146146
(off & 0xfff));
@@ -198,11 +198,11 @@ static void pci_ecam_config_write16(uint8_t bus, uint8_t dev, uint8_t fun,
198198
#define PCI_IO_CONFIG_ADDR(bus, dev, fn, off) \
199199
(uint32_t)( \
200200
(1UL << PCI_CONFIG_ADDRESS_ENABLE_BIT_SHIFT) | \
201-
(bus << PCI_CONFIG_ADDRESS_BUS_SHIFT) | \
202-
(dev << PCI_CONFIG_ADDRESS_DEVICE_SHIFT) | \
203-
(fn << PCI_CONFIG_ADDRESS_FUNCTION_SHIFT) | \
204-
((off & 0xF00) << 16) | \
205-
(off & PCI_CONFIG_ADDRESS_OFFSET_MASK))
201+
((bus) << PCI_CONFIG_ADDRESS_BUS_SHIFT) | \
202+
((dev) << PCI_CONFIG_ADDRESS_DEVICE_SHIFT) | \
203+
((fn) << PCI_CONFIG_ADDRESS_FUNCTION_SHIFT) | \
204+
(((off) & 0xF00) << 16) | \
205+
((off) & PCI_CONFIG_ADDRESS_OFFSET_MASK))
206206

207207
static uint32_t pci_io_config_read32(uint32_t bus, uint32_t dev, uint32_t func,
208208
uint32_t off)
@@ -227,44 +227,44 @@ static void pci_io_config_write32(uint32_t bus, uint32_t dev, uint32_t func,
227227
static uint16_t pci_io_config_read16(uint32_t bus, uint32_t dev, uint32_t func,
228228
uint32_t off)
229229
{
230-
uint32_t address = PCI_IO_CONFIG_ADDR(bus, dev, func, off);
231-
uint32_t data = 0xffff;
230+
uint32_t data;
232231
int aligned32;
232+
uint32_t off_aligned;
233233

234234
/* off must be 16 bit aligned */
235-
if ((address & PCI_ADDR_16BIT_ALIGNED_MASK) != 0)
236-
return data;
235+
if ((off & PCI_ADDR_16BIT_ALIGNED_MASK) != 0)
236+
return 0xffff;
237237

238-
address = pci_align32_address(address, &aligned32);
239-
data = pci_io_config_read32(bus, dev, func, address);
240-
if (!aligned32)
241-
data >>= PCI_DATA_HI16_SHIFT;
242-
else
238+
off_aligned = pci_align32_address(off, &aligned32);
239+
data = pci_io_config_read32(bus, dev, func, off_aligned);
240+
if (aligned32)
243241
data &= PCI_DATA_LO16_MASK;
242+
else
243+
data >>= PCI_DATA_HI16_SHIFT;
244244
return (uint16_t)data;
245245
}
246246

247247
static void pci_io_config_write16(uint32_t bus, uint32_t dev, uint32_t func,
248248
uint32_t off, uint16_t val)
249249
{
250-
uint32_t dst_addr = PCI_IO_CONFIG_ADDR(bus, dev, func, off);
250+
uint32_t off_aligned;
251251
uint32_t reg;
252252
int aligned32;
253253

254254
/* off must be 16 bit aligned */
255-
if ((dst_addr & PCI_ADDR_16BIT_ALIGNED_MASK) != 0)
255+
if ((off & PCI_ADDR_16BIT_ALIGNED_MASK) != 0)
256256
return;
257257

258-
dst_addr = pci_align32_address(dst_addr, &aligned32);
259-
reg = pci_io_config_read32(bus, dev, func, dst_addr);
258+
off_aligned = pci_align32_address(off, &aligned32);
259+
reg = pci_io_config_read32(bus, dev, func, off_aligned);
260260
if (aligned32) {
261261
reg &= PCI_DATA_HI16_MASK;
262262
reg |= val;
263263
} else {
264264
reg &= PCI_DATA_LO16_MASK;
265265
reg |= (val << PCI_DATA_HI16_SHIFT);
266266
}
267-
pci_io_config_write32(bus, dev, func, dst_addr, reg);
267+
pci_io_config_write32(bus, dev, func, off_aligned, reg);
268268
}
269269
#endif /* PCI_USE_ECAM */
270270

@@ -337,35 +337,7 @@ uint8_t pci_config_read8(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off)
337337
return reg;
338338
}
339339

340-
uint64_t pci_get_mmio_addr(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t bar)
341-
{
342-
uint32_t reg;
343-
uint64_t addr = 0;
344340

345-
if (bar >= PCI_ENUM_MAX_BARS)
346-
{
347-
return addr;
348-
}
349-
350-
reg = pci_config_read32(bus, dev, fun, PCI_BAR0_OFFSET + (bar * 8));
351-
wolfBoot_printf("BAR%d[0x%x] reg value = 0x%x\r\n", bar, PCI_BAR0_OFFSET + (bar * 8), reg);
352-
353-
if (!pci_enum_is_mmio(reg))
354-
{
355-
return addr;
356-
}
357-
358-
addr = reg & 0xFFFFFFF0;
359-
360-
if (pci_enum_is_64bit(reg))
361-
{
362-
reg = pci_config_read32(bus, dev, fun, (PCI_BAR0_OFFSET + 4) + (bar * 8));
363-
wolfBoot_printf("BAR%d_HIGH[0x%x] reg value = 0x%x\r\n", bar, (PCI_BAR0_OFFSET + 4) + (bar * 8), reg);
364-
addr |= ((uint64_t)reg << 32);
365-
}
366-
367-
return addr;
368-
}
369341

370342
static int pci_enum_is_64bit(uint32_t value)
371343
{
@@ -470,16 +442,23 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
470442
bar_align = bar_value & PCI_ENUM_MM_BAR_MASK;
471443
is_prefetch = pci_enum_is_prefetch(bar_value);
472444
if (pci_enum_is_64bit(bar_value)) {
445+
*is_64bit = 1;
473446
orig_bar2 = pci_config_read32(bus, dev, fun, bar_off + 4);
447+
448+
/* rewrite 0xff..ff mask and re-read the first BAR value, specs
449+
* requires to write the mask on both registers before reading
450+
* the sizes back */
451+
pci_config_write32(bus, dev, fun, bar_off, 0xffffffff);
474452
pci_config_write32(bus, dev, fun, bar_off + 4, 0xffffffff);
453+
bar_value = pci_config_read32(bus, dev, fun, bar_off);
454+
bar_align = bar_value & PCI_ENUM_MM_BAR_MASK;
475455
reg = pci_config_read32(bus, dev, fun, bar_off + 4);
476456
PCI_DEBUG_PRINTF("bar high 32bit: %d\r\n", reg);
477457
if (reg != 0xffffffff) {
478458
PCI_DEBUG_PRINTF("Device wants too much memory, skipping\r\n");
479459
pci_config_write32(bus, dev, fun, bar_off + 4, orig_bar2);
480460
goto restore_bar;
481461
}
482-
*is_64bit = 1;
483462
}
484463
if (is_prefetch) {
485464
base = &info->mem_pf;
@@ -510,7 +489,7 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
510489
/* check max length */
511490
ret = pci_enum_next_aligned32(*base, &bar_value, align, limit);
512491
if (ret != 0) {
513-
wolfBoot_printf("Not memory space for mapping the PCI device... skipping\r\n");
492+
PCI_DEBUG_PRINTF("Not memory space for mapping the PCI device... skipping\r\n");
514493
goto restore_bar;
515494
}
516495

@@ -526,7 +505,7 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
526505
return 0;
527506

528507
restore_bar:
529-
pci_config_write32(bus, dev, fun, bar_idx, orig_bar);
508+
pci_config_write32(bus, dev, fun, bar_off, orig_bar);
530509

531510
return ret;
532511
}
@@ -612,8 +591,17 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
612591
uint32_t mem_start;
613592
uint32_t io_start;
614593
uint32_t orig_cmd;
594+
uint8_t saved_bus;
595+
uint32_t saved_mem;
596+
uint32_t saved_pf;
597+
uint32_t saved_io;
615598
int ret;
616599

600+
saved_bus = info->curr_bus_number;
601+
saved_mem = info->mem;
602+
saved_pf = info->mem_pf;
603+
saved_io = info->io;
604+
617605
orig_cmd = pci_config_read16(bus, dev, fun, PCI_COMMAND_OFFSET);
618606
pci_config_write16(bus, dev, fun, PCI_COMMAND_OFFSET, 0);
619607

@@ -627,6 +615,8 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
627615
* (curr_bus_number,0xff) to scan the bus behind the bridge */
628616
pci_config_write8(bus, dev, fun, PCI_SUB_SEC_BUS, 0xff);
629617

618+
/* PCI bridge window registers enforce alignment constraints from the spec:
619+
* prefetch and MMIO windows are 1MB-aligned, IO windows are 4KB-aligned. */
630620
ret = pci_align_check_up(info->mem_pf, ONE_MB,
631621
info->mem_pf_limit,
632622
&prefetch_start);
@@ -655,7 +645,10 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
655645
* bridge */
656646
pci_config_write8(bus, dev, fun, PCI_SUB_SEC_BUS, info->curr_bus_number);
657647

658-
/* upate prefetch range */
648+
/* PCI bridge window registers enforce alignment constraints from the spec:
649+
* prefetch and MMIO windows are 1MB-aligned, IO windows are 4KB-aligned.
650+
* After enumeration, the end of each window must also be aligned up to meet
651+
* these granularity requirements. */
659652
if (prefetch_start != info->mem_pf) {
660653
ret = pci_align_check_up(info->mem_pf, ONE_MB,
661654
info->mem_pf_limit,
@@ -722,11 +715,18 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
722715
return 0;
723716

724717
err:
718+
info->curr_bus_number = saved_bus;
719+
info->mem = saved_mem;
720+
info->mem_pf = saved_pf;
721+
info->io = saved_io;
722+
pci_config_write8(bus, dev, fun, PCI_PRIMARY_BUS, 0);
723+
pci_config_write8(bus, dev, fun, PCI_SECONDARY_BUS, 0);
724+
pci_config_write8(bus, dev, fun, PCI_SUB_SEC_BUS, 0);
725725
pci_config_write16(bus, dev, fun, PCI_COMMAND_OFFSET, orig_cmd);
726726
return -1;
727727
}
728728

729-
uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info)
729+
int pci_enum_bus(uint8_t bus, struct pci_enum_info *info)
730730
{
731731
uint16_t header_type;
732732
uint32_t vd_code;
@@ -781,16 +781,16 @@ int pci_pre_enum(void)
781781
uint32_t reg;
782782

783783
reg = pci_config_read32(0, 0, 0, CAPID0_A_0_0_0_PCI);
784-
wolfBoot_printf("cap a %d\r\n", reg);
785-
wolfBoot_printf("ddt disabled %d\r\n", reg & DTT_DEVICE_DISABLE);
784+
PCI_DEBUG_PRINTF("cap a %d\r\n", reg);
785+
PCI_DEBUG_PRINTF("ddt disabled %d\r\n", reg & DTT_DEVICE_DISABLE);
786786
reg &= ~(DTT_DEVICE_DISABLE);
787787
pci_config_write32(0, 0, 0, CAPID0_A_0_0_0_PCI, reg);
788788
reg = pci_config_read32(0, 0, 0, DEVICE_ENABLE);
789-
wolfBoot_printf("device enable: %d\r\n", reg);
789+
PCI_DEBUG_PRINTF("device enable: %d\r\n", reg);
790790
reg |= (1 << 7);
791791
pci_config_write32(0, 0, 0, DEVICE_ENABLE, reg);
792792
reg = pci_config_read32(0, 0, 0, DEVICE_ENABLE);
793-
wolfBoot_printf("device enable: %d\r\n", reg);
793+
PCI_DEBUG_PRINTF("device enable: %d\r\n", reg);
794794

795795
return 0;
796796
}
@@ -817,11 +817,11 @@ void pci_dump(uint8_t bus, uint8_t dev, uint8_t fun)
817817
for (i = 0; i < 256; i++) {
818818
if (i % 0x10 == 0x0) {
819819
if (i < 0x10) {
820-
wolfBoot_printf("0");
820+
PCI_DEBUG_PRINTF("0");
821821
}
822-
wolfBoot_printf("%x: ", (int)i);
822+
PCI_DEBUG_PRINTF("%x: ", (int)i);
823823
}
824-
wolfBoot_printf("%s%x%s", (ptr[i] < 0x10 ? "0" :""), (int)ptr[i],
824+
PCI_DEBUG_PRINTF("%s%x%s", (ptr[i] < 0x10 ? "0" :""), (int)ptr[i],
825825
(i % 0x10 == 0xf ? "\r\n":" "));
826826
}
827827
}
@@ -856,12 +856,12 @@ static void pci_dump_bus(uint8_t bus)
856856
}
857857

858858
if (bus < 0x10)
859-
wolfBoot_printf("0");
860-
wolfBoot_printf("%x:", bus);
859+
PCI_DEBUG_PRINTF("0");
860+
PCI_DEBUG_PRINTF("%x:", bus);
861861
if (dev < 0x10)
862-
wolfBoot_printf("0");
863-
wolfBoot_printf("%x.", dev);
864-
wolfBoot_printf("%d \r\n", fun);
862+
PCI_DEBUG_PRINTF("0");
863+
PCI_DEBUG_PRINTF("%x.", dev);
864+
PCI_DEBUG_PRINTF("%d \r\n", fun);
865865
pci_dump(bus, dev, fun);
866866
header_type = pci_config_read16(bus, dev, fun,
867867
PCI_HEADER_TYPE_OFFSET);
@@ -906,7 +906,7 @@ int pci_enum_do(void)
906906

907907
ret = pci_pre_enum();
908908
if (ret != 0) {
909-
wolfBoot_printf("pci_pre_enum error: %d\r\n", ret);
909+
PCI_DEBUG_PRINTF("pci_pre_enum error: %d\r\n", ret);
910910
return ret;
911911
}
912912

0 commit comments

Comments
 (0)