Serenity Operating System
at portability 195 lines 5.9 kB view raw
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}