Patch ahci (#348)

* Modify the ahci module and delete the useless c code

修改ahci使其不再依赖旧的pci函数
删除旧的pci、msi函数代码
This commit is contained in:
YJwu2023
2023-08-28 15:43:07 +08:00
committed by GitHub
parent f5df0e79c6
commit 8d94ea66a3
18 changed files with 75 additions and 1750 deletions

View File

@ -1,28 +0,0 @@
#include "ia64_msi.h"
/**
* @brief 生成架构相关的msi的message address
*
*/
#define ia64_pci_get_arch_msi_message_address(processor) ((0xfee00000UL | (processor << 12)))
/**
* @brief 生成架构相关的message data
*
*/
#define ia64_pci_get_arch_msi_message_data(vector, processor, edge_trigger, assert) ((uint32_t)((vector & 0xff) | (edge_trigger == 1 ? 0 : (1 << 15)) | ((assert == 0) ? 0 : (1 << 14))))
/**
* @brief 生成msi消息
*
* @param msi_desc msi描述符
* @return struct msi_msg_t* msi消息指针在描述符内
*/
struct msi_msg_t *msi_arch_get_msg(struct msi_desc_t *msi_desc)
{
msi_desc->msg.address_hi = 0;
msi_desc->msg.address_lo = ia64_pci_get_arch_msi_message_address(msi_desc->processor);
msi_desc->msg.data = ia64_pci_get_arch_msi_message_data(msi_desc->irq_num, msi_desc->processor, msi_desc->edge_trigger, msi_desc->assert);
msi_desc->msg.vector_control = 0;
return &(msi_desc->msg);
}

View File

@ -1,11 +0,0 @@
#pragma once
#include <driver/pci/msi.h>
/**
* @brief 生成msi消息
*
* @param msi_desc msi描述符
* @return struct msi_msg_t* msi消息指针在描述符内
*/
struct msi_msg_t *msi_arch_get_msg(struct msi_desc_t *msi_desc);

View File

@ -1,17 +1,17 @@
#pragma once
#include <common/glib.h>
#include<process/ptrace.h>
#include <process/ptrace.h>
// 使用弱引用属性导出kallsyms中的符号表。
// 采用weak属性是由于第一次编译时kallsyms还未链接进来若不使用weak属性则会报错
extern const uint64_t kallsyms_address[] __attribute__((weak));
extern const uint64_t kallsyms_num __attribute__((weak));
extern const uint64_t kallsyms_names_index[] __attribute__((weak));
extern const char* kallsyms_names __attribute__((weak));
extern const char *kallsyms_names __attribute__((weak));
/**
* @brief 追溯内核栈调用情况
*
*
* @param regs 内核栈结构体
*/
void traceback(struct pt_regs * regs);
void traceback(struct pt_regs *regs);

View File

@ -1,10 +1,7 @@
all: ata.o ahci.o
all: ata.o
CFLAGS += -I .
ata.o: ata.c
$(CC) $(CFLAGS) -c ata.c -o ata.o
ahci.o: ahci/ahci.c
$(CC) $(CFLAGS) -c ahci/ahci.c -o ahci/ahci.o
$(CC) $(CFLAGS) -c ata.c -o ata.o

View File

@ -1,32 +0,0 @@
#include "ahci.h"
#include <common/kprint.h>
#include <mm/slab.h>
#include <common/string.h>
#include <common/block.h>
#include <debug/bug.h>
#include <common/kthread.h>
/// @brief 保留了对 pci设备获取 和 mm内存映射 的依赖
void ahci_cpp_init(uint32_t *count_ahci_devices, struct pci_device_structure_header_t *ahci_devs[MAX_AHCI_DEVICES], struct pci_device_structure_general_device_t *gen_devs[MAX_AHCI_DEVICES])
{
kinfo("Initializing AHCI...");
pci_get_device_structure(0x1, 0x6, ahci_devs, count_ahci_devices);
if (*count_ahci_devices == 0)
{
kwarn("There is no AHCI device found on this computer!");
return;
}
for (int i = 0; i < *count_ahci_devices; i++)
{
gen_devs[i] = ((struct pci_device_structure_general_device_t *)(ahci_devs[i]));
}
// 映射ABAR
uint32_t bar5 = gen_devs[0]->BAR5;
rs_map_phys(AHCI_MAPPING_BASE, (ul)(bar5)&PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
kinfo("ABAR mapped!");
}

View File

@ -1,364 +1,5 @@
#pragma once
#include <common/blk_types.h>
#include <driver/pci/pci.h>
#include <mm/mm.h>
/**
* @todo 加入io调度器当操作系统实现了多进程之后要加入这个
*
*/
#define AHCI_MAPPING_BASE SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + AHCI_MAPPING_OFFSET
#define MAX_AHCI_DEVICES 100
#define HBA_PxCMD_ST 0x0001
#define HBA_PxCMD_FRE 0x0010
#define HBA_PxCMD_FR 0x4000
#define HBA_PxCMD_CR 0x8000
#define AHCI_DEV_BUSY 0x80
#define AHCI_DEV_DRQ 0x08
#define AHCI_CMD_READ_DMA_EXT 0x25
#define AHCI_CMD_WRITE_DMA_EXT 0x30
#define HBA_PxIS_TFES (1 << 30) /* TFES - Task File Error Status */
#define AHCI_SUCCESS 0 // 请求成功
#define E_NOEMPTYSLOT 1 // 没有空闲的slot
#define E_PORT_HUNG 2 // 端口被挂起
#define E_TASK_FILE_ERROR 3 // 任务文件错误
#define E_UNSUPPORTED_CMD 4 // 不支持的命令
extern struct block_device_operation ahci_operation;
/**
* @brief 在SATA3.0规范中定义的Frame Information Structure类型
*
*/
typedef enum
{
FIS_TYPE_REG_H2D = 0x27, // Register FIS - host to device
FIS_TYPE_REG_D2H = 0x34, // Register FIS - device to host
FIS_TYPE_DMA_ACT = 0x39, // DMA activate FIS - device to host
FIS_TYPE_DMA_SETUP = 0x41, // DMA setup FIS - bidirectional
FIS_TYPE_DATA = 0x46, // Data FIS - bidirectional
FIS_TYPE_BIST = 0x58, // BIST activate FIS - bidirectional
FIS_TYPE_PIO_SETUP = 0x5F, // PIO setup FIS - device to host
FIS_TYPE_DEV_BITS = 0xA1, // Set device bits FIS - device to host
} FIS_TYPE;
/**
* @brief FIS_REG_H2D 被用于从主机向设备发送控制命令
* 注意reserved bit应当被清零
*/
typedef struct tagFIS_REG_H2D
{
// DWORD 0
uint8_t fis_type; // FIS_TYPE_REG_H2D
uint8_t pmport : 4; // Port multiplier
uint8_t rsv0 : 3; // Reserved
uint8_t c : 1; // 1: Command, 0: Control
uint8_t command; // Command register
uint8_t featurel; // Feature register, 7:0
// DWORD 1
uint8_t lba0; // LBA low register, 7:0
uint8_t lba1; // LBA mid register, 15:8
uint8_t lba2; // LBA high register, 23:16
uint8_t device; // Device register
// DWORD 2
uint8_t lba3; // LBA register, 31:24
uint8_t lba4; // LBA register, 39:32
uint8_t lba5; // LBA register, 47:40
uint8_t featureh; // Feature register, 15:8
// DWORD 3
uint8_t countl; // Count register, 7:0
uint8_t counth; // Count register, 15:8
uint8_t icc; // Isochronous command completion
uint8_t control; // Control register
// DWORD 4
uint8_t rsv1[4]; // Reserved
} FIS_REG_H2D;
// A device to host register FIS is used by the device to notify the host that some ATA register has changed.
// It contains the updated task files such as status, error and other registers.
typedef struct tagFIS_REG_D2H
{
// DWORD 0
uint8_t fis_type; // FIS_TYPE_REG_D2H
uint8_t pmport : 4; // Port multiplier
uint8_t rsv0 : 2; // Reserved
uint8_t i : 1; // Interrupt bit
uint8_t rsv1 : 1; // Reserved
uint8_t status; // Status register
uint8_t error; // Error register
// DWORD 1
uint8_t lba0; // LBA low register, 7:0
uint8_t lba1; // LBA mid register, 15:8
uint8_t lba2; // LBA high register, 23:16
uint8_t device; // Device register
// DWORD 2
uint8_t lba3; // LBA register, 31:24
uint8_t lba4; // LBA register, 39:32
uint8_t lba5; // LBA register, 47:40
uint8_t rsv2; // Reserved
// DWORD 3
uint8_t countl; // Count register, 7:0
uint8_t counth; // Count register, 15:8
uint8_t rsv3[2]; // Reserved
// DWORD 4
uint8_t rsv4[4]; // Reserved
} FIS_REG_D2H;
// This FIS is used by the host or device to send data payload. The data size can be varied.
typedef struct tagFIS_DATA
{
// DWORD 0
uint8_t fis_type; // FIS_TYPE_DATA
uint8_t pmport : 4; // Port multiplier
uint8_t rsv0 : 4; // Reserved
uint8_t rsv1[2]; // Reserved
// DWORD 1 ~ N
uint32_t data[1]; // Payload
} FIS_DATA;
// This FIS is used by the device to tell the host that its about to send or ready to receive a PIO data payload.
typedef struct tagFIS_PIO_SETUP
{
// DWORD 0
uint8_t fis_type; // FIS_TYPE_PIO_SETUP
uint8_t pmport : 4; // Port multiplier
uint8_t rsv0 : 1; // Reserved
uint8_t d : 1; // Data transfer direction, 1 - device to host
uint8_t i : 1; // Interrupt bit
uint8_t rsv1 : 1;
uint8_t status; // Status register
uint8_t error; // Error register
// DWORD 1
uint8_t lba0; // LBA low register, 7:0
uint8_t lba1; // LBA mid register, 15:8
uint8_t lba2; // LBA high register, 23:16
uint8_t device; // Device register
// DWORD 2
uint8_t lba3; // LBA register, 31:24
uint8_t lba4; // LBA register, 39:32
uint8_t lba5; // LBA register, 47:40
uint8_t rsv2; // Reserved
// DWORD 3
uint8_t countl; // Count register, 7:0
uint8_t counth; // Count register, 15:8
uint8_t rsv3; // Reserved
uint8_t e_status; // New value of status register
// DWORD 4
uint16_t tc; // Transfer count
uint8_t rsv4[2]; // Reserved
} FIS_PIO_SETUP;
typedef struct tagFIS_DMA_SETUP
{
// DWORD 0
uint8_t fis_type; // FIS_TYPE_DMA_SETUP
uint8_t pmport : 4; // Port multiplier
uint8_t rsv0 : 1; // Reserved
uint8_t d : 1; // Data transfer direction, 1 - device to host
uint8_t i : 1; // Interrupt bit
uint8_t a : 1; // Auto-activate. Specifies if DMA Activate FIS is needed
uint8_t rsved[2]; // Reserved
// DWORD 1&2
uint64_t DMAbufferID; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory.
// SATA Spec says host specific and not in Spec. Trying AHCI spec might work.
// DWORD 3
uint32_t rsvd; // More reserved
// DWORD 4
uint32_t DMAbufOffset; // Byte offset into buffer. First 2 bits must be 0
// DWORD 5
uint32_t TransferCount; // Number of bytes to transfer. Bit 0 must be 0
// DWORD 6
uint32_t resvd; // Reserved
} FIS_DMA_SETUP;
typedef volatile struct tagHBA_PORT
{
uint64_t clb; // 0x00, command list base address, 1K-byte aligned
uint64_t fb; // 0x08, FIS base address, 256-byte aligned
uint32_t is; // 0x10, interrupt status
uint32_t ie; // 0x14, interrupt enable
uint32_t cmd; // 0x18, command and status
uint32_t rsv0; // 0x1C, Reserved
uint32_t tfd; // 0x20, task file data
uint32_t sig; // 0x24, signature
uint32_t ssts; // 0x28, SATA status (SCR0:SStatus)
uint32_t sctl; // 0x2C, SATA control (SCR2:SControl)
uint32_t serr; // 0x30, SATA error (SCR1:SError)
uint32_t sact; // 0x34, SATA active (SCR3:SActive)
uint32_t ci; // 0x38, command issue
uint32_t sntf; // 0x3C, SATA notification (SCR4:SNotification)
uint32_t fbs; // 0x40, FIS-based switch control
uint32_t rsv1[11]; // 0x44 ~ 0x6F, Reserved
uint32_t vendor[4]; // 0x70 ~ 0x7F, vendor specific
} HBA_PORT;
typedef volatile struct tagHBA_MEM
{
// 0x00 - 0x2B, Generic Host Control
uint32_t cap; // 0x00, Host capability
uint32_t ghc; // 0x04, Global host control
uint32_t is; // 0x08, Interrupt status
uint32_t pi; // 0x0C, Port implemented
uint32_t vs; // 0x10, Version
uint32_t ccc_ctl; // 0x14, Command completion coalescing control
uint32_t ccc_pts; // 0x18, Command completion coalescing ports
uint32_t em_loc; // 0x1C, Enclosure management location
uint32_t em_ctl; // 0x20, Enclosure management control
uint32_t cap2; // 0x24, Host capabilities extended
uint32_t bohc; // 0x28, BIOS/OS handoff control and status
// 0x2C - 0x9F, Reserved
uint8_t rsv[0xA0 - 0x2C];
// 0xA0 - 0xFF, Vendor specific registers
uint8_t vendor[0x100 - 0xA0];
// 0x100 - 0x10FF, Port control registers
HBA_PORT ports[32]; // 1 ~ 32
} HBA_MEM;
// There are four kinds of FIS which may be sent to the host by the device as indicated in the following structure declaration.
//
typedef volatile struct tagHBA_FIS
{
// 0x00
FIS_DMA_SETUP dsfis; // DMA Setup FIS
uint8_t pad0[4];
// 0x20
FIS_PIO_SETUP psfis; // PIO Setup FIS
uint8_t pad1[12];
// 0x40
FIS_REG_D2H rfis; // Register Device to Host FIS
uint8_t pad2[4];
// 0x58
// FIS_DEV_BITS sdbfis; // Set Device Bit FIS
// 0x60
uint8_t ufis[64];
// 0xA0
uint8_t rsv[0x100 - 0xA0];
} HBA_FIS;
typedef struct tagHBA_CMD_HEADER
{
// DW0
uint8_t cfl : 5; // Command FIS length in DWORDS, 2 ~ 16
uint8_t a : 1; // ATAPI
uint8_t w : 1; // Write, 1: H2D, 0: D2H
uint8_t p : 1; // Prefetchable
uint8_t r : 1; // Reset
uint8_t b : 1; // BIST
uint8_t c : 1; // Clear busy upon R_OK
uint8_t rsv0 : 1; // Reserved
uint8_t pmp : 4; // Port multiplier port
uint16_t prdtl; // Physical region descriptor table length in entries
// DW1
volatile uint32_t prdbc; // Physical region descriptor byte count transferred
// DW2, 3
uint64_t ctba; // Command table descriptor base address
// DW4 - 7
uint32_t rsv1[4]; // Reserved
} HBA_CMD_HEADER;
typedef struct tagHBA_PRDT_ENTRY
{
uint64_t dba; // Data base address
uint32_t rsv0; // Reserved
// DW3
uint32_t dbc : 22; // Byte count, 4M max
uint32_t rsv1 : 9; // Reserved
uint32_t i : 1; // Interrupt on completion
} HBA_PRDT_ENTRY;
typedef struct tagHBA_CMD_TBL
{
// 0x00
uint8_t cfis[64]; // Command FIS
// 0x40
uint8_t acmd[16]; // ATAPI command, 12 or 16 bytes
// 0x50
uint8_t rsv[48]; // Reserved
// 0x80
HBA_PRDT_ENTRY prdt_entry[1]; // Physical region descriptor table entries, 0 ~ 65535
} HBA_CMD_TBL;
struct ahci_device_t
{
uint32_t type; // 设备类型
struct pci_device_structure_header_t *dev_struct;
HBA_MEM *hba_mem;
} ahci_devices[MAX_AHCI_DEVICES];
#define SATA_SIG_ATA 0x00000101 // SATA drive
#define SATA_SIG_ATAPI 0xEB140101 // SATAPI drive
#define SATA_SIG_SEMB 0xC33C0101 // Enclosure management bridge
#define SATA_SIG_PM 0x96690101 // Port multiplier
#define AHCI_DEV_NULL 0
#define AHCI_DEV_SATA 1
#define AHCI_DEV_SEMB 2
#define AHCI_DEV_PM 3
#define AHCI_DEV_SATAPI 4
#define HBA_PORT_IPM_ACTIVE 1
#define HBA_PORT_DET_PRESENT 3
struct ahci_request_packet_t
{
struct block_device_request_packet blk_pak; // 块设备请求包
uint8_t ahci_ctrl_num; // ahci控制器号 默认应为0
uint8_t port_num; // ahci的设备端口号
};
/**
* @brief 初始化ahci模块
*

View File

@ -1,19 +0,0 @@
#pragma once
#include <common/kprint.h>
#include <mm/slab.h>
#include <syscall/syscall.h>
#include <syscall/syscall_num.h>
#include <sched/sched.h>
#include <common/string.h>
#include <common/block.h>
#include <debug/bug.h>
#include <driver/pci/pci.h>
#include <mm/mm.h>
// 计算HBA_MEM的虚拟内存地址
#define MAX_AHCI_DEVICES 100
#define AHCI_MAPPING_BASE SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + AHCI_MAPPING_OFFSET
/// @brief 保留了对 pci设备获取 和 mm内存映射 的依赖
void ahci_cpp_init(uint32_t *count_ahci_devices, struct pci_device_structure_header_t *ahci_devs[MAX_AHCI_DEVICES], struct pci_device_structure_general_device_t *gen_devs[MAX_AHCI_DEVICES]);

View File

@ -5,9 +5,13 @@ pub mod hba;
use crate::filesystem::vfs::io::device::BlockDevice;
// 依赖的rust工具包
use crate::driver::pci::pci::{
get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
};
use crate::filesystem::devfs::devfs_register;
use crate::filesystem::vfs::io::disk_info::BLK_GF_AHCI;
use crate::kerror;
use crate::libs::rwlock::RwLockWriteGuard;
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
use crate::mm::virt_2_phys;
use crate::syscall::SystemError;
@ -20,21 +24,23 @@ use crate::{
kdebug,
};
use ahci_inode::LockedAhciInode;
use alloc::boxed::Box;
use alloc::string::ToString;
use alloc::{format, string::String, sync::Arc, vec::Vec};
use core::sync::atomic::compiler_fence;
// 依赖的C结构体/常量
use crate::include::bindings::bindings::{
ahci_cpp_init, pci_device_structure_general_device_t, pci_device_structure_header_t,
AHCI_MAPPING_BASE, MAX_AHCI_DEVICES, PAGE_2M_MASK,
use alloc::{
boxed::Box,
collections::LinkedList,
format,
string::{String, ToString},
sync::Arc,
vec::Vec,
};
use core::sync::atomic::compiler_fence;
// 仅module内可见 全局数据区 hbr_port, disks
static LOCKED_HBA_MEM_LIST: SpinLock<Vec<&mut HbaMem>> = SpinLock::new(Vec::new());
static LOCKED_DISKS_LIST: SpinLock<Vec<Arc<LockedAhciDisk>>> = SpinLock::new(Vec::new());
const AHCI_CLASS: u8 = 0x1;
const AHCI_SUBCLASS: u8 = 0x6;
/* TFES - Task File Error Status */
#[allow(non_upper_case_globals)]
pub const HBA_PxIS_TFES: u32 = 1 << 30;
@ -48,53 +54,57 @@ pub extern "C" fn ahci_init() -> i32 {
return r.unwrap_err().to_posix_errno();
}
}
/// @brief 寻找所有的ahci设备
/// @param list 链表的写锁
/// @return Result<Vec<&'a mut Box<dyn PciDeviceStructure>>, SystemError> 成功则返回包含所有ahci设备结构体的可变引用的链表失败则返回err
fn ahci_device_search<'a>(
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
) -> Result<Vec<&'a mut Box<dyn PciDeviceStructure>>, SystemError> {
let result = get_pci_device_structure_mut(list, AHCI_CLASS, AHCI_SUBCLASS);
if result.is_empty() {
return Err(SystemError::ENODEV);
}
kdebug!("{}", result.len());
Ok(result)
}
/// @brief: 初始化 ahci
pub fn ahci_rust_init() -> Result<(), SystemError> {
compiler_fence(core::sync::atomic::Ordering::SeqCst);
let mut ahci_dev_counts: u32 = 0;
let mut ahci_devs: [*mut pci_device_structure_header_t; MAX_AHCI_DEVICES as usize] =
[0 as *mut pci_device_structure_header_t; MAX_AHCI_DEVICES as usize];
let mut gen_devs: [*mut pci_device_structure_general_device_t; MAX_AHCI_DEVICES as usize] =
[0 as *mut pci_device_structure_general_device_t; MAX_AHCI_DEVICES as usize];
compiler_fence(core::sync::atomic::Ordering::SeqCst);
unsafe {
// 单线程 init 所以写 ahci_devs 全局变量不会出错?
ahci_cpp_init(
(&mut ahci_dev_counts) as *mut u32,
(&mut ahci_devs) as *mut *mut pci_device_structure_header_t,
(&mut gen_devs) as *mut *mut pci_device_structure_general_device_t,
);
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
let mut list = PCI_DEVICE_LINKEDLIST.write();
let ahci_device = ahci_device_search(&mut list)?;
// 全局数据 - 列表
let mut disks_list = LOCKED_DISKS_LIST.lock();
for i in 0..(ahci_dev_counts as usize) {
for device in ahci_device {
let standard_device = device.as_standard_device_mut().unwrap();
standard_device.bar_ioremap();
// 对于每一个ahci控制器分配一块空间 (目前slab algorithm最大支持1MB)
let ahci_port_base_vaddr =
Box::leak(Box::new([0u8; (1 << 20) as usize])) as *mut u8 as usize;
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// 获取全局引用 : 计算 HBA_MEM 的虚拟地址 依赖于C的宏定义 cal_HBA_MEM_VIRT_ADDR
let virt_addr = AHCI_MAPPING_BASE as usize + unsafe { (*gen_devs[i]).BAR5 as usize }
- (unsafe { (*gen_devs[0]).BAR5 as usize } & PAGE_2M_MASK as usize);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
let virtaddr = standard_device
.bar()
.ok_or(SystemError::EACCES)?
.get_bar(5)
.or(Err(SystemError::EACCES))?
.virtual_address()
.unwrap();
// 最后把这个引用列表放入到全局列表
let mut hba_mem_list = LOCKED_HBA_MEM_LIST.lock();
hba_mem_list.push(unsafe { (virt_addr as *mut HbaMem).as_mut().unwrap() });
let pi = volatile_read!(hba_mem_list[i].pi);
//这里两次unsafe转引用规避rust只能有一个可变引用的检查提高运行速度
let hba_mem = unsafe { (virtaddr as *mut HbaMem).as_mut().unwrap() };
hba_mem_list.push(unsafe { (virtaddr as *mut HbaMem).as_mut().unwrap() });
let pi = volatile_read!(hba_mem.pi);
let hba_mem_index = hba_mem_list.len() - 1;
drop(hba_mem_list);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// 初始化所有的port
let mut id = 0;
for j in 0..32 {
if (pi >> j) & 1 > 0 {
let mut hba_mem_list = LOCKED_HBA_MEM_LIST.lock();
let tp = hba_mem_list[i].ports[j].check_type();
let hba_mem_list = LOCKED_HBA_MEM_LIST.lock();
let hba_mem_port = &mut hba_mem.ports[j];
let tp = hba_mem_port.check_type();
match tp {
HbaPortType::None => {
kdebug!("<ahci_rust_init> Find a None type Disk.");
@ -108,7 +118,6 @@ pub fn ahci_rust_init() -> Result<(), SystemError> {
// 计算地址
let fb = virt_2_phys(ahci_port_base_vaddr + (32 << 10) + (j << 8));
let clb = virt_2_phys(ahci_port_base_vaddr + (j << 10));
compiler_fence(core::sync::atomic::Ordering::SeqCst);
let ctbas = (0..32)
.map(|x| {
virt_2_phys(
@ -118,17 +127,14 @@ pub fn ahci_rust_init() -> Result<(), SystemError> {
.collect::<Vec<_>>();
// 初始化 port
hba_mem_list[i].ports[j].init(clb as u64, fb as u64, &ctbas);
// 释放锁
hba_mem_port.init(clb as u64, fb as u64, &ctbas);
drop(hba_mem_list);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// 创建 disk
disks_list.push(LockedAhciDisk::new(
format!("ahci_disk_{}", id),
BLK_GF_AHCI,
i as u8,
hba_mem_index as u8,
j as u8,
)?);
id += 1; // ID 从0开始
@ -144,7 +150,7 @@ pub fn ahci_rust_init() -> Result<(), SystemError> {
kerror!(
"Ahci_{} ctrl = {}, port = {} failed to register, error code = {:?}",
id,
i,
hba_mem_index as u8,
j,
err
);
@ -168,23 +174,20 @@ pub fn disks() -> Vec<Arc<LockedAhciDisk>> {
/// @brief: 通过 name 获取 disk
pub fn get_disks_by_name(name: String) -> Result<Arc<LockedAhciDisk>, SystemError> {
compiler_fence(core::sync::atomic::Ordering::SeqCst);
let disks_list: SpinLockGuard<Vec<Arc<LockedAhciDisk>>> = LOCKED_DISKS_LIST.lock();
for i in 0..disks_list.len() {
if disks_list[i].0.lock().name == name {
return Ok(disks_list[i].clone());
}
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
return Err(SystemError::ENXIO);
let result = disks_list
.iter()
.find(|x| x.0.lock().name == name)
.ok_or(SystemError::ENXIO)?
.clone();
return Ok(result);
}
/// @brief: 通过 ctrl_num 和 port_num 获取 port
pub fn _port(ctrl_num: u8, port_num: u8) -> &'static mut HbaPort {
compiler_fence(core::sync::atomic::Ordering::SeqCst);
fn _port(ctrl_num: u8, port_num: u8) -> &'static mut HbaPort {
let list: SpinLockGuard<Vec<&mut HbaMem>> = LOCKED_HBA_MEM_LIST.lock();
let port: &HbaPort = &list[ctrl_num as usize].ports[port_num as usize];
compiler_fence(core::sync::atomic::Ordering::SeqCst);
return unsafe { (port as *const HbaPort as *mut HbaPort).as_mut().unwrap() };
}

View File

@ -1,14 +1,9 @@
all: pci.o pci_irq.o msi.o
all: pci_irq.o
CFLAGS += -I .
pci.o: pci.c
$(CC) $(CFLAGS) -c pci.c -o pci.o
pci_irq.o: pci_irq.c
$(CC) $(CFLAGS) -c pci_irq.c -o pci_irq.o
msi.o: msi.c
$(CC) $(CFLAGS) -c msi.c -o msi.o

View File

@ -1,340 +0,0 @@
#include "msi.h"
#include "pci.h"
#include <common/errno.h>
#include <mm/mmio.h>
/**
* @brief 生成msi消息
*
* @param msi_desc msi描述符
* @return struct msi_msg_t* msi消息指针在描述符内
*/
extern struct msi_msg_t *msi_arch_get_msg(struct msi_desc_t *msi_desc);
/**
* @brief 读取msix的capability list
*
* @param msi_desc msi描述符
* @param cap_off capability list的offset
* @return struct pci_msix_cap_t 对应的capability list
*/
static __always_inline struct pci_msix_cap_t __msi_read_msix_cap_list(struct msi_desc_t *msi_desc, uint32_t cap_off)
{
struct pci_msix_cap_t cap_list = {0};
uint32_t dw0;
dw0 = pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off);
io_lfence();
cap_list.cap_id = dw0 & 0xff;
cap_list.next_off = (dw0 >> 8) & 0xff;
cap_list.msg_ctrl = (dw0 >> 16) & 0xffff;
cap_list.dword1 =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x4);
cap_list.dword2 =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x8);
return cap_list;
}
static __always_inline struct pci_msi_cap_t __msi_read_cap_list(struct msi_desc_t *msi_desc, uint32_t cap_off)
{
struct pci_msi_cap_t cap_list = {0};
uint32_t dw0;
dw0 = pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off);
cap_list.cap_id = dw0 & 0xff;
cap_list.next_off = (dw0 >> 8) & 0xff;
cap_list.msg_ctrl = (dw0 >> 16) & 0xffff;
cap_list.msg_addr_lo =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x4);
uint16_t msg_data_off = 0xc;
if (cap_list.msg_ctrl & (1 << 7)) // 64位
{
cap_list.msg_addr_hi =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x8);
}
else
{
cap_list.msg_addr_hi = 0;
msg_data_off = 0x8;
}
cap_list.msg_data = pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func,
cap_off + msg_data_off) &
0xffff;
cap_list.mask =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x10);
cap_list.pending =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x14);
return cap_list;
}
/**
* @brief 映射设备的msix表 //MSIX表不再单独映射(To do)
*
* @param pci_dev pci设备信息结构体
* @param msix_cap msix capability list的结构体
* @return int 错误码
*/
static __always_inline int __msix_map_table(struct pci_device_structure_header_t *pci_dev,
struct pci_msix_cap_t *msix_cap)
{
// 计算bar寄存器的offset
uint32_t bar_off = 0x10 + 4 * (msix_cap->dword1 & 0x7);
// msix table相对于bar寄存器中存储的地址的offset
pci_dev->msix_offset = msix_cap->dword1 & (~0x7);
pci_dev->msix_table_size = (msix_cap->msg_ctrl & 0x7ff) + 1;
pci_dev->msix_mmio_size = pci_dev->msix_table_size * 16 + pci_dev->msix_offset;
// 申请mmio空间
mmio_create(pci_dev->msix_mmio_size, VM_IO | VM_DONTCOPY, &pci_dev->msix_mmio_vaddr, &pci_dev->msix_mmio_size);
pci_dev->msix_mmio_vaddr &= (~0xf);
uint32_t bar = pci_read_config(pci_dev->bus, pci_dev->device, pci_dev->func, bar_off);
// kdebug("pci_dev->msix_mmio_vaddr=%#018lx, bar=%#010lx, table offset=%#010lx, table_size=%#010lx, mmio_size=%d",
// pci_dev->msix_mmio_vaddr, bar, pci_dev->msix_offset, pci_dev->msix_table_size, pci_dev->msix_mmio_size);
// 将msix table映射到页表
rs_map_phys(pci_dev->msix_mmio_vaddr, bar, pci_dev->msix_mmio_size, PAGE_KERNEL_PAGE);
return 0;
}
/**
* @brief 将msi_desc中的数据填写到msix表的指定表项处
*
* @param pci_dev pci设备结构体
* @param msi_desc msi描述符
*/
static __always_inline void __msix_set_entry(struct msi_desc_t *msi_desc)
{
uint64_t *ptr =
(uint64_t *)(msi_desc->pci_dev->msix_mmio_vaddr + msi_desc->pci_dev->msix_offset + msi_desc->msi_index * 16);
*ptr = ((uint64_t)(msi_desc->msg.address_hi) << 32) | (msi_desc->msg.address_lo);
io_mfence();
++ptr;
io_mfence();
*ptr = ((uint64_t)(msi_desc->msg.vector_control) << 32) | (msi_desc->msg.data);
io_mfence();
}
/**
* @brief 清空设备的msix table的指定表项
*
* @param pci_dev pci设备
* @param msi_index 表项号
*/
static __always_inline void __msix_clear_entry(struct pci_device_structure_header_t *pci_dev, uint16_t msi_index)
{
uint64_t *ptr = (uint64_t *)(pci_dev->msix_mmio_vaddr + pci_dev->msix_offset + msi_index * 16);
*ptr = 0;
++ptr;
*ptr = 0;
}
/**
* @brief 启用 Message Signaled Interrupts
*
* @param header 设备header
* @param vector 中断向量号
* @param processor 要投递到的处理器
* @param edge_trigger 是否边缘触发
* @param assert 是否高电平触发
*
* @return 返回码
*/
int pci_enable_msi(struct msi_desc_t *msi_desc)
{
struct pci_device_structure_header_t *ptr = msi_desc->pci_dev;
uint32_t cap_ptr;
uint32_t tmp;
uint16_t message_control;
uint64_t message_addr;
// 先尝试获取msi-x若不存在则获取msi capability
if (msi_desc->pci.msi_attribute.is_msix)
{
cap_ptr = pci_enumerate_capability_list(ptr, 0x11);
if (((int32_t)cap_ptr) < 0)
{
cap_ptr = pci_enumerate_capability_list(ptr, 0x05);
if (((int32_t)cap_ptr) < 0)
return -ENOSYS;
msi_desc->pci.msi_attribute.is_msix = 0;
}
}
else
{
cap_ptr = pci_enumerate_capability_list(ptr, 0x05);
if (((int32_t)cap_ptr) < 0)
return -ENOSYS;
msi_desc->pci.msi_attribute.is_msix = 0;
}
// 获取msi消息
msi_arch_get_msg(msi_desc);
if (msi_desc->pci.msi_attribute.is_msix) // MSI-X
{
kdebug("is msix");
// 读取msix的信息
struct pci_msix_cap_t cap = __msi_read_msix_cap_list(msi_desc, cap_ptr);
// 映射msix table
__msix_map_table(msi_desc->pci_dev, &cap);
io_mfence();
// 设置msix的中断
__msix_set_entry(msi_desc);
io_mfence();
// todo: disable intx
// 使能msi-x
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp |= (1U << 31);
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
}
else
{
kdebug("is msi");
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
message_control = (tmp >> 16) & 0xffff;
// 写入message address
message_addr = ((((uint64_t)msi_desc->msg.address_hi) << 32) | msi_desc->msg.address_lo); // 获取message address
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x4, (uint32_t)(message_addr & 0xffffffff));
if (message_control & (1 << 7)) // 64位
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8,
(uint32_t)((message_addr >> 32) & 0xffffffff));
// 写入message data
tmp = msi_desc->msg.data;
if (message_control & (1 << 7)) // 64位
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0xc, tmp);
else
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8, tmp);
// 使能msi
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp |= (1 << 16);
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
}
return 0;
}
/**
* @brief 在已配置好msi寄存器的设备上使能msi
*
* @param header 设备头部
* @return int 返回码
*/
int pci_start_msi(void *header)
{
struct pci_device_structure_header_t *ptr = (struct pci_device_structure_header_t *)header;
uint32_t cap_ptr;
uint32_t tmp;
switch (ptr->HeaderType)
{
case 0x00: // general device
if (!(ptr->Status & 0x10))
return -ENOSYS;
cap_ptr = ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer;
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
if (tmp & 0xff != 0x5)
return -ENOSYS;
// 使能msi
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp |= (1 << 16);
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
break;
case 0x01: // pci to pci bridge
if (!(ptr->Status & 0x10))
return -ENOSYS;
cap_ptr = ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer;
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
if (tmp & 0xff != 0x5)
return -ENOSYS;
// 使能msi
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp |= (1 << 16);
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
break;
case 0x02: // pci to card bus bridge
return -ENOSYS;
break;
default: // 不应该到达这里
return -EINVAL;
break;
}
return 0;
}
/**
* @brief 禁用指定设备的msi
*
* @param header pci header
* @return int
*/
int pci_disable_msi(void *header)
{
struct pci_device_structure_header_t *ptr = (struct pci_device_structure_header_t *)header;
uint32_t cap_ptr;
uint32_t tmp;
switch (ptr->HeaderType)
{
case 0x00: // general device
if (!(ptr->Status & 0x10))
return -ENOSYS;
cap_ptr = ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer;
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
if (tmp & 0xff != 0x5)
return -ENOSYS;
// 禁用msi
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp &= (~(1 << 16));
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
break;
case 0x01: // pci to pci bridge
if (!(ptr->Status & 0x10))
return -ENOSYS;
cap_ptr = ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer;
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
if (tmp & 0xff != 0x5)
return -ENOSYS;
// 禁用msi
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp &= (~(1 << 16));
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
break;
case 0x02: // pci to card bus bridge
return -ENOSYS;
break;
default: // 不应该到达这里
return -EINVAL;
break;
}
return 0;
}

View File

@ -1,110 +0,0 @@
#pragma once
#include <common/glib.h>
/**
* @brief msi消息内容结构体
*
*/
struct msi_msg_t
{
uint32_t address_lo;
uint32_t address_hi;
uint32_t data;
uint32_t vector_control;
};
struct pci_msi_desc_t
{
union
{
uint32_t msi_mask; // [PCI MSI] MSI cached mask bits
uint32_t msix_ctrl; // [PCI MSI-X] MSI-X cached per vector control bits
};
struct
{
uint8_t is_msix : 1; // [PCI MSI/X] True if MSI-X
uint8_t can_mask : 1; // [PCI MSI/X] Masking supported?
uint8_t is_64 : 1; // [PCI MSI/X] Address size: 0=32bit 1=64bit
} msi_attribute;
};
/**
* @brief msi capability list的结构
*
*/
struct pci_msi_cap_t
{
uint8_t cap_id;
uint8_t next_off;
uint16_t msg_ctrl;
uint32_t msg_addr_lo;
uint32_t msg_addr_hi;
uint16_t msg_data;
uint16_t Rsvd;
uint32_t mask;
uint32_t pending;
};
/**
* @brief MSI-X的capability list结构体
*
*/
struct pci_msix_cap_t
{
uint8_t cap_id;
uint8_t next_off;
uint16_t msg_ctrl;
uint32_t dword1; // 该DWORD的组成为[Table Offset][BIR2:0].
// 由于Table Offset是8字节对齐的因此mask掉该dword的BIR部分就是table offset的值
uint32_t dword2; // 该DWORD的组成为[Pending Bit Offset][Pending Bit BIR2:0].
// 由于Pending Bit Offset是8字节对齐的因此mask掉该dword的BIR部分就是Pending Bit Offset的值
};
/**
* @brief msi描述符
*
*/
struct msi_desc_t
{
uint16_t irq_num; // 中断向量号
uint16_t processor; // 定向投递的处理器
uint16_t edge_trigger; // 是否边缘触发
uint16_t assert; // 是否高电平触发
struct pci_device_structure_header_t *pci_dev; // 对应的pci设备的结构体
struct msi_msg_t msg; // msi消息
uint16_t msi_index; // msi描述符的index
struct pci_msi_desc_t pci; // 与pci相关的msi描述符数据
};
/**
* @brief 启用 Message Signaled Interrupts
*
* @param header 设备header
* @param vector 中断向量号
* @param processor 要投递到的处理器
* @param edge_trigger 是否边缘触发
* @param assert 是否高电平触发
*
* @return 返回码
*/
int pci_enable_msi(struct msi_desc_t *msi_desc);
/**
* @brief 禁用指定设备的msi
*
* @param header pci header
* @return int
*/
int pci_disable_msi(void *header);
/**
* @brief 在已配置好msi寄存器的设备上使能msi
*
* @param header 设备头部
* @return int 返回码
*/
int pci_start_msi(void *header);

View File

@ -1,542 +0,0 @@
#include "pci.h"
#include <common/kprint.h>
#include <mm/slab.h>
#include <debug/bug.h>
#include <common/errno.h>
static uint count_device_list = 0;
static void pci_checkBus(uint8_t bus);
/**
* @brief 将设备信息结构体加到链表里面
*
*/
#define ADD_DEVICE_STRUCT_TO_LIST(ret) \
do \
{ \
if (count_device_list > 0) \
{ \
++count_device_list; \
list_add(pci_device_structure_list, &(ret->header.list)); \
} \
else \
{ \
++count_device_list; \
list_init(&(ret->header.list)); \
pci_device_structure_list = &(ret->header.list); \
} \
} while (0)
/**
* @brief 从pci配置空间读取信息
*
* @param bus 总线号
* @param slot 设备号
* @param func 功能号
* @param offset 字节偏移量
* @return uint 寄存器值
*/
uint32_t pci_read_config(uchar bus, uchar slot, uchar func, uchar offset)
{
uint lbus = (uint)bus;
uint lslot = (uint)slot;
uint lfunc = ((uint)func) & 7;
// 构造pci配置空间地址
uint address = (uint)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xfc) | ((uint)0x80000000));
io_out32(PORT_PCI_CONFIG_ADDRESS, address);
// 读取返回的数据
uint32_t ret = (uint)(io_in32(PORT_PCI_CONFIG_DATA));
return ret;
}
/**
* @brief 向pci配置空间写入信息
*
* @param bus 总线号
* @param slot 设备号
* @param func 功能号
* @param offset 字节偏移量
* @return uint 返回码
*/
uint pci_write_config(uchar bus, uchar slot, uchar func, uchar offset, uint32_t data)
{
uint lbus = (uint)bus;
uint lslot = (uint)slot;
uint lfunc = ((uint)func) & 7;
// 构造pci配置空间地址
uint address = (uint)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xfc) | ((uint)0x80000000));
io_out32(PORT_PCI_CONFIG_ADDRESS, address);
// 写入数据
io_out32(PORT_PCI_CONFIG_DATA, data);
return 0;
}
/**
* @brief 读取type为0x0的pci设备的header
* 本函数只应被 pci_read_header()调用
* @param header 返回的header
* @param bus 总线号
* @param slot 插槽号
* @param func 功能号
*/
static void pci_read_general_device_header(struct pci_device_structure_general_device_t *header, uchar bus, uchar slot, uchar func)
{
uint32_t tmp32;
header->BAR0 = pci_read_config(bus, slot, func, 0x10);
header->BAR1 = pci_read_config(bus, slot, func, 0x14);
header->BAR2 = pci_read_config(bus, slot, func, 0x18);
header->BAR3 = pci_read_config(bus, slot, func, 0x1c);
header->BAR4 = pci_read_config(bus, slot, func, 0x20);
header->BAR5 = pci_read_config(bus, slot, func, 0x24);
header->Cardbus_CIS_Pointer = pci_read_config(bus, slot, func, 0x28);
tmp32 = pci_read_config(bus, slot, func, 0x2c);
header->Subsystem_Vendor_ID = tmp32 & 0xffff;
header->Subsystem_ID = (tmp32 >> 16) & 0xffff;
header->Expansion_ROM_base_address = pci_read_config(bus, slot, func, 0x30);
tmp32 = pci_read_config(bus, slot, func, 0x34);
header->Capabilities_Pointer = tmp32 & 0xff;
header->reserved0 = (tmp32 >> 8) & 0xff;
header->reserved1 = (tmp32 >> 16) & 0xffff;
header->reserved2 = pci_read_config(bus, slot, func, 0x38);
tmp32 = pci_read_config(bus, slot, func, 0x3c);
header->Interrupt_Line = tmp32 & 0xff;
header->Interrupt_PIN = (tmp32 >> 8) & 0xff;
header->Min_Grant = (tmp32 >> 16) & 0xff;
header->Max_Latency = (tmp32 >> 24) & 0xff;
}
/**
* @brief 读取type为0x1的pci_to_pci_bridge的header
* 本函数只应被 pci_read_header()调用
* @param header 返回的header
* @param bus 总线号
* @param slot 插槽号
* @param func 功能号
*/
static void pci_read_pci_to_pci_bridge_header(struct pci_device_structure_pci_to_pci_bridge_t *header, uchar bus, uchar slot, uchar func)
{
uint32_t tmp32;
header->BAR0 = pci_read_config(bus, slot, func, 0x10);
header->BAR1 = pci_read_config(bus, slot, func, 0x14);
tmp32 = pci_read_config(bus, slot, func, 0x18);
header->Primary_Bus_Number = tmp32 & 0xff;
header->Secondary_Bus_Number = (tmp32 >> 8) & 0xff;
header->Subordinate_Bus_Number = (tmp32 >> 16) & 0xff;
header->Secondary_Latency_Timer = (tmp32 >> 24) & 0xff;
tmp32 = pci_read_config(bus, slot, func, 0x1c);
header->io_base = tmp32 & 0xff;
header->io_limit = (tmp32 >> 8) & 0xff;
header->Secondary_Status = (tmp32 >> 16) & 0xffff;
tmp32 = pci_read_config(bus, slot, func, 0x20);
header->Memory_Base = tmp32 & 0xffff;
header->Memory_Limit = (tmp32 >> 16) & 0xffff;
tmp32 = pci_read_config(bus, slot, func, 0x24);
header->Prefetchable_Memory_Base = tmp32 & 0xffff;
header->Prefetchable_Memory_Limit = (tmp32 >> 16) & 0xffff;
header->Prefetchable_Base_Upper_32_Bits = pci_read_config(bus, slot, func, 0x28);
header->Prefetchable_Limit_Upper_32_Bits = pci_read_config(bus, slot, func, 0x2c);
tmp32 = pci_read_config(bus, slot, func, 0x30);
header->io_Base_Upper_16_Bits = tmp32 & 0xffff;
header->io_Limit_Upper_16_Bits = (tmp32 >> 16) & 0xffff;
tmp32 = pci_read_config(bus, slot, func, 0x34);
header->Capability_Pointer = tmp32 & 0xff;
header->reserved0 = (tmp32 >> 8) & 0xff;
header->reserved1 = (tmp32 >> 16) & 0xffff;
header->Expansion_ROM_base_address = pci_read_config(bus, slot, func, 0x38);
tmp32 = pci_read_config(bus, slot, func, 0x3c);
header->Interrupt_Line = tmp32 & 0xff;
header->Interrupt_PIN = (tmp32 >> 8) & 0xff;
header->Bridge_Control = (tmp32 >> 16) & 0xffff;
}
/**
* @brief 读取type为0x2的pci_to_cardbus_bridge的header
* 本函数只应被 pci_read_header()调用
* @param header 返回的header
* @param bus 总线号
* @param slot 插槽号
* @param func 功能号
*/
static void pci_read_pci_to_cardbus_bridge_header(struct pci_device_structure_pci_to_cardbus_bridge_t *header, uchar bus, uchar slot, uchar func)
{
uint32_t tmp32;
header->CardBus_Socket_ExCa_base_address = pci_read_config(bus, slot, func, 0x10);
tmp32 = pci_read_config(bus, slot, func, 0x14);
header->Offset_of_capabilities_list = tmp32 & 0xff;
header->Reserved = (tmp32 >> 8) & 0xff;
header->Secondary_status = (tmp32 >> 16) & 0xff;
tmp32 = pci_read_config(bus, slot, func, 0x18);
header->PCI_bus_number = tmp32 & 0xff;
header->CardBus_bus_number = (tmp32 >> 8) & 0xff;
header->Subordinate_bus_number = (tmp32 >> 16) & 0xff;
header->CardBus_latency_timer = (tmp32 >> 24) & 0xff;
header->Memory_Base_Address0 = pci_read_config(bus, slot, func, 0x1c);
header->Memory_Limit0 = pci_read_config(bus, slot, func, 0x20);
header->Memory_Base_Address1 = pci_read_config(bus, slot, func, 0x24);
header->Memory_Limit1 = pci_read_config(bus, slot, func, 0x28);
header->IO_Base_Address0 = pci_read_config(bus, slot, func, 0x2c);
header->IO_Limit0 = pci_read_config(bus, slot, func, 0x30);
header->IO_Base_Address1 = pci_read_config(bus, slot, func, 0x34);
header->IO_Limit1 = pci_read_config(bus, slot, func, 0x38);
tmp32 = pci_read_config(bus, slot, func, 0x3c);
header->Interrupt_Line = tmp32 & 0xff;
header->Interrupt_PIN = (tmp32 >> 8) & 0xff;
header->Bridge_Control = (tmp32 >> 16) & 0xffff;
tmp32 = pci_read_config(bus, slot, func, 0x40);
header->Subsystem_Device_ID = tmp32 & 0xffff;
header->Subsystem_Vendor_ID = (tmp32 >> 16) & 0xffff;
header->PC_Card_legacy_mode_base_address_16_bit = pci_read_config(bus, slot, func, 0x44);
}
/**
* @brief 读取pci设备标头
*
* @param type 标头类型
* @param bus 总线号
* @param slot 插槽号
* @param func 功能号
* @param add_to_list 添加到链表
* @return 返回的header
*/
void *pci_read_header(int *type, uchar bus, uchar slot, uchar func, bool add_to_list)
{
struct pci_device_structure_header_t *common_header = (struct pci_device_structure_header_t *)kmalloc(127, 0);
common_header->bus = bus;
common_header->device = slot;
common_header->func = func;
uint32_t tmp32;
// 先读取公共header
tmp32 = pci_read_config(bus, slot, func, 0x0);
common_header->Vendor_ID = tmp32 & 0xffff;
common_header->Device_ID = (tmp32 >> 16) & 0xffff;
tmp32 = pci_read_config(bus, slot, func, 0x4);
common_header->Command = tmp32 & 0xffff;
common_header->Status = (tmp32 >> 16) & 0xffff;
tmp32 = pci_read_config(bus, slot, func, 0x8);
common_header->RevisionID = tmp32 & 0xff;
common_header->ProgIF = (tmp32 >> 8) & 0xff;
common_header->SubClass = (tmp32 >> 16) & 0xff;
common_header->Class_code = (tmp32 >> 24) & 0xff;
tmp32 = pci_read_config(bus, slot, func, 0xc);
common_header->CacheLineSize = tmp32 & 0xff;
common_header->LatencyTimer = (tmp32 >> 8) & 0xff;
common_header->HeaderType = (tmp32 >> 16) & 0xff;
common_header->BIST = (tmp32 >> 24) & 0xff;
void *ret;
if (common_header->Vendor_ID == 0xffff)
{
*type = -ENXIO;
kfree(common_header);
return NULL;
}
// 根据公共头部,判断该结构所属的类型
switch (common_header->HeaderType)
{
case 0x0: // general device
ret = common_header;
pci_read_general_device_header((struct pci_device_structure_general_device_t *)ret, bus, slot, func);
if (add_to_list)
ADD_DEVICE_STRUCT_TO_LIST(((struct pci_device_structure_general_device_t *)ret));
*type = 0x0;
return ret;
break;
case 0x1:
ret = common_header;
pci_read_pci_to_pci_bridge_header((struct pci_device_structure_pci_to_pci_bridge_t *)ret, bus, slot, func);
if (add_to_list)
ADD_DEVICE_STRUCT_TO_LIST(((struct pci_device_structure_pci_to_pci_bridge_t *)ret));
*type = 0x1;
return ret;
break;
case 0x2:
ret = common_header;
pci_read_pci_to_cardbus_bridge_header((struct pci_device_structure_pci_to_cardbus_bridge_t *)ret, bus, slot, func);
if (add_to_list)
ADD_DEVICE_STRUCT_TO_LIST(((struct pci_device_structure_pci_to_cardbus_bridge_t *)ret));
*type = 0x2;
return ret;
break;
default: // 错误的头类型 这里不应该被执行
// kerror("PCI->pci_read_header(): Invalid header type.");
*type = -EINVAL;
// kerror("vendor id=%#010lx", common_header->Vendor_ID);
// kerror("header type = %d", common_header->HeaderType);
kfree(common_header);
return NULL;
break;
}
}
static void pci_checkFunction(uint8_t bus, uint8_t device, uint8_t function)
{
int header_type;
struct pci_device_structure_header_t *header = pci_read_header(&header_type, bus, device, function, true);
if (header_type == -EINVAL)
{
// kerror("pci_checkFunction(): wrong header type!");
// 此处内存已经在read header函数里面释放不用重复释放
return;
}
// header = ((struct pci_device_structure_general_device_t *)raw_header)->header;
if ((header->Class_code == 0x6) && (header->SubClass == 0x4))
{
uint8_t SecondaryBus = ((struct pci_device_structure_pci_to_pci_bridge_t *)header)->Secondary_Bus_Number;
pci_checkBus(SecondaryBus);
}
}
static int pci_checkDevice(uint8_t bus, uint8_t device)
{
int header_type;
struct pci_device_structure_header_t *header = pci_read_header(&header_type, bus, device, 0, false);
if (header_type == -EINVAL)
{
// 此处内存已经在read header函数里面释放不用重复释放
return -EINVAL;
}
if (header_type == -ENXIO)
{
// kerror("DEVICE INVALID");
return -ENXIO;
}
uint16_t vendorID = header->Vendor_ID;
if (vendorID == 0xffff) // 设备不存在
{
kfree(header);
return -ENXIO;
}
pci_checkFunction(bus, device, 0);
header_type = header->HeaderType;
if ((header_type & 0x80) != 0)
{
kdebug("Multi func device");
// 这是一个多function的设备因此查询剩余的function
for (uint8_t func = 1; func < 8; ++func)
{
struct pci_device_structure_header_t *tmp_header;
tmp_header = (struct pci_device_structure_header_t *)pci_read_header(&header_type, bus, device, func, false);
if (tmp_header->Vendor_ID != 0xffff)
pci_checkFunction(bus, device, func);
// 释放内存
kfree(tmp_header);
}
}
kfree(header);
return 0;
}
static void pci_checkBus(uint8_t bus)
{
for (uint8_t device = 0; device < 32; ++device)
{
pci_checkDevice(bus, device);
}
}
/**
* @brief 扫描所有pci总线上的所有设备
*
*/
void pci_checkAllBuses()
{
kinfo("Checking all devices in PCI bus...");
int header_type;
struct pci_device_structure_header_t *header = pci_read_header(&header_type, 0, 0, 0, false);
if (header_type == EINVAL)
{
kBUG("pci_checkAllBuses(): wrong header type!");
// 此处内存已经在read header函数里面释放不用重复释放
return;
}
header_type = header->HeaderType;
if ((header_type & 0x80) == 0) // Single pci host controller
{
pci_checkBus(0);
}
else
{
// Multiple PCI host controller
// 那么总线0设备0功能1则是总线1的pci主机控制器以此类推
struct pci_device_structure_header_t *tmp_header;
for (uint8_t func = 0; func < 8; ++func)
{
tmp_header = (struct pci_device_structure_header_t *)pci_read_header(&header_type, 0, 0, func, false);
if (WARN_ON(header->Vendor_ID != 0xffff)) // @todo 这里的判断条件可能有点问题
{
kfree(tmp_header);
break;
}
pci_checkBus(func);
kfree(tmp_header);
}
}
kfree(header);
}
void pci_init()
{
kinfo("Initializing PCI bus...");
pci_checkAllBuses();
kinfo("Total pci device and function num = %d", count_device_list);
struct pci_device_structure_header_t *ptr = container_of(pci_device_structure_list, struct pci_device_structure_header_t, list);
for (int i = 0; i < count_device_list; ++i)
{
if (ptr->HeaderType == 0x0)
{
if (ptr->Status & 0x10)
{
kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\tcap_pointer=%#010lx\tbar5=%#010lx, vendor=%#08x, device id=%#08x", i, ptr->Class_code, ptr->SubClass, ptr->Status, ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer, ((struct pci_device_structure_general_device_t *)ptr)->BAR5,
ptr->Vendor_ID, ptr->Device_ID);
uint32_t tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer);
}
else
{
kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\t", i, ptr->Class_code, ptr->SubClass, ptr->Status);
}
}
else if (ptr->HeaderType == 0x1)
{
if (ptr->Status & 0x10)
{
kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\tcap_pointer=%#010lx", i, ptr->Class_code, ptr->SubClass, ptr->Status, ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer);
}
else
{
kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\t", i, ptr->Class_code, ptr->SubClass, ptr->Status);
}
}
else if (ptr->HeaderType == 0x2)
{
kinfo("[ pci device %d ] class code = %d\tsubclass=%d\tstatus=%#010lx\t", i, ptr->Class_code, ptr->SubClass, ptr->Status);
}
ptr = container_of(list_next(&(ptr->list)), struct pci_device_structure_header_t, list);
}
kinfo("PCI bus initialized.");
}
/**
* @brief 获取 device structure
*
* @param class_code
* @param sub_class
* @param res 返回的结果数组
*/
void pci_get_device_structure(uint8_t class_code, uint8_t sub_class, struct pci_device_structure_header_t *res[], uint32_t *count_res)
{
struct pci_device_structure_header_t *ptr = container_of(pci_device_structure_list, struct pci_device_structure_header_t, list);
*count_res = 0;
for (int i = 0; i < count_device_list; ++i)
{
if ((ptr->Class_code == class_code) && (ptr->SubClass == sub_class))
{
kdebug("[%d] class_code=%d, sub_class=%d, progIF=%d, bar5=%#010lx", i, ptr->Class_code, ptr->SubClass, ptr->ProgIF, ((struct pci_device_structure_general_device_t *)ptr)->BAR5);
res[*count_res] = ptr;
++(*count_res);
}
ptr = container_of(list_next(&(ptr->list)), struct pci_device_structure_header_t, list);
}
}
/**
* @brief 寻找符合指定类型的capability list
*
* @param pci_dev pci设备header
* @param cap_type c要寻找的capability类型
* @return uint64_t cap list的偏移量
*/
int32_t pci_enumerate_capability_list(struct pci_device_structure_header_t *pci_dev, uint32_t cap_type)
{
uint32_t cap_offset;
switch (pci_dev->HeaderType)
{
case 0x00:
cap_offset = ((struct pci_device_structure_general_device_t *)pci_dev)->Capabilities_Pointer;
break;
case 0x10:
cap_offset = ((struct pci_device_structure_pci_to_pci_bridge_t *)pci_dev)->Capability_Pointer;
break;
default:
// 不支持
return -ENOSYS;
}
uint32_t tmp;
while (1)
{
tmp = pci_read_config(pci_dev->bus, pci_dev->device, pci_dev->func, cap_offset);
if ((tmp & 0xff) != cap_type)
{
if (((tmp & 0xff00) >> 8))
{
cap_offset = (tmp & 0xff00)>>8;
continue;
}
else
return -ENOSYS;
}
return cap_offset;
}
}

