Skip to content

Commit 3c392d8

Browse files
committed
[mk][pci] Port PCI to work with MK/Zircon
Change-Id: I1ac00de716939f820d27b1a244891b4291ac27f0
1 parent 3543217 commit 3c392d8

File tree

15 files changed

+1866
-1763
lines changed

15 files changed

+1866
-1763
lines changed

dev/BUILD.gn

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright 2025 Mist Tecnologia Ltda. All rights reserved.
2+
# Use of this source code is governed by a BSD-style license that can be
3+
# found in the LICENSE file.
4+
5+
import("//build/zircon/zx_library.gni")
6+
7+
zx_library("dev") {
8+
}

dev/bus/pci/BUILD.gn

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2025 Mist Tecnologia Ltda. All rights reserved.
2+
# Use of this source code is governed by a BSD-style license that can be
3+
# found in the LICENSE file.
4+
5+
import("//build/zircon/zx_library.gni")
6+
7+
zx_library("pci") {
8+
sources = [
9+
"backend/ecam.cpp",
10+
"backend/type1.cpp",
11+
"bus_mgr/bridge.cpp",
12+
"bus_mgr/bus.cpp",
13+
"bus_mgr/bus_mgr.cpp",
14+
"bus_mgr/device.cpp",
15+
"bus_mgr/resource.cpp",
16+
"debug.cpp",
17+
"pci.cpp",
18+
]
19+
20+
deps = [
21+
"//zircon/kernel/lib/console",
22+
"//zircon/kernel/vm:headers",
23+
"//zircon/system/ulib/pretty",
24+
]
25+
26+
public_deps = [
27+
"//third_party/lk/dev",
28+
"//vendor/misttech/lib/lk_redirect:headers",
29+
]
30+
31+
cflags_cc = [
32+
"-Wno-invalid-offsetof",
33+
"-Wmissing-declarations",
34+
]
35+
36+
configs += [ ":suppress-warning" ]
37+
}
38+
39+
config("suppress-warning") {
40+
cflags_cc = [ "-Wno-implicit-int-conversion" ]
41+
}

dev/bus/pci/backend/ecam.cpp

+97-86
Original file line numberDiff line numberDiff line change
@@ -8,141 +8,152 @@
88
*/
99
#include "ecam.h"
1010

11-
#include <lk/debug.h>
12-
#include <lk/err.h>
1311
#include <stdlib.h>
1412
#include <string.h>
15-
#include <kernel/thread.h>
16-
#include <kernel/spinlock.h>
13+
1714
#include <dev/bus/pci.h>
15+
#include <fbl/alloc_checker.h>
16+
#include <kernel/spinlock.h>
17+
#include <kernel/thread.h>
18+
#include <lk/debug.h>
19+
#include <lk/err.h>
1820
#include <lk/trace.h>
19-
20-
#if WITH_KERNEL_VM
21-
#include <kernel/vm.h>
22-
#endif
21+
#include <vm/vm_aspace.h>
2322

2423
#include "../pci_priv.h"
2524

2625
#define LOCAL_TRACE 0
2726

28-
pci_ecam::pci_ecam(paddr_t base, uint16_t segment, uint8_t start_bus, uint8_t end_bus) :
29-
base_(base), segment_(segment), start_bus_(start_bus), end_bus_(end_bus) {}
27+
pci_ecam::pci_ecam(paddr_t base, uint16_t segment, uint8_t start_bus, uint8_t end_bus)
28+
: base_(base), segment_(segment), start_bus_(start_bus), end_bus_(end_bus) {}
3029

3130
pci_ecam::~pci_ecam() {
32-
LTRACE_ENTRY;
33-
#if WITH_KERNEL_VM
34-
if (ecam_ptr_) {
35-
vmm_free_region(vmm_get_kernel_aspace(), (vaddr_t)ecam_ptr_);
36-
}
37-
#endif
31+
LTRACE_ENTRY;
32+
if (ecam_ptr_) {
33+
VmAspace::kernel_aspace()->FreeRegion(reinterpret_cast<vaddr_t>(ecam_ptr_));
34+
ecam_ptr_ = nullptr;
35+
}
3836
}
3937

