mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-27 03:13:23 +00:00
Replace Location with PciDeviceLocation
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
a47b98b160
commit
9bce8b879b
@ -1,4 +1,5 @@
|
|||||||
use crate::util::{CSpaceAccessMethod, Location};
|
use crate::util::CSpaceAccessMethod;
|
||||||
|
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct CapabilityEXPData {
|
pub struct CapabilityEXPData {
|
||||||
@ -9,7 +10,7 @@ pub struct CapabilityEXPData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CapabilityEXPData {
|
impl CapabilityEXPData {
|
||||||
pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self {
|
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||||
let am = CSpaceAccessMethod::IO;
|
let am = CSpaceAccessMethod::IO;
|
||||||
let cap = am.read16(loc, cap_ptr + 0x2);
|
let cap = am.read16(loc, cap_ptr + 0x2);
|
||||||
Self {
|
Self {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! This mod is used in frame to do device initialization
|
//! This mod is used in frame to do device initialization
|
||||||
use crate::util::*;
|
use crate::util::CSpaceAccessMethod;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
exp::CapabilityEXPData, msi::CapabilityMSIData, msix::CapabilityMSIXData, pm::CapabilityPMData,
|
exp::CapabilityEXPData, msi::CapabilityMSIData, msix::CapabilityMSIXData, pm::CapabilityPMData,
|
||||||
@ -70,7 +71,7 @@ pub struct Capability {
|
|||||||
|
|
||||||
impl Capability {
|
impl Capability {
|
||||||
/// get the capabilities of one device
|
/// get the capabilities of one device
|
||||||
pub fn device_capabilities(loc: Location) -> Vec<Self> {
|
pub fn device_capabilities(loc: PciDeviceLocation) -> Vec<Self> {
|
||||||
let mut capabilities = Vec::new();
|
let mut capabilities = Vec::new();
|
||||||
let am = CSpaceAccessMethod::IO;
|
let am = CSpaceAccessMethod::IO;
|
||||||
let mut cap_ptr = am.read8(loc, PCI_CAP_PTR) as u16;
|
let mut cap_ptr = am.read8(loc, PCI_CAP_PTR) as u16;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::util::{CSpaceAccessMethod, Location};
|
use crate::util::CSpaceAccessMethod;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct CapabilityMSIMessageControl: u16 {
|
pub struct CapabilityMSIMessageControl: u16 {
|
||||||
const ADDR64_CAPABLE = 1 << 7;
|
const ADDR64_CAPABLE = 1 << 7;
|
||||||
@ -25,7 +26,7 @@ pub struct CapabilityMSIData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CapabilityMSIData {
|
impl CapabilityMSIData {
|
||||||
pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self {
|
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||||
let am = CSpaceAccessMethod::IO;
|
let am = CSpaceAccessMethod::IO;
|
||||||
let message_control =
|
let message_control =
|
||||||
CapabilityMSIMessageControl::from_bits_truncate(am.read16(loc, cap_ptr + 0x02));
|
CapabilityMSIMessageControl::from_bits_truncate(am.read16(loc, cap_ptr + 0x02));
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::util::*;
|
use crate::util::CSpaceAccessMethod;
|
||||||
|
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -9,7 +10,7 @@ pub struct CapabilityMSIXData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CapabilityMSIXData {
|
impl CapabilityMSIXData {
|
||||||
pub fn new(loc: Location, cap_ptr: u16) -> Self {
|
pub fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||||
let am = CSpaceAccessMethod::IO;
|
let am = CSpaceAccessMethod::IO;
|
||||||
Self {
|
Self {
|
||||||
message_control: am.read16(loc, cap_ptr + 2),
|
message_control: am.read16(loc, cap_ptr + 2),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::util::{CSpaceAccessMethod, Location};
|
use crate::util::CSpaceAccessMethod;
|
||||||
|
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct CapabilityPMData {
|
pub struct CapabilityPMData {
|
||||||
@ -12,7 +13,7 @@ pub struct CapabilityPMData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CapabilityPMData {
|
impl CapabilityPMData {
|
||||||
pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self {
|
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||||
let am = CSpaceAccessMethod::IO;
|
let am = CSpaceAccessMethod::IO;
|
||||||
let cap = am.read32(loc, cap_ptr + 0x4);
|
let cap = am.read32(loc, cap_ptr + 0x4);
|
||||||
Self {
|
Self {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::util::{CSpaceAccessMethod, Location};
|
use crate::util::CSpaceAccessMethod;
|
||||||
|
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct CapabilitySATAData {
|
pub struct CapabilitySATAData {
|
||||||
@ -9,7 +10,7 @@ pub struct CapabilitySATAData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CapabilitySATAData {
|
impl CapabilitySATAData {
|
||||||
pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self {
|
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||||
let am = CSpaceAccessMethod::IO;
|
let am = CSpaceAccessMethod::IO;
|
||||||
let sata_cr0 = am.read32(loc, cap_ptr);
|
let sata_cr0 = am.read32(loc, cap_ptr);
|
||||||
let sata_cr1 = am.read32(loc, cap_ptr + 0x4);
|
let sata_cr1 = am.read32(loc, cap_ptr + 0x4);
|
||||||
|
@ -2,7 +2,8 @@ pub mod virtio;
|
|||||||
|
|
||||||
use virtio::CapabilityVirtioData;
|
use virtio::CapabilityVirtioData;
|
||||||
|
|
||||||
use crate::util::{CSpaceAccessMethod, Location};
|
use crate::util::CSpaceAccessMethod;
|
||||||
|
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum CapabilityVNDRData {
|
pub enum CapabilityVNDRData {
|
||||||
@ -11,7 +12,7 @@ pub enum CapabilityVNDRData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CapabilityVNDRData {
|
impl CapabilityVNDRData {
|
||||||
pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self {
|
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||||
let am = CSpaceAccessMethod::IO;
|
let am = CSpaceAccessMethod::IO;
|
||||||
let vid = am.read16(loc, 0);
|
let vid = am.read16(loc, 0);
|
||||||
match vid {
|
match vid {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::util::*;
|
use crate::util::CSpaceAccessMethod;
|
||||||
|
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct CapabilityVirtioData {
|
pub struct CapabilityVirtioData {
|
||||||
@ -10,7 +11,7 @@ pub struct CapabilityVirtioData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CapabilityVirtioData {
|
impl CapabilityVirtioData {
|
||||||
pub(crate) fn new(loc: Location, cap_ptr: u16) -> Self {
|
pub(crate) fn new(loc: PciDeviceLocation, cap_ptr: u16) -> Self {
|
||||||
let am = CSpaceAccessMethod::IO;
|
let am = CSpaceAccessMethod::IO;
|
||||||
let cap_len = am.read8(loc, cap_ptr + 2);
|
let cap_len = am.read8(loc, cap_ptr + 2);
|
||||||
let option = if cap_len > 0x10 {
|
let option = if cap_len > 0x10 {
|
||||||
|
@ -11,10 +11,11 @@ use component::init_component;
|
|||||||
use component::ComponentInitError;
|
use component::ComponentInitError;
|
||||||
|
|
||||||
use alloc::{sync::Arc, vec::Vec};
|
use alloc::{sync::Arc, vec::Vec};
|
||||||
|
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||||
use spin::{mutex::Mutex, Once};
|
use spin::{mutex::Mutex, Once};
|
||||||
use util::CSpaceAccessMethod;
|
use util::CSpaceAccessMethod;
|
||||||
|
|
||||||
pub use crate::util::PCIDevice;
|
pub use crate::util::PciDevice;
|
||||||
|
|
||||||
pub const PCI_COMMAND: u16 = 0x04;
|
pub const PCI_COMMAND: u16 = 0x04;
|
||||||
pub const PCI_BAR: u16 = 0x10;
|
pub const PCI_BAR: u16 = 0x10;
|
||||||
@ -37,28 +38,31 @@ fn pci_component_init() -> Result<(), ComponentInitError> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub struct PCIComponent {
|
pub struct PCIComponent {
|
||||||
pci_device: Mutex<Vec<Arc<PCIDevice>>>,
|
pci_device: Mutex<Vec<Arc<PciDevice>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PCIComponent {
|
impl PCIComponent {
|
||||||
pub fn init() -> Result<Self, ComponentInitError> {
|
pub fn init() -> Result<Self, ComponentInitError> {
|
||||||
let mut devices = Vec::new();
|
let mut devices = Vec::new();
|
||||||
for dev in util::scan_bus(CSpaceAccessMethod::IO) {
|
for location in PciDeviceLocation::all() {
|
||||||
|
let Some(device) = util::find_device(location,CSpaceAccessMethod::IO) else{
|
||||||
|
continue;
|
||||||
|
};
|
||||||
log::info!(
|
log::info!(
|
||||||
"pci: {:02x}:{:02x}.{} {:#x} {:#x} ({} {}) command: {:?} status: {:?} irq: {}:{:?}",
|
"pci: {:02x}:{:02x}.{} {:#x} {:#x} ({} {}) command: {:?} status: {:?} irq: {}:{:?}",
|
||||||
dev.loc.bus,
|
device.loc.bus,
|
||||||
dev.loc.device,
|
device.loc.device,
|
||||||
dev.loc.function,
|
device.loc.function,
|
||||||
dev.id.vendor_id,
|
device.id.vendor_id,
|
||||||
dev.id.device_id,
|
device.id.device_id,
|
||||||
dev.id.class,
|
device.id.class,
|
||||||
dev.id.subclass,
|
device.id.subclass,
|
||||||
dev.command,
|
device.command,
|
||||||
dev.status,
|
device.status,
|
||||||
dev.pic_interrupt_line,
|
device.pic_interrupt_line,
|
||||||
dev.interrupt_pin
|
device.interrupt_pin
|
||||||
);
|
);
|
||||||
devices.push(Arc::new(dev));
|
devices.push(Arc::new(device));
|
||||||
}
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
pci_device: Mutex::new(devices),
|
pci_device: Mutex::new(devices),
|
||||||
@ -75,7 +79,7 @@ impl PCIComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PCIComponent {
|
impl PCIComponent {
|
||||||
pub fn get_pci_devices(self: &Self, index: usize) -> Option<Arc<PCIDevice>> {
|
pub fn get_pci_devices(self: &Self, index: usize) -> Option<Arc<PciDevice>> {
|
||||||
self.pci_device.lock().get(index).cloned()
|
self.pci_device.lock().get(index).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@ use alloc::vec::Vec;
|
|||||||
use log::debug;
|
use log::debug;
|
||||||
use pod::Pod;
|
use pod::Pod;
|
||||||
|
|
||||||
use crate::util::{CSpaceAccessMethod, Location, BAR};
|
use crate::util::{CSpaceAccessMethod, BAR};
|
||||||
|
|
||||||
use super::capability::msix::CapabilityMSIXData;
|
use super::capability::msix::CapabilityMSIXData;
|
||||||
|
|
||||||
use jinux_frame::{offset_of, trap::IrqAllocateHandle};
|
use jinux_frame::{bus::pci::PciDeviceLocation, offset_of, trap::IrqAllocateHandle};
|
||||||
use jinux_util::frame_ptr::InFramePtr;
|
use jinux_util::frame_ptr::InFramePtr;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -37,7 +37,7 @@ impl MSIX {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
cap: &CapabilityMSIXData,
|
cap: &CapabilityMSIXData,
|
||||||
bars: [Option<BAR>; 6],
|
bars: [Option<BAR>; 6],
|
||||||
loc: Location,
|
loc: PciDeviceLocation,
|
||||||
cap_ptr: u16,
|
cap_ptr: u16,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let table_info = cap.table_info;
|
let table_info = cap.table_info;
|
||||||
|
@ -2,6 +2,7 @@ extern crate jinux_frame;
|
|||||||
use crate::capability::Capability;
|
use crate::capability::Capability;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
use jinux_frame::bus::pci::PciDeviceLocation;
|
||||||
|
|
||||||
pub enum PCIDeviceCommonCfgOffset {
|
pub enum PCIDeviceCommonCfgOffset {
|
||||||
VendorId = 0x00,
|
VendorId = 0x00,
|
||||||
@ -46,19 +47,19 @@ pub enum CSpaceAccessMethod {
|
|||||||
// All IO-bus ops are 32-bit, we mask and shift to get the values we want.
|
// All IO-bus ops are 32-bit, we mask and shift to get the values we want.
|
||||||
|
|
||||||
impl CSpaceAccessMethod {
|
impl CSpaceAccessMethod {
|
||||||
pub fn read8(self, loc: Location, offset: u16) -> u8 {
|
pub fn read8(self, loc: PciDeviceLocation, offset: u16) -> u8 {
|
||||||
let val = self.read32(loc, offset & 0b11111100);
|
let val = self.read32(loc, offset & 0b11111100);
|
||||||
((val >> ((offset as usize & 0b11) << 3)) & 0xFF) as u8
|
((val >> ((offset as usize & 0b11) << 3)) & 0xFF) as u8
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a value in native endian.
|
/// Returns a value in native endian.
|
||||||
pub fn read16(self, loc: Location, offset: u16) -> u16 {
|
pub fn read16(self, loc: PciDeviceLocation, offset: u16) -> u16 {
|
||||||
let val = self.read32(loc, offset & 0b11111100);
|
let val = self.read32(loc, offset & 0b11111100);
|
||||||
((val >> ((offset as usize & 0b10) << 3)) & 0xFFFF) as u16
|
((val >> ((offset as usize & 0b10) << 3)) & 0xFFFF) as u16
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a value in native endian.
|
/// Returns a value in native endian.
|
||||||
pub fn read32(self, loc: Location, offset: u16) -> u32 {
|
pub fn read32(self, loc: PciDeviceLocation, offset: u16) -> u32 {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
(offset & 0b11) == 0,
|
(offset & 0b11) == 0,
|
||||||
"misaligned PCI configuration dword u32 read"
|
"misaligned PCI configuration dword u32 read"
|
||||||
@ -66,7 +67,7 @@ impl CSpaceAccessMethod {
|
|||||||
match self {
|
match self {
|
||||||
CSpaceAccessMethod::IO => {
|
CSpaceAccessMethod::IO => {
|
||||||
jinux_frame::arch::x86::device::pci::PCI_ADDRESS_PORT
|
jinux_frame::arch::x86::device::pci::PCI_ADDRESS_PORT
|
||||||
.write(loc.encode() | ((offset as u32) & 0b11111100));
|
.write(loc.encode_as_x86_address_value() | ((offset as u32) & 0b11111100));
|
||||||
jinux_frame::arch::x86::device::pci::PCI_DATA_PORT
|
jinux_frame::arch::x86::device::pci::PCI_DATA_PORT
|
||||||
.read()
|
.read()
|
||||||
.to_le()
|
.to_le()
|
||||||
@ -77,7 +78,7 @@ impl CSpaceAccessMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write8(self, loc: Location, offset: u16, val: u8) {
|
pub fn write8(self, loc: PciDeviceLocation, offset: u16, val: u8) {
|
||||||
let old = self.read32(loc, offset & (0xFFFC));
|
let old = self.read32(loc, offset & (0xFFFC));
|
||||||
let dest = offset as usize & 0b11 << 3;
|
let dest = offset as usize & 0b11 << 3;
|
||||||
let mask = (0xFF << dest) as u32;
|
let mask = (0xFF << dest) as u32;
|
||||||
@ -89,7 +90,7 @@ impl CSpaceAccessMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Converts val to little endian before writing.
|
/// Converts val to little endian before writing.
|
||||||
pub fn write16(self, loc: Location, offset: u16, val: u16) {
|
pub fn write16(self, loc: PciDeviceLocation, offset: u16, val: u16) {
|
||||||
let old = self.read32(loc, offset & (0xFFFC));
|
let old = self.read32(loc, offset & (0xFFFC));
|
||||||
let dest = offset as usize & 0b10 << 3;
|
let dest = offset as usize & 0b10 << 3;
|
||||||
let mask = (0xFFFF << dest) as u32;
|
let mask = (0xFFFF << dest) as u32;
|
||||||
@ -102,7 +103,7 @@ impl CSpaceAccessMethod {
|
|||||||
|
|
||||||
/// Takes a value in native endian, converts it to little-endian, and writes it to the PCI
|
/// Takes a value in native endian, converts it to little-endian, and writes it to the PCI
|
||||||
/// device configuration space at register `offset`.
|
/// device configuration space at register `offset`.
|
||||||
pub fn write32(self, loc: Location, offset: u16, val: u32) {
|
pub fn write32(self, loc: PciDeviceLocation, offset: u16, val: u32) {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
(offset & 0b11) == 0,
|
(offset & 0b11) == 0,
|
||||||
"misaligned PCI configuration dword u32 read"
|
"misaligned PCI configuration dword u32 read"
|
||||||
@ -110,7 +111,7 @@ impl CSpaceAccessMethod {
|
|||||||
match self {
|
match self {
|
||||||
CSpaceAccessMethod::IO => {
|
CSpaceAccessMethod::IO => {
|
||||||
jinux_frame::arch::x86::device::pci::PCI_ADDRESS_PORT
|
jinux_frame::arch::x86::device::pci::PCI_ADDRESS_PORT
|
||||||
.write(loc.encode() | (offset as u32 & 0b11111100));
|
.write(loc.encode_as_x86_address_value() | (offset as u32 & 0b11111100));
|
||||||
jinux_frame::arch::x86::device::pci::PCI_DATA_PORT.write(val.to_le())
|
jinux_frame::arch::x86::device::pci::PCI_DATA_PORT.write(val.to_le())
|
||||||
} //MemoryMapped(ptr) => {
|
} //MemoryMapped(ptr) => {
|
||||||
// // FIXME: Clarify whether the rules for GEP/GEPi forbid using regular .offset() here.
|
// // FIXME: Clarify whether the rules for GEP/GEPi forbid using regular .offset() here.
|
||||||
@ -120,24 +121,6 @@ impl CSpaceAccessMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Physical location of a device on the bus
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct Location {
|
|
||||||
pub bus: u8,
|
|
||||||
pub device: u8,
|
|
||||||
pub function: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Location {
|
|
||||||
#[inline(always)]
|
|
||||||
fn encode(self) -> u32 {
|
|
||||||
(1 << 31)
|
|
||||||
| ((self.bus as u32) << 16)
|
|
||||||
| (((self.device as u32) & 0b11111) << 11)
|
|
||||||
| (((self.function as u32) & 0b111) << 8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct Identifier {
|
pub struct Identifier {
|
||||||
pub vendor_id: u16,
|
pub vendor_id: u16,
|
||||||
@ -215,8 +198,8 @@ bitflags! {
|
|||||||
///
|
///
|
||||||
/// Although accessing configuration space may be expensive, it is not cached.
|
/// Although accessing configuration space may be expensive, it is not cached.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct PCIDevice {
|
pub struct PciDevice {
|
||||||
pub loc: Location,
|
pub loc: PciDeviceLocation,
|
||||||
pub id: Identifier,
|
pub id: Identifier,
|
||||||
pub command: Command,
|
pub command: Command,
|
||||||
pub status: Status,
|
pub status: Status,
|
||||||
@ -232,7 +215,7 @@ pub struct PCIDevice {
|
|||||||
pub capabilities: Vec<Capability>,
|
pub capabilities: Vec<Capability>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PCIDevice {
|
impl PciDevice {
|
||||||
/// set the status bits
|
/// set the status bits
|
||||||
pub fn set_status_bits(&self, status: Status) {
|
pub fn set_status_bits(&self, status: Status) {
|
||||||
let am = CSpaceAccessMethod::IO;
|
let am = CSpaceAccessMethod::IO;
|
||||||
@ -328,7 +311,11 @@ pub enum BAR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BAR {
|
impl BAR {
|
||||||
pub fn decode(loc: Location, am: CSpaceAccessMethod, idx: u16) -> (Option<BAR>, usize) {
|
pub fn decode(
|
||||||
|
loc: PciDeviceLocation,
|
||||||
|
am: CSpaceAccessMethod,
|
||||||
|
idx: u16,
|
||||||
|
) -> (Option<BAR>, usize) {
|
||||||
let raw = am.read32(loc, 16 + (idx << 2));
|
let raw = am.read32(loc, 16 + (idx << 2));
|
||||||
am.write32(loc, 16 + (idx << 2), !0);
|
am.write32(loc, 16 + (idx << 2), !0);
|
||||||
let len_encoded = am.read32(loc, 16 + (idx << 2));
|
let len_encoded = am.read32(loc, 16 + (idx << 2));
|
||||||
@ -370,66 +357,7 @@ impl BAR {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct BusScan {
|
pub(crate) fn find_device(loc: PciDeviceLocation, am: CSpaceAccessMethod) -> Option<PciDevice> {
|
||||||
loc: Location,
|
|
||||||
am: CSpaceAccessMethod,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BusScan {
|
|
||||||
fn done(&self) -> bool {
|
|
||||||
if self.loc.bus == 255 && self.loc.device == 31 && self.loc.function == 7 {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn increment(&mut self) {
|
|
||||||
// TODO: Decide whether this is actually nicer than taking a u16 and incrementing until it
|
|
||||||
// wraps.
|
|
||||||
if self.loc.function < 7 {
|
|
||||||
self.loc.function += 1;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
self.loc.function = 0;
|
|
||||||
if self.loc.device < 31 {
|
|
||||||
self.loc.device += 1;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
self.loc.device = 0;
|
|
||||||
if self.loc.bus == 255 {
|
|
||||||
self.loc.device = 31;
|
|
||||||
self.loc.device = 7;
|
|
||||||
} else {
|
|
||||||
self.loc.bus += 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::core::iter::Iterator for BusScan {
|
|
||||||
type Item = PCIDevice;
|
|
||||||
#[inline]
|
|
||||||
fn next(&mut self) -> Option<PCIDevice> {
|
|
||||||
// FIXME: very naive atm, could be smarter and waste much less time by only scanning used
|
|
||||||
// busses.
|
|
||||||
let mut ret = None;
|
|
||||||
loop {
|
|
||||||
if self.done() {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = probe_function(self.loc, self.am);
|
|
||||||
self.increment();
|
|
||||||
if ret.is_some() {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn probe_function(loc: Location, am: CSpaceAccessMethod) -> Option<PCIDevice> {
|
|
||||||
// FIXME: it'd be more efficient to use read32 and decode separately.
|
// FIXME: it'd be more efficient to use read32 and decode separately.
|
||||||
let vid = am.read16(loc, 0);
|
let vid = am.read16(loc, 0);
|
||||||
if vid == 0xFFFF {
|
if vid == 0xFFFF {
|
||||||
@ -551,7 +479,7 @@ fn probe_function(loc: Location, am: CSpaceAccessMethod) -> Option<PCIDevice> {
|
|||||||
i = next;
|
i = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(PCIDevice {
|
Some(PciDevice {
|
||||||
loc: loc,
|
loc: loc,
|
||||||
id: id,
|
id: id,
|
||||||
command: command,
|
command: command,
|
||||||
@ -568,14 +496,3 @@ fn probe_function(loc: Location, am: CSpaceAccessMethod) -> Option<PCIDevice> {
|
|||||||
capabilities: capabilities,
|
capabilities: capabilities,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn scan_bus(am: CSpaceAccessMethod) -> BusScan {
|
|
||||||
BusScan {
|
|
||||||
loc: Location {
|
|
||||||
bus: 0,
|
|
||||||
device: 0,
|
|
||||||
function: 0,
|
|
||||||
},
|
|
||||||
am: am,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -13,7 +13,7 @@ use bitflags::bitflags;
|
|||||||
use component::ComponentInitError;
|
use component::ComponentInitError;
|
||||||
use device::VirtioDevice;
|
use device::VirtioDevice;
|
||||||
use jinux_frame::{offset_of, trap::TrapFrame};
|
use jinux_frame::{offset_of, trap::TrapFrame};
|
||||||
use jinux_pci::util::{PCIDevice, BAR};
|
use jinux_pci::{util::BAR, PciDevice};
|
||||||
use jinux_util::frame_ptr::InFramePtr;
|
use jinux_util::frame_ptr::InFramePtr;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use pod::Pod;
|
use pod::Pod;
|
||||||
@ -226,7 +226,7 @@ pub struct PCIVirtioDevice {
|
|||||||
|
|
||||||
impl PCIVirtioDevice {
|
impl PCIVirtioDevice {
|
||||||
/// create a new PCI Virtio Device, note that this function will stop with device status features ok
|
/// create a new PCI Virtio Device, note that this function will stop with device status features ok
|
||||||
pub fn new(dev: Arc<PCIDevice>) -> Self {
|
pub fn new(dev: Arc<PciDevice>) -> Self {
|
||||||
assert_eq!(dev.id.vendor_id, 0x1af4);
|
assert_eq!(dev.id.vendor_id, 0x1af4);
|
||||||
let device_type = match dev.id.device_id {
|
let device_type = match dev.id.device_id {
|
||||||
0x1000 | 0x1041 => VirtioDeviceType::Network,
|
0x1000 | 0x1041 => VirtioDeviceType::Network,
|
||||||
|
Reference in New Issue
Block a user