View File

@ -1,225 +0,0 @@
#pragma once
#include <common/glib.h>
#include <DragonOS/stdint.h>
#define PORT_PCI_CONFIG_ADDRESS 0xcf8
#define PORT_PCI_CONFIG_DATA 0xcfc
// pci设备结构信息的链表
struct List *pci_device_structure_list = NULL;
/**
* @brief 初始化pci驱动
*
*/
void pci_init();
void rs_pci_init();
// pci设备结构的通用标题字段
struct pci_device_structure_header_t
{
struct List list;
// 包含msix table地址的bar的mmio基地址
uint64_t msix_mmio_vaddr;
uint64_t msix_mmio_size; // msix映射长度
uint32_t msix_offset; // msix表的offset
uint16_t msix_table_size; // msix表的表项数量
// ==== 以下三个变量表示该结构体所处的位置
uint8_t bus;
uint8_t device;
uint8_t func;
uint16_t Vendor_ID; // 供应商ID 0xffff是一个无效值在读取访问不存在的设备的配置空间寄存器时返回
uint16_t Device_ID; // 设备ID标志特定设备
uint16_t Command; // 提供对设备生成和响应pci周期的能力的控制 向该寄存器写入0时设备与pci总线断开除配置空间访问以外的所有连接
uint16_t Status; // 用于记录pci总线相关时间的状态信息寄存器
uint8_t RevisionID; // 修订ID指定特定设备的修订标志符
uint8_t ProgIF; // 编程接口字节,一个只读寄存器,指定设备具有的寄存器级别的编程接口(如果有的话)
uint8_t SubClass; // 子类。指定设备执行的特定功能的只读寄存器
uint8_t Class_code; // 类代码,一个只读寄存器,指定设备执行的功能类型
uint8_t CacheLineSize; // 缓存线大小:以 32 位为单位指定系统缓存线大小。设备可以限制它可以支持的缓存线大小的数量,如果不支持的值写入该字段,设备将表现得好像写入了 0 值
uint8_t LatencyTimer; // 延迟计时器:以 PCI 总线时钟为单位指定延迟计时器。
uint8_t HeaderType; // 标头类型 a value of 0x0 specifies a general device, a value of 0x1 specifies a PCI-to-PCI bridge, and a value of 0x2 specifies a CardBus bridge. If bit 7 of this register is set, the device has multiple functions; otherwise, it is a single function device.
uint8_t BIST; // Represents that status and allows control of a devices BIST (built-in self test).
// Here is the layout of the BIST register:
// | bit7 | bit6 | Bits 5-4 | Bits 3-0 |
// | BIST Capable | Start BIST | Reserved | Completion Code |
// for more details, please visit https://wiki.osdev.org/PCI
};
/**
* @brief 表头类型为0x0的pci设备结构
*
*/
struct pci_device_structure_general_device_t
{
struct pci_device_structure_header_t header;
uint32_t BAR0;
uint32_t BAR1;
uint32_t BAR2;
uint32_t BAR3;
uint32_t BAR4;
uint32_t BAR5;
uint32_t Cardbus_CIS_Pointer; // 指向卡信息结构,供在 CardBus 和 PCI 之间共享芯片的设备使用。
uint16_t Subsystem_Vendor_ID;
uint16_t Subsystem_ID;
uint32_t Expansion_ROM_base_address;
uint8_t Capabilities_Pointer;
uint8_t reserved0;
uint16_t reserved1;
uint32_t reserved2;
uint8_t Interrupt_Line; // 指定设备的中断引脚连接到系统中断控制器的哪个输入,并由任何使用中断引脚的设备实现。对于 x86 架构,此寄存器对应于 PIC IRQ 编号 0-15而不是 I/O APIC IRQ 编号并且值0xFF定义为无连接。
uint8_t Interrupt_PIN; // 指定设备使用的中断引脚。其中值为0x1INTA#、0x2INTB#、0x3INTC#、0x4INTD#0x0表示设备不使用中断引脚。
uint8_t Min_Grant; // 一个只读寄存器,用于指定设备所需的突发周期长度(以 1/4 微秒为单位)(假设时钟速率为 33 MHz
uint8_t Max_Latency; // 一个只读寄存器,指定设备需要多长时间访问一次 PCI 总线(以 1/4 微秒为单位)。
} __attribute__((packed));
/**
* @brief 表头类型为0x1的pci设备结构PCI to PCI Bridge
*
*/
struct pci_device_structure_pci_to_pci_bridge_t
{
struct pci_device_structure_header_t header;
uint32_t BAR0;
uint32_t BAR1;
uint8_t Primary_Bus_Number;
uint8_t Secondary_Bus_Number;
uint8_t Subordinate_Bus_Number;
uint8_t Secondary_Latency_Timer;
uint8_t io_base;
uint8_t io_limit;
uint16_t Secondary_Status;
uint16_t Memory_Base;
uint16_t Memory_Limit;
uint16_t Prefetchable_Memory_Base;
uint16_t Prefetchable_Memory_Limit;
uint32_t Prefetchable_Base_Upper_32_Bits;
uint32_t Prefetchable_Limit_Upper_32_Bits;
uint16_t io_Base_Upper_16_Bits;
uint16_t io_Limit_Upper_16_Bits;
uint8_t Capability_Pointer;
uint8_t reserved0;
uint16_t reserved1;
uint32_t Expansion_ROM_base_address;
uint8_t Interrupt_Line;
uint8_t Interrupt_PIN;
uint16_t Bridge_Control;
} __attribute__((packed));
/**
* @brief 表头类型为0x2的pci设备结构PCI to CardBus Bridge
*
*/
struct pci_device_structure_pci_to_cardbus_bridge_t
{
struct pci_device_structure_header_t header;
uint32_t CardBus_Socket_ExCa_base_address;
uint8_t Offset_of_capabilities_list;
uint8_t Reserved;
uint16_t Secondary_status;
uint8_t PCI_bus_number;
uint8_t CardBus_bus_number;
uint8_t Subordinate_bus_number;
uint8_t CardBus_latency_timer;
uint32_t Memory_Base_Address0;
uint32_t Memory_Limit0;
uint32_t Memory_Base_Address1;
uint32_t Memory_Limit1;
uint32_t IO_Base_Address0;
uint32_t IO_Limit0;
uint32_t IO_Base_Address1;
uint32_t IO_Limit1;
uint8_t Interrupt_Line;
uint8_t Interrupt_PIN;
uint16_t Bridge_Control;
uint16_t Subsystem_Device_ID;
uint16_t Subsystem_Vendor_ID;
uint32_t PC_Card_legacy_mode_base_address_16_bit;
} __attribute__((packed));
/**
* @brief 从pci配置空间读取信息
*
* @param bus 总线号
* @param slot 插槽号
* @param func 功能号
* @param offset 字节偏移量
* @return uint 寄存器值
*/
uint32_t pci_read_config(uchar bus, uchar slot, uchar func, uchar offset);
/**
* @brief 向pci配置空间写入信息
*
* @param bus 总线号
* @param slot 设备号
* @param func 功能号
* @param offset 字节偏移量
* @return uint 寄存器值
*/
uint pci_write_config(uchar bus, uchar slot, uchar func, uchar offset, uint32_t data);
/**
* @brief 读取pci设备标头
*
* @param type 标头类型
* @param bus 总线号
* @param slot 插槽号
* @param func 功能号
* @return 返回的header的指针
*/
void *pci_read_header(int *type, uchar bus, uchar slot, uchar func, bool add_to_list);
/**
* @brief 扫描所有pci总线上的所有设备
*
*/
void pci_checkAllBuses();
/**
* @brief 获取 device structure
*
* @param class_code
* @param sub_class
* @param res 返回的结果数组
*/
void pci_get_device_structure(uint8_t class_code, uint8_t sub_class, struct pci_device_structure_header_t *res[], uint32_t *count_res);
/**
* @brief 寻找符合指定类型的capability list
*
* @param pci_dev pci设备header
* @param cap_type c要寻找的capability类型
* @return uint64_t cap list的偏移量
*/
int32_t pci_enumerate_capability_list(struct pci_device_structure_header_t *pci_dev, uint32_t cap_type);

