[Zion][Yellowstone] First pass at adding PCI ioport access.
This commit is contained in:
parent
f2c2cff98a
commit
b677633248
16 changed files with 337 additions and 199 deletions
|
|
@ -36,13 +36,14 @@ fn spawn_from_vmmo(vmmo_cap: z_cap_t, server_cap: Capability) -> Result<(), ZErr
|
|||
|
||||
#[no_mangle]
|
||||
extern "C" fn main() -> z_err_t {
|
||||
let pci_region = MemoryRegion::from_cap(Capability::take(unsafe { BOOT_PCI_VMMO }))
|
||||
.expect("Failed to create PCI region");
|
||||
let fb_region = MemoryRegion::from_cap(Capability::take(unsafe { BOOT_FRAMEBUFFER_INFO_VMMO }))
|
||||
.expect("Failed to create Framebuffer region");
|
||||
let context = Arc::new(
|
||||
server::YellowstoneServerContext::new(pci_region, fb_region)
|
||||
.expect("Failed to create yellowstone context"),
|
||||
server::YellowstoneServerContext::new(
|
||||
Capability::take(unsafe { BOOT_PCI_VMMO }),
|
||||
fb_region,
|
||||
)
|
||||
.expect("Failed to create yellowstone context"),
|
||||
);
|
||||
let handler = server::YellowstoneServerImpl::new(context.clone());
|
||||
let server = YellowstoneServer::new(handler).expect("Couldn't create yellowstone server");
|
||||
|
|
|
|||
|
|
@ -1,14 +1,29 @@
|
|||
use mammoth::{cap::Capability, mem::MemoryRegion, zion::ZError};
|
||||
use mammoth::{
|
||||
cap::Capability,
|
||||
mem::MemoryRegion,
|
||||
syscall,
|
||||
zion::{kZionPerm_All, ZError},
|
||||
};
|
||||
|
||||
enum PciType {
|
||||
Port(Capability),
|
||||
Memory(MemoryRegion),
|
||||
}
|
||||
|
||||
pub struct PciReader {
|
||||
memory_region: MemoryRegion,
|
||||
internal_type: PciType,
|
||||
}
|
||||
|
||||
type DevPredicate = fn(u8, u8, u8) -> bool;
|
||||
|
||||
impl PciReader {
|
||||
pub fn new(memory_region: MemoryRegion) -> Self {
|
||||
Self { memory_region }
|
||||
pub fn new(capability: Capability) -> Self {
|
||||
let internal_type =
|
||||
match MemoryRegion::from_cap(capability.duplicate(kZionPerm_All).unwrap()) {
|
||||
Ok(mem) => PciType::Memory(mem),
|
||||
Err(_) => PciType::Port(capability),
|
||||
};
|
||||
Self { internal_type }
|
||||
}
|
||||
|
||||
pub fn get_ahci_region(&self) -> Result<Capability, ZError> {
|
||||
|
|
@ -28,15 +43,13 @@ impl PciReader {
|
|||
}
|
||||
|
||||
fn probe_pci(&self, pred: DevPredicate) -> Option<Capability> {
|
||||
let base_header = self.pci_header(0, 0, 0);
|
||||
if (base_header.header_type & 0x80) == 0 {
|
||||
if (self.header_type(0, 0, 0) & 0x80) == 0 {
|
||||
if let Some(dev) = self.probe_bus(pred, 0) {
|
||||
return Some(dev);
|
||||
}
|
||||
} else {
|
||||
for fun in 0..8 {
|
||||
let fun_hdr = self.pci_header(0, 0, fun);
|
||||
if fun_hdr.vendor_id != 0xFFFF {
|
||||
if self.vendor_id(0, 0, fun) != 0xFFFF {
|
||||
if let Some(dev) = self.probe_bus(pred, fun) {
|
||||
return Some(dev);
|
||||
}
|
||||
|
|
@ -56,8 +69,7 @@ impl PciReader {
|
|||
}
|
||||
|
||||
fn probe_device(&self, pred: DevPredicate, bus: u8, dev: u8) -> Option<Capability> {
|
||||
let device_base_header = self.pci_header(bus, dev, 0);
|
||||
if device_base_header.vendor_id == 0xFFFF {
|
||||
if self.vendor_id(bus, dev, 0) == 0xFFFF {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +77,7 @@ impl PciReader {
|
|||
return Some(dev);
|
||||
}
|
||||
|
||||
if (device_base_header.header_type & 0x80) != 0 {
|
||||
if (self.header_type(bus, dev, 0) & 0x80) != 0 {
|
||||
for fun in 1..8 {
|
||||
if let Some(dev) = self.probe_function(pred, bus, dev, fun) {
|
||||
return Some(dev);
|
||||
|
|
@ -76,37 +88,66 @@ impl PciReader {
|
|||
}
|
||||
|
||||
fn probe_function(&self, pred: DevPredicate, bus: u8, dev: u8, fun: u8) -> Option<Capability> {
|
||||
let function_header = self.pci_header(bus, dev, fun);
|
||||
let (class, subclass, prog_interface) = self.class_codes(bus, dev, fun);
|
||||
|
||||
mammoth::debug!(
|
||||
"PCI Function: {:#x} {:#x} {:#x}",
|
||||
function_header.class_code,
|
||||
function_header.subclass,
|
||||
function_header.prog_interface
|
||||
class,
|
||||
subclass,
|
||||
prog_interface
|
||||
);
|
||||
|
||||
if pred(
|
||||
function_header.class_code,
|
||||
function_header.subclass,
|
||||
function_header.prog_interface,
|
||||
) {
|
||||
if pred(class, subclass, prog_interface) {
|
||||
mammoth::debug!("Found!");
|
||||
let offset = pci_header_offset(bus, dev, fun);
|
||||
Some(
|
||||
self.memory_region
|
||||
.duplicate(offset as u64, 0x1000)
|
||||
.expect("Failed to duplicate PCI cap"),
|
||||
)
|
||||
Some(self.create_cap(bus, dev, fun))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn pci_header(&self, bus: u8, dev: u8, fun: u8) -> &PciHeader {
|
||||
let offset = pci_header_offset(bus, dev, fun);
|
||||
let header_slice: &[u8] =
|
||||
&self.memory_region.slice()[offset..offset + size_of::<PciHeader>()];
|
||||
unsafe { header_slice.as_ptr().cast::<PciHeader>().as_ref().unwrap() }
|
||||
fn header_type(&self, bus: u8, dev: u8, fun: u8) -> u8 {
|
||||
let data = self.read_at(bus, dev, fun, 0xC);
|
||||
|
||||
((data >> 16) & 0xFF) as u8
|
||||
}
|
||||
|
||||
fn vendor_id(&self, bus: u8, dev: u8, fun: u8) -> u16 {
|
||||
let data = self.read_at(bus, dev, fun, 0);
|
||||
|
||||
(data & 0xFFFF) as u16
|
||||
}
|
||||
|
||||
fn class_codes(&self, bus: u8, dev: u8, fun: u8) -> (u8, u8, u8) {
|
||||
let data = self.read_at(bus, dev, fun, 0x8);
|
||||
|
||||
let class = (data >> 24) as u8;
|
||||
let subclass = ((data >> 16) & 0xFF) as u8;
|
||||
let prog_if = ((data >> 8) & 0xFF) as u8;
|
||||
|
||||
(class, subclass, prog_if)
|
||||
}
|
||||
|
||||
fn read_at(&self, bus: u8, dev: u8, fun: u8, off: u8) -> u32 {
|
||||
match &self.internal_type {
|
||||
PciType::Memory(region) => {
|
||||
let offset = pci_header_offset(bus, dev, fun);
|
||||
let header_slice: &[u32] = ®ion.slice()[offset..offset + size_of::<PciHeader>()];
|
||||
header_slice[(off >> 2) as usize]
|
||||
}
|
||||
PciType::Port(pci_cap) => syscall::pci_read(pci_cap, bus, dev, fun, off).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_cap(&self, bus: u8, dev: u8, fun: u8) -> Capability {
|
||||
match &self.internal_type {
|
||||
PciType::Memory(region) => {
|
||||
let offset = pci_header_offset(bus, dev, fun);
|
||||
region
|
||||
.duplicate(offset as u64, 0x1000)
|
||||
.expect("Failed to duplicate PCI cap")
|
||||
}
|
||||
PciType::Port(_pci_cap) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,13 +43,11 @@ impl YellowstoneServerContext {
|
|||
green_mask_shift: fb_info.green_mask_shift as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl YellowstoneServerContext {
|
||||
pub fn new(pci_region: MemoryRegion, fb_region: MemoryRegion) -> Result<Self, ZError> {
|
||||
pub fn new(pci_cap: Capability, fb_region: MemoryRegion) -> Result<Self, ZError> {
|
||||
Ok(Self {
|
||||
registration_semaphore: mammoth::sync::Semaphore::new()?,
|
||||
pci_reader: PciReader::new(pci_region),
|
||||
pci_reader: PciReader::new(pci_cap),
|
||||
framebuffer_info_region: fb_region,
|
||||
service_map: Mutex::new(BTreeMap::new()),
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue