Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
185 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
// PhoeniX OS Stub hello module | ||
// Copyright © 2019 Yury Popov a.k.a. PhoeniX | ||
|
||
#include "kernmod.hpp" | ||
|
||
MODDESC(name, "Driver/PCI"); | ||
MODDESC(version, "1.0"); | ||
MODDESC(description, "Generic PCI Driver"); | ||
MODDESC(requirements, "port/CF8-CFF"); | ||
MODDESC(developer, "PhoeniX"); | ||
|
||
static inline void putl(uint32_t l) { | ||
char buf[11]; | ||
int off = 10; | ||
buf[off] = 0; | ||
while (off == 10 || l > 0) { | ||
buf[--off] = '0' + (l % 10); | ||
l /= 10; | ||
} | ||
puts(buf + off); | ||
} | ||
|
||
static inline void putx(uint32_t l) { | ||
char buf[9]; | ||
int off = 8; | ||
buf[off] = 0; | ||
while (off == 8 || l > 0) { | ||
char c = static_cast<char>(l & 0xF); | ||
buf[--off] = (c < 10) ? ('0' + c) : ('a' + c - 10); | ||
l /= 16; | ||
c = static_cast<char>(l & 0xF); | ||
buf[--off] = (c < 10) ? ('0' + c) : ('a' + c - 10); | ||
l /= 16; | ||
} | ||
puts(buf + off); | ||
} | ||
|
||
namespace PCI { | ||
static inline uint32_t readConfig32(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { | ||
uint32_t address, value; | ||
address = 0x80000000u | | ||
(uint32_t(bus) << 16) | | ||
(uint32_t(slot) << 11) | | ||
(uint32_t(func) << 8) | | ||
(uint32_t(offset) & 0xFC); | ||
asm volatile( | ||
"mov $0xCF8, %%dx\n" | ||
"outl %%eax, %%dx\n" | ||
"add $4, %%dx\n" | ||
"inl %%dx, %%eax" | ||
:"=a"(value):"a"(address):"dx"); | ||
return value; | ||
} | ||
struct Device { | ||
uint16_t vendor, device; | ||
uint16_t command, status; | ||
uint8_t revision, prog_if, subclass, classcode; | ||
uint8_t cache_line_size, latency_timer, header_type, bist; | ||
union { | ||
struct { | ||
uint32_t bar[6]; | ||
uint32_t cardbus_cis; | ||
uint16_t subsystem_vendor, subsystem_id; | ||
uint32_t rom_base; | ||
uint8_t caps_ptr, rsvd[3+4]; | ||
uint8_t intr_line, intr_pin, min_grant, max_latency; | ||
} __attribute__((packed)) device; | ||
struct { | ||
uint32_t bar[2]; | ||
uint8_t prim_bus_num, sec_bus_num, sub_bus_num, sec_latency_timer; | ||
uint8_t iobase, iolimit; uint16_t sec_status; | ||
uint16_t membase, memlim; | ||
uint16_t pref_membase, pref_memlim; | ||
uint32_t pref_membase_u32; | ||
uint32_t pref_memlim_u32; | ||
uint16_t iobase_u16, iolim_u16; | ||
uint8_t caps_ptr, rsvd[3]; | ||
uint32_t rom_base; | ||
uint8_t intr_line, intr_pin; uint16_t bridgectl; | ||
} __attribute__((packed)) pcibridge; | ||
struct { | ||
uint32_t cardbus_sock_exca_base; | ||
uint8_t cap_off, rsvd; uint16_t sec_status; | ||
uint8_t pci_bus_num, cardbus_bus_num, sub_bus_num, cardbus_lat_timer; | ||
uint32_t membase0, memlim0; | ||
uint32_t membase1, memlim1; | ||
uint32_t iobase0, iolim0; | ||
uint32_t iobase1, iolim1; | ||
uint8_t intr_line, intr_pin, bridgectl; | ||
uint16_t sub_device, sub_vendor; | ||
uint32_t pccard_base; | ||
} __attribute__((packed)) cardbusbridge; | ||
} __attribute__((packed)) _spec; | ||
|
||
template<typename T> static inline T read(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { | ||
return T(readConfig32(bus, slot, func, offset) >> ((offset & 0x3) * 8)); | ||
} | ||
static inline uint8_t getHeaderType(uint8_t bus, uint8_t slot, uint8_t func) { | ||
return read<uint8_t>(bus, slot, func, offsetof(Device, header_type)); | ||
} | ||
static inline uint16_t getVendorID(uint8_t bus, uint8_t slot, uint8_t func) { | ||
return read<uint16_t>(bus, slot, func, offsetof(Device, vendor)); | ||
} | ||
static inline uint16_t getDeviceID(uint8_t bus, uint8_t slot, uint8_t func) { | ||
return read<uint16_t>(bus, slot, func, offsetof(Device, device)); | ||
} | ||
static inline uint8_t getBaseClass(uint8_t bus, uint8_t slot, uint8_t func) { | ||
return read<uint8_t>(bus, slot, func, offsetof(Device, classcode)); | ||
} | ||
static inline uint8_t getSubClass(uint8_t bus, uint8_t slot, uint8_t func) { | ||
return read<uint8_t>(bus, slot, func, offsetof(Device, subclass)); | ||
} | ||
static inline uint8_t getProgIf(uint8_t bus, uint8_t slot, uint8_t func) { | ||
return read<uint8_t>(bus, slot, func, offsetof(Device, prog_if)); | ||
} | ||
static inline uint8_t getRevision(uint8_t bus, uint8_t slot, uint8_t func) { | ||
return read<uint8_t>(bus, slot, func, offsetof(Device, revision)); | ||
} | ||
static inline uint8_t getSecondaryBus(uint8_t bus, uint8_t slot, uint8_t func) { | ||
return read<uint8_t>(bus, slot, func, offsetof(Device, _spec.pcibridge.sec_bus_num)); | ||
} | ||
} __attribute__((packed)); | ||
static void provideDevice(uint8_t bus, uint8_t device, uint8_t function) { | ||
uint8_t baseClass = Device::getBaseClass(bus, device, function); | ||
uint8_t subClass = Device::getSubClass(bus, device, function); | ||
uint8_t progIf = Device::getProgIf(bus, device, function); | ||
uint8_t rev = Device::getRevision(bus, device, function); | ||
puts("TODO: Provide device: "); | ||
uint16_t vendorID = Device::getVendorID(bus, device, function); | ||
uint16_t deviceId = Device::getDeviceID(bus, device, function); | ||
putl(bus); puts("."); putl(device); puts("."); putl(function); puts(" => "); | ||
puts("["); putx(uint32_t(baseClass << 8) | subClass); puts("."); putx(progIf); puts("."); putx(rev); puts("]"); | ||
putx(vendorID); puts("."); putx(deviceId); | ||
puts("\n"); | ||
} | ||
static void scanBus(uint8_t bus); | ||
static void scanFunction(uint8_t bus, uint8_t device, uint8_t function) { | ||
uint8_t baseClass = Device::getBaseClass(bus, device, function); | ||
uint8_t subClass = Device::getSubClass(bus, device, function); | ||
if ((baseClass == 0x06) && (subClass == 0x04)) { | ||
uint8_t secondaryBus = Device::getSecondaryBus(bus, device, function); | ||
scanBus(secondaryBus); | ||
} else { | ||
provideDevice(bus, device, function); | ||
} | ||
} | ||
static void scanDevice(uint8_t bus, uint8_t device) { | ||
uint8_t function = 0; | ||
uint16_t vendorID = Device::getVendorID(bus, device, function); | ||
if (vendorID == 0xFFFF) return; | ||
scanFunction(bus, device, function); | ||
uint8_t headerType = Device::getHeaderType(bus, device, function); | ||
if ((headerType & 0x80) != 0) { | ||
for (function = 1; function < 8; function++) { | ||
if (Device::getVendorID(bus, device, function) != 0xFFFF) { | ||
scanFunction(bus, device, function); | ||
} | ||
} | ||
} | ||
} | ||
static void scanBus(uint8_t bus) { | ||
static uint64_t checked = 0; | ||
if (checked & (1llu << bus)) return; | ||
checked |= (1llu << bus); | ||
for (uint8_t device = 0; device < 32; device++) { | ||
scanDevice(bus, device); | ||
} | ||
} | ||
static void scanAllBuses() { | ||
uint8_t headerType = Device::getHeaderType(0, 0, 0); | ||
if ((headerType & 0x80) == 0) { | ||
scanBus(0); | ||
} else { | ||
for (uint8_t function = 0; function < 8; function++) { | ||
if (Device::getVendorID(0, 0, function) != 0xFFFF) break; | ||
scanBus(function); | ||
} | ||
} | ||
} | ||
} // namespace PCI | ||
|
||
void module() { | ||
PCI::scanAllBuses(); | ||
exit(0); | ||
} |
File renamed without changes.
This file was deleted.
Oops, something went wrong.