View File

@ -1,9 +1,9 @@
use super::transport_pci::PciTransport;
use super::virtio_impl::HalImpl;
use crate::driver::net::virtio_net::virtio_net;
use crate::driver::pci::pci::PciDeviceStructureGeneralDevice;
use crate::driver::pci::pci::{
get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice,
PCI_DEVICE_LINKEDLIST,
};
use crate::libs::rwlock::RwLockWriteGuard;
use crate::{kdebug, kerror, kwarn};

View File

@ -30,9 +30,7 @@
#include <common/time.h>
#include <common/unistd.h>
#include <driver/disk/ahci/ahci.h>
#include <driver/disk/ahci/ahci_rust.h>
#include <driver/multiboot2/multiboot2.h>
#include <driver/pci/pci.h>
#include <driver/video/video.h>
#include <driver/virtio/virtio.h>
#include <exception/gate.h>

View File

@ -27,7 +27,6 @@
#include "driver/keyboard/ps2_keyboard.h"
#include "driver/mouse/ps2_mouse.h"
#include "driver/multiboot2/multiboot2.h"
#include "driver/pci/pci.h"
#include <driver/timers/HPET/HPET.h>
#include <driver/uart/uart.h>
#include <driver/video/video.h>
@ -165,8 +164,6 @@ void system_initialize()
ps2_keyboard_init();
io_mfence();
pci_init();
rs_pci_init();
// 这里必须加内存屏障,否则会出错

View File

@ -81,8 +81,7 @@ impl Syscall {
timezone: *mut PosixTimeZone,
) -> Result<usize, SystemError> {
// TODO; 处理时区信息
// kdebug!("enter sys_do_gettimeofday");
if tv == null_mut() {
if tv.is_null() {
return Err(SystemError::EFAULT);
}
let mut tv_buf =

View File

@ -142,7 +142,9 @@ impl Timekeeper {
}
}
pub fn timekeeper() -> &'static Timekeeper {
return unsafe { __TIMEKEEPER.as_ref().unwrap() };
let r = unsafe { __TIMEKEEPER.as_ref().unwrap() };
return r;
}
pub fn timekeeper_init() {