4038
pci_ecam *pci_ecam::detect(paddr_t base, uint16_t segment, uint8_t start_bus, uint8_t end_bus) {
41-
LTRACEF("base %#lx, segment %hu, bus [%hhu...%hhu]\n", base, segment, start_bus, end_bus);
42-
43-
// we only support a limited configuration at the moment
44-
if (segment != 0 || start_bus != 0) {
45-
return nullptr;
46-
}
47-
48-
auto ecam = new pci_ecam(base, segment, start_bus, end_bus);
49-
50-
// initialize the object, which may fail
51-
status_t err = ecam->initialize();
52-
if (err != NO_ERROR) {
53-
delete ecam;
54-
return nullptr;
55-
}
56-
57-
return ecam;
39+
LTRACEF("base %#lx, segment %hu, bus [%hhu...%hhu]\n", base, segment, start_bus, end_bus);
40+
41+
// we only support a limited configuration at the moment
42+
if (segment != 0 || start_bus != 0) {
43+
return nullptr;
44+
}
45+
46+
fbl::AllocChecker ac;
47+
auto ecam = new (&ac) pci_ecam(base, segment, start_bus, end_bus);
48+
if (!ac.check()) {
49+
return nullptr;
50+
}
51+
52+
// initialize the object, which may fail
53+
status_t err = ecam->initialize();
54+
if (err != NO_ERROR) {
55+
delete ecam;
56+
return nullptr;
57+
}
58+
59+
return ecam;
5860
}
5961

6062
status_t pci_ecam::initialize() {
61-
// compute the aperture size of this
62-
size_t size = ((size_t)end_bus_ - (size_t)start_bus_ + 1) << 20; // each bus occupies 20 bits of address space
63-
LTRACEF("aperture size %#zx\n", size);
64-
65-
66-
#if WITH_KERNEL_VM
67-
// try to map the aperture
68-
// ask for 4MB aligned regions (log2 22) to help with the mmu on most architectures
69-
//status_t vmm_alloc_physical(vmm_aspace_t *aspace, const char *name, size_t size, void **ptr, uint8_t align_log2, paddr_t paddr, uint vmm_flags, uint arch_mmu_flags)
70-
status_t err = vmm_alloc_physical(vmm_get_kernel_aspace(), "pci_ecam", size, (void **)&ecam_ptr_, 22, base_, 0, ARCH_MMU_FLAG_UNCACHED_DEVICE);
71-
LTRACEF("vmm_alloc_physical returns %d, ptr %p\n", err, ecam_ptr_);
72-
73-
if (err != NO_ERROR) {
74-
ecam_ptr_ = nullptr;
75-
return err;
76-
}
77-
#else
78-
// no vm, so can directly access the aperture
79-
ecam_ptr_ = (uint8_t *)base_;
80-
#endif
81-
82-
set_last_bus(end_bus_);
83-
84-
return NO_ERROR;
63+
// compute the aperture size of this
64+
size_t size = ((size_t)end_bus_ - (size_t)start_bus_ + 1)
65+
<< 20; // each bus occupies 20 bits of address space
66+
LTRACEF("aperture size %#zx\n", size);
67+
68+
// try to map the aperture
69+
// ask for 4MB aligned regions (log2 22) to help with the mmu on most architectures
70+
// status_t vmm_alloc_physical(vmm_aspace_t *aspace, const char *name, size_t size, void **ptr,
71+
// uint8_t align_log2, paddr_t paddr, uint vmm_flags, uint arch_mmu_flags)
72+
zx_status_t err = VmAspace::kernel_aspace()->AllocPhysical(
73+
"pci_ecam", size, /* size */
74+
(void **)&ecam_ptr_, /* returned virtual address */
75+
22, /* alignment log2 */
76+
base_, /* physical address */
77+
0, /* vmm flags */
78+
ARCH_MMU_FLAG_UNCACHED_DEVICE | ARCH_MMU_FLAG_PERM_READ | ARCH_MMU_FLAG_PERM_WRITE);
79+
80+
LTRACEF("vmm_alloc_physical returns %d, ptr %p\n", err, ecam_ptr_);
81+
if (err != ZX_OK) {
82+
ecam_ptr_ = nullptr;
83+
return err;
84+
}
85+
86+
set_last_bus(end_bus_);
87+
88+
return NO_ERROR;
8589
}
8690

