The Pedigree Project 0.1
Pci.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef PCI_COMMON_H
21#define PCI_COMMON_H
22
23#include "pedigree/kernel/compiler.h"
24#include "pedigree/kernel/machine/PciExtendedCapabilities.h"
25#include "pedigree/kernel/machine/PciFunctionState.h"
26#include "pedigree/kernel/processor/types.h"
27
28class Device;
29
31class EXPORTED_PUBLIC PciBus {
32 public:
33 class DmaMapping {
34 public:
35 DmaMapping() = default;
36 ~DmaMapping() {
37 release();
38 }
39 DmaMapping(const DmaMapping&) = delete;
40 DmaMapping& operator=(const DmaMapping&) = delete;
41
42 uint32_t address() const {
43 return m_Address;
44 }
45 void release();
46
47 private:
48 friend class PciBus;
49 Device* m_Device = nullptr;
50 uint32_t m_Address = 0;
51 uint16_t m_Token = 0;
52 };
53
54 PciBus();
55 virtual ~PciBus();
56
57 static PciBus& instance() {
58 return m_Instance;
59 }
60
64 void initialise();
65
71 uint32_t readConfigSpace(Device* pDev, uint8_t offset);
72
80 uint32_t readConfigSpace(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset);
81
88 void writeConfigSpace(Device* pDev, uint8_t offset, uint32_t data);
89
98 void writeConfigSpace(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset,
99 uint32_t data);
100
101 // Byte offsets, checked before I/O; subword writes never touch adjacent W1C fields.
102 bool readConfig8(Device* device, uint16_t offset, uint8_t& value);
103 bool readConfig16(Device* device, uint16_t offset, uint16_t& value);
104 bool readConfig32(Device* device, uint16_t offset, uint32_t& value);
105 bool writeConfig8(Device* device, uint16_t offset, uint8_t value);
106 bool writeConfig16(Device* device, uint16_t offset, uint16_t value);
107 bool writeConfig32(Device* device, uint16_t offset, uint32_t value);
108 PciExtendedCapabilities::FindResult findExtendedCapability(
109 Device* device, uint16_t id, PciExtendedCapabilities::Capability& result);
110 // Reserve a level-triggered PIC line before programming a chipset route.
111 bool reserveLegacyInterrupt(uint8_t irq);
112 bool updateCommand(Device* device, uint16_t clearBits, uint16_t setBits);
113 bool inspectFunction(Device* device, PciFunctionState::State& state,
114 bool requireLegacyInterrupt = true);
115 bool disableMessageInterrupts(Device* device, const PciFunctionState::State& state);
116 bool enableMsi(Device* device, uint64_t address, uint16_t data);
117 bool disableMsi(Device* device);
118 bool enableMsix(Device* device, uint64_t address, uint32_t data);
119 bool enableMsixVectors(Device* device, uint64_t address, const uint32_t* data, size_t count,
120 bool* touched = nullptr, const uint64_t* addresses = nullptr);
121 bool setMsixVectorMask(Device* device, size_t index, bool masked);
122 bool disableMsix(Device* device);
123 bool resourcesUnchanged(Device* device, const PciFunctionState::State& state);
125 bool translateAddress(uint64_t pciAddress, uint64_t bytes, bool io, uint64_t& cpuPhysical);
127 bool busRange(uint8_t& first, uint8_t& last);
128 uint32_t interruptRoute(uint8_t bus, uint8_t device, uint8_t function, uint8_t pin);
130 bool assignBar(Device* device, uint8_t index, uint32_t low, uint32_t high, uint32_t maskLow,
131 uint32_t maskHigh);
133 bool attachDmaRemapping(Device* device);
134 bool hasDmaRemapping(Device* device) const;
136 bool attachIsolatedDma(Device* device);
138 bool detachIsolatedDma(Device* device);
140 bool isolatedDmaIdle(Device* device) const;
142 bool detachDisabledIsolatedDma(Device* device);
143 bool hasDmaIsolation(Device* device) const;
145 bool mapDmaPage(Device* device, physical_uintptr_t physical, size_t bytes, DmaMapping& mapping);
146 void unmapDmaPage(Device* device, uint16_t token);
147
148 struct ConfigSpace {
149 uint16_t vendor;
150 uint16_t device;
151 uint16_t command;
152 uint16_t status;
153 uint8_t revision;
154 uint8_t progif;
155 uint8_t subclass;
156 uint8_t class_code;
157 uint8_t cache_line_size;
158 uint8_t latency_timer;
159 uint8_t header_type;
160 uint8_t bist;
161 uint32_t bar[6];
162 uint32_t cardbus_pointer;
163 uint16_t subsys_vendor;
164 uint16_t subsys_id;
165 uint32_t rom_base_address;
166 uint32_t reserved0;
167 uint32_t reserved1;
168 uint8_t interrupt_line;
169 uint8_t interrupt_pin;
170 uint8_t min_grant;
171 uint8_t max_latency;
172 } __attribute__((packed));
173
174 private:
175 static PciBus m_Instance;
176};
177
178inline void PciBus::DmaMapping::release() {
179 if (m_Token) {
180 PciBus::instance().unmapDmaPage(m_Device, m_Token);
181 }
182 m_Device = nullptr;
183 m_Address = 0;
184 m_Token = 0;
185}
186
187inline PciExtendedCapabilities::FindResult PciBus::findExtendedCapability(
188 Device* device, uint16_t id, PciExtendedCapabilities::Capability& result) {
189 if (!device) {
190 return PciExtendedCapabilities::FindResult::Unavailable;
191 }
192 struct Config {
193 PciBus& bus;
194 Device* device;
195 bool read32(uint16_t offset, uint32_t& value) {
196 return bus.readConfig32(device, offset, value);
197 }
198 } config{*this, device};
199 return PciExtendedCapabilities::find(config, id, result);
200}
201
202#endif
Definition Pci.h:31