Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include <AK/Function.h>
30#include <AK/Types.h>
31
32namespace Kernel {
33
34
35#define PCI_VENDOR_ID 0x00 // word
36#define PCI_DEVICE_ID 0x02 // word
37#define PCI_COMMAND 0x04 // word
38#define PCI_STATUS 0x06 // word
39#define PCI_REVISION_ID 0x08 // byte
40#define PCI_PROG_IF 0x09 // byte
41#define PCI_SUBCLASS 0x0a // byte
42#define PCI_CLASS 0x0b // byte
43#define PCI_CACHE_LINE_SIZE 0x0c // byte
44#define PCI_LATENCY_TIMER 0x0d // byte
45#define PCI_HEADER_TYPE 0x0e // byte
46#define PCI_BIST 0x0f // byte
47#define PCI_BAR0 0x10 // u32
48#define PCI_BAR1 0x14 // u32
49#define PCI_BAR2 0x18 // u32
50#define PCI_BAR3 0x1C // u32
51#define PCI_BAR4 0x20 // u32
52#define PCI_BAR5 0x24 // u32
53#define PCI_SUBSYSTEM_ID 0x2C // u16
54#define PCI_SUBSYSTEM_VENDOR_ID 0x2E // u16
55#define PCI_INTERRUPT_LINE 0x3C // byte
56#define PCI_SECONDARY_BUS 0x19 // byte
57#define PCI_HEADER_TYPE_DEVICE 0
58#define PCI_HEADER_TYPE_BRIDGE 1
59#define PCI_TYPE_BRIDGE 0x0604
60#define PCI_ADDRESS_PORT 0xCF8
61#define PCI_VALUE_PORT 0xCFC
62#define PCI_NONE 0xFFFF
63#define PCI_MAX_DEVICES_PER_BUS 32
64#define PCI_MAX_BUSES 256
65#define PCI_MAX_FUNCTIONS_PER_DEVICE 8
66
67//#define PCI_DEBUG 1
68
69namespace PCI {
70struct ID {
71 u16 vendor_id { 0 };
72 u16 device_id { 0 };
73
74 bool is_null() const { return !vendor_id && !device_id; }
75
76 bool operator==(const ID& other) const
77 {
78 return vendor_id == other.vendor_id && device_id == other.device_id;
79 }
80 bool operator!=(const ID& other) const
81 {
82 return vendor_id != other.vendor_id || device_id != other.device_id;
83 }
84};
85
86struct Address {
87public:
88 Address() {}
89 Address(u16 seg)
90 : m_seg(seg)
91 , m_bus(0)
92 , m_slot(0)
93 , m_function(0)
94 {
95 }
96 Address(u16 seg, u8 bus, u8 slot, u8 function)
97 : m_seg(seg)
98 , m_bus(bus)
99 , m_slot(slot)
100 , m_function(function)
101 {
102 }
103
104 Address(const Address& address)
105 : m_seg(address.seg())
106 , m_bus(address.bus())
107 , m_slot(address.slot())
108 , m_function(address.function())
109 {
110 }
111
112 bool is_null() const { return !m_bus && !m_slot && !m_function; }
113 operator bool() const { return !is_null(); }
114
115 u16 seg() const { return m_seg; }
116 u8 bus() const { return m_bus; }
117 u8 slot() const { return m_slot; }
118 u8 function() const { return m_function; }
119
120 u32 io_address_for_field(u8 field) const
121 {
122 return 0x80000000u | (m_bus << 16u) | (m_slot << 11u) | (m_function << 8u) | (field & 0xfc);
123 }
124
125protected:
126 u32 m_seg { 0 };
127 u8 m_bus { 0 };
128 u8 m_slot { 0 };
129 u8 m_function { 0 };
130};
131
132struct ChangeableAddress : public Address {
133 ChangeableAddress()
134 : Address(0)
135 {
136 }
137 explicit ChangeableAddress(u16 seg)
138 : Address(seg)
139 {
140 }
141 ChangeableAddress(u16 seg, u8 bus, u8 slot, u8 function)
142 : Address(seg, bus, slot, function)
143 {
144 }
145 void set_seg(u16 seg) { m_seg = seg; }
146 void set_bus(u8 bus) { m_bus = bus; }
147 void set_slot(u8 slot) { m_slot = slot; }
148 void set_function(u8 function) { m_function = function; }
149 bool operator==(const Address& address)
150 {
151 if (m_seg == address.seg() && m_bus == address.bus() && m_slot == address.slot() && m_function == address.function())
152 return true;
153 else
154 return false;
155 }
156 const ChangeableAddress& operator=(const Address& address)
157 {
158 set_seg(address.seg());
159 set_bus(address.bus());
160 set_slot(address.slot());
161 set_function(address.function());
162 return *this;
163 }
164};
165
166ID get_id(PCI::Address);
167void enumerate_all(Function<void(Address, ID)> callback);
168void enable_interrupt_line(Address);
169void disable_interrupt_line(Address);
170u8 get_interrupt_line(Address);
171u32 get_BAR0(Address);
172u32 get_BAR1(Address);
173u32 get_BAR2(Address);
174u32 get_BAR3(Address);
175u32 get_BAR4(Address);
176u32 get_BAR5(Address);
177u8 get_revision_id(Address);
178u8 get_subclass(Address);
179u8 get_class(Address);
180u16 get_subsystem_id(Address);
181u16 get_subsystem_vendor_id(Address);
182size_t get_BAR_Space_Size(Address, u8);
183void enable_bus_mastering(Address);
184void disable_bus_mastering(Address);
185
186class Initializer;
187class Access;
188class MMIOAccess;
189class IOAccess;
190class MMIOSegment;
191class Device;
192
193}
194
195}