8791
// compute the offset into the ecam given the location and register offset
8892
inline size_t location_to_offset(const pci_location_t state, uint32_t reg) {
89-
//
90-
// | 27 - 20 | 19 - 15 | 14 - 12 | 11 - 8 | 7 - 2 | 1 - 0 |
91-
// | Bus Nr | Dev Nr | Function Nr | Ext. Register Nr | Register Nr | Byte Enable |
92-
93-
// TODO: clamp or assert on invalid offset
94-
size_t offset = (size_t)state.bus << 20;
95-
offset += (size_t)state.dev << 15;
96-
offset += (size_t)state.fn << 12;
97-
offset += reg;
98-
return offset;
93+
//
94+
// | 27 - 20 | 19 - 15 | 14 - 12 | 11 - 8 | 7 - 2 | 1 - 0 |
95+
// | Bus Nr | Dev Nr | Function Nr | Ext. Register Nr | Register Nr | Byte Enable |
96+
97+
// TODO: clamp or assert on invalid offset
98+
size_t offset = (size_t)state.bus << 20;
99+
offset += (size_t)state.dev << 15;
100+
offset += (size_t)state.fn << 12;
101+
offset += reg;
102+
return offset;
99103
}
100104

101105
// templatized routines to access the pci config space using a specific type
102106
template <typename T>
103-
inline int read_config(const pci_location_t state, uint32_t reg, T *value, const uint8_t *ecam_ptr) {
104-
auto off = location_to_offset(state, reg);
107+
inline int read_config(const pci_location_t state, uint32_t reg, T *value,
108+
const uint8_t *ecam_ptr) {
109+
auto off = location_to_offset(state, reg);
105110

106-
*value = *reinterpret_cast<const volatile T *>(&ecam_ptr[off]);
111+
*value = *reinterpret_cast<const volatile T *>(&ecam_ptr[off]);
107112

108-
return NO_ERROR;
113+
return NO_ERROR;
109114
}
110115

111116
template <typename T>
112117
inline int write_config(const pci_location_t state, uint32_t reg, T value, uint8_t *ecam_ptr) {
113-
auto off = location_to_offset(state, reg);
118+
auto off = location_to_offset(state, reg);
114119

115-
*reinterpret_cast<volatile T *>(&ecam_ptr[off]) = value;
120+
*reinterpret_cast<volatile T *>(&ecam_ptr[off]) = value;
116121

117-
return NO_ERROR;
122+
return NO_ERROR;
118123
}
119124

120125
int pci_ecam::read_config_byte(const pci_location_t state, uint32_t reg, uint8_t *value) {
121-
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn, reg);
122-
return read_config(state, reg, value, ecam_ptr_);
126+
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn,
127+
reg);
128+
return read_config(state, reg, value, ecam_ptr_);
123129
}
124130

125131
int pci_ecam::read_config_half(const pci_location_t state, uint32_t reg, uint16_t *value) {
126-
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn, reg);
127-
return read_config(state, reg, value, ecam_ptr_);
132+
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn,
133+
reg);
134+
return read_config(state, reg, value, ecam_ptr_);
128135
}
129136

130137
int pci_ecam::read_config_word(const pci_location_t state, uint32_t reg, uint32_t *value) {
131-
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn, reg);
132-
return read_config(state, reg, value, ecam_ptr_);
138+
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn,
139+
reg);
140+
return read_config(state, reg, value, ecam_ptr_);
133141
}
134142

135143
int pci_ecam::write_config_byte(const pci_location_t state, uint32_t reg, uint8_t value) {
136-
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn, reg);
137-
return write_config(state, reg, value, ecam_ptr_);
144+
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn,
145+
reg);
146+
return write_config(state, reg, value, ecam_ptr_);
138147
}
139148

140149
int pci_ecam::write_config_half(const pci_location_t state, uint32_t reg, uint16_t value) {
141-
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn, reg);
142-
return write_config(state, reg, value, ecam_ptr_);
150+
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn,
151+
reg);
152+
return write_config(state, reg, value, ecam_ptr_);
143153
}
144154

145155
int pci_ecam::write_config_word(const pci_location_t state, uint32_t reg, uint32_t value) {
146-
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn, reg);
147-
return write_config(state, reg, value, ecam_ptr_);
156+
LTRACEF_LEVEL(2, "state bus %#hhx dev %#hhx %#hhx reg %#x\n", state.bus, state.dev, state.fn,
157+
reg);
158+
return write_config(state, reg, value, ecam_ptr_);
148159
}

0 commit comments

Comments
 (0)