mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-22 07:03:22 +00:00
feat: 添加gendisk抽象 (#903)
* feat: 添加gendisk抽象. * 支持使用virtio磁盘作为根文件系统 * Update initial_kthread.rs to resolve conflict. --------- Co-authored-by: Donkey Kane <109840258+xiaolin2004@users.noreply.github.com>
This commit is contained in:
@ -13,12 +13,12 @@ use crate::driver::{
|
||||
block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE},
|
||||
};
|
||||
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use core::any::Any;
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
use core::{any::Any, fmt::Display, ops::Deref};
|
||||
use log::error;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::disk_info::Partition;
|
||||
use super::{disk_info::Partition, gendisk::GenDisk, manager::BlockDevMeta};
|
||||
|
||||
/// 该文件定义了 Device 和 BlockDevice 的接口
|
||||
/// Notice 设备错误码使用 Posix 规定的 int32_t 的错误码表示,而不是自己定义错误enum
|
||||
@ -36,6 +36,41 @@ pub const BLK_SIZE_LOG2_LIMIT: u8 = 12; // 设定块设备的块大小不能超
|
||||
/// 在DragonOS中,我们认为磁盘的每个LBA大小均为512字节。(注意,文件系统的1个扇区可能事实上是多个LBA)
|
||||
pub const LBA_SIZE: usize = 512;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct GeneralBlockRange {
|
||||
pub lba_start: usize,
|
||||
pub lba_end: usize,
|
||||
}
|
||||
|
||||
impl GeneralBlockRange {
|
||||
pub fn new(lba_start: usize, lba_end: usize) -> Option<Self> {
|
||||
if lba_start >= lba_end {
|
||||
return None;
|
||||
}
|
||||
return Some(GeneralBlockRange { lba_start, lba_end });
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
return self.lba_end - self.lba_start;
|
||||
}
|
||||
|
||||
/// 取交集
|
||||
pub fn intersects_with(&self, rhs: &Self) -> Option<Self> {
|
||||
// 检查是否相交
|
||||
if self.lba_start <= rhs.lba_end && self.lba_end >= rhs.lba_start {
|
||||
// 计算相交部分的起始和结束 LBA
|
||||
let start = usize::max(self.lba_start, rhs.lba_start);
|
||||
let end = usize::min(self.lba_end, rhs.lba_end);
|
||||
// 返回相交部分
|
||||
GeneralBlockRange::new(start, end)
|
||||
} else {
|
||||
// 不相交,返回 None
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 块设备的迭代器
|
||||
/// @usage 某次操作读/写块设备的[L,R]范围内的字节,
|
||||
/// 那么可以使用此结构体进行迭代遍历,每次调用next()返回一个BlockRange
|
||||
@ -186,8 +221,80 @@ pub fn __lba_to_bytes(lba_id: usize, blk_size: usize) -> BlockId {
|
||||
return lba_id * blk_size;
|
||||
}
|
||||
|
||||
/// 块设备的名字
|
||||
pub struct BlockDevName {
|
||||
name: Arc<String>,
|
||||
id: usize,
|
||||
}
|
||||
|
||||
impl BlockDevName {
|
||||
pub fn new(name: String, id: usize) -> Self {
|
||||
return BlockDevName {
|
||||
name: Arc::new(name),
|
||||
id,
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn id(&self) -> usize {
|
||||
return self.id;
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for BlockDevName {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
return write!(f, "{}", self.name);
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BlockDevName {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
return write!(f, "{}", self.name);
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for BlockDevName {
|
||||
fn clone(&self) -> Self {
|
||||
return BlockDevName {
|
||||
name: self.name.clone(),
|
||||
id: self.id,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl core::hash::Hash for BlockDevName {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.name.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for BlockDevName {
|
||||
type Target = String;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
return self.name.as_ref();
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for BlockDevName {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
return self.name == other.name;
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for BlockDevName {}
|
||||
|
||||
/// @brief 块设备应该实现的操作
|
||||
pub trait BlockDevice: Device {
|
||||
/// # dev_name
|
||||
/// 返回块设备的名字
|
||||
fn dev_name(&self) -> &BlockDevName;
|
||||
|
||||
fn blkdev_meta(&self) -> &BlockDevMeta;
|
||||
|
||||
/// 获取设备的扇区范围
|
||||
fn disk_range(&self) -> GeneralBlockRange;
|
||||
|
||||
/// @brief: 在块设备中,从第lba_id_start个块开始,读取count个块数据,存放到buf中
|
||||
///
|
||||
/// @parameter lba_id_start: 起始块
|
||||
@ -379,6 +486,11 @@ pub trait BlockDevice: Device {
|
||||
}
|
||||
return Ok(len);
|
||||
}
|
||||
|
||||
/// # gendisk注册成功的回调函数
|
||||
fn callback_gendisk_registered(&self, _gendisk: &Arc<GenDisk>) -> Result<(), SystemError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 块设备框架函数集
|
||||
|
@ -1,22 +1,19 @@
|
||||
#![allow(dead_code)]
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::block_device::BlockDevice;
|
||||
use super::block_device::{BlockDevice, GeneralBlockRange};
|
||||
|
||||
pub type SectorT = u64;
|
||||
|
||||
pub const BLK_TYPE_AHCI: u64 = 0;
|
||||
pub const DISK_NAME_LEN: usize = 32; // 磁盘名称的最大长度
|
||||
pub const BLK_GF_AHCI: u16 = 1 << 0; // 定义blk_gendisk中的标志位
|
||||
|
||||
/// @brief: 磁盘的分区信息 - (保留了c版本的数据信息)
|
||||
#[derive(Debug)]
|
||||
pub struct Partition {
|
||||
pub start_sector: SectorT, // 该分区的起始扇区
|
||||
pub lba_start: u64, // 起始LBA号
|
||||
pub sectors_num: u64, // 该分区的扇区数
|
||||
disk: Weak<dyn BlockDevice>, // 当前分区所属的磁盘
|
||||
pub partno: u16, // 在磁盘上的分区号
|
||||
pub start_sector: SectorT, // 该分区的起始扇区
|
||||
pub lba_start: u64, // 起始LBA号
|
||||
pub sectors_num: u64, // 该分区的扇区数
|
||||
disk: Option<Weak<dyn BlockDevice>>, // 当前分区所属的磁盘
|
||||
pub partno: u16, // 在磁盘上的分区号
|
||||
}
|
||||
|
||||
/// @brief: 分区信息 - 成员函数
|
||||
@ -33,14 +30,39 @@ impl Partition {
|
||||
start_sector,
|
||||
lba_start,
|
||||
sectors_num,
|
||||
disk,
|
||||
disk: Some(disk),
|
||||
partno,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn new_raw(start_sector: SectorT, lba_start: u64, sectors_num: u64, partno: u16) -> Self {
|
||||
return Partition {
|
||||
start_sector,
|
||||
lba_start,
|
||||
sectors_num,
|
||||
disk: None,
|
||||
partno,
|
||||
};
|
||||
}
|
||||
|
||||
/// @brief 获取当前分区所属的磁盘的Arc指针
|
||||
#[inline]
|
||||
pub fn disk(&self) -> Arc<dyn BlockDevice> {
|
||||
return self.disk.upgrade().unwrap();
|
||||
return self.disk.as_ref().unwrap().upgrade().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<GeneralBlockRange> for Partition {
|
||||
type Error = SystemError;
|
||||
|
||||
fn try_into(self) -> Result<GeneralBlockRange, Self::Error> {
|
||||
if let Some(range) = GeneralBlockRange::new(
|
||||
self.lba_start as usize,
|
||||
(self.lba_start + self.sectors_num) as usize,
|
||||
) {
|
||||
return Ok(range);
|
||||
} else {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
195
kernel/src/driver/base/block/gendisk.rs
Normal file
195
kernel/src/driver/base/block/gendisk.rs
Normal file
@ -0,0 +1,195 @@
|
||||
use core::{
|
||||
ops::{Deref, DerefMut},
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use hashbrown::HashMap;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::block_device::{BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GenDisk {
|
||||
bdev: Weak<dyn BlockDevice>,
|
||||
range: GeneralBlockRange,
|
||||
block_size_log2: u8,
|
||||
idx: Option<u32>,
|
||||
}
|
||||
|
||||
impl GenDisk {
|
||||
/// 如果gendisk是整个磁盘,则idx为u32::MAX
|
||||
pub const ENTIRE_DISK_IDX: u32 = u32::MAX;
|
||||
|
||||
pub fn new(
|
||||
bdev: Weak<dyn BlockDevice>,
|
||||
range: GeneralBlockRange,
|
||||
idx: Option<u32>,
|
||||
) -> Arc<Self> {
|
||||
let bsizelog2 = bdev.upgrade().unwrap().blk_size_log2();
|
||||
|
||||
return Arc::new(GenDisk {
|
||||
bdev,
|
||||
range,
|
||||
block_size_log2: bsizelog2,
|
||||
idx,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn block_device(&self) -> Arc<dyn BlockDevice> {
|
||||
return self.bdev.upgrade().unwrap();
|
||||
}
|
||||
|
||||
/// # read_at
|
||||
///
|
||||
/// 读取分区内的数据
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - buf: 输出缓冲区,大小必须为LBA_SIZE的整数倍,否则返回EINVAL
|
||||
/// - start_block_offset: 分区内的块号
|
||||
pub fn read_at(
|
||||
&self,
|
||||
buf: &mut [u8],
|
||||
start_block_offset: BlockId,
|
||||
) -> Result<usize, SystemError> {
|
||||
if (buf.len() & (LBA_SIZE - 1)) > 0 {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let blocks = buf.len() / (1 << self.block_size_log2 as usize);
|
||||
let lba = self.block_offset_2_disk_blkid(start_block_offset);
|
||||
|
||||
return self.block_device().read_at(lba, blocks, buf);
|
||||
}
|
||||
|
||||
/// # read_at_bytes
|
||||
///
|
||||
/// 按字节偏移量从分区中读取数据
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - buf: 输出缓冲区
|
||||
/// - bytes_offset: 分区内的字节偏移量
|
||||
pub fn read_at_bytes(&self, buf: &mut [u8], bytes_offset: usize) -> Result<usize, SystemError> {
|
||||
let start_lba = self.range.lba_start;
|
||||
let bytes_offset = self.disk_blkid_2_bytes(start_lba) + bytes_offset;
|
||||
return self
|
||||
.block_device()
|
||||
.read_at_bytes(bytes_offset, buf.len(), buf);
|
||||
}
|
||||
|
||||
/// # 分区内的字节偏移量转换为磁盘上的字节偏移量
|
||||
pub fn disk_bytes_offset(&self, bytes_offset: usize) -> usize {
|
||||
let start_lba = self.range.lba_start;
|
||||
return self.disk_blkid_2_bytes(start_lba) + bytes_offset;
|
||||
}
|
||||
|
||||
/// # write_at_bytes
|
||||
///
|
||||
/// 按字节偏移量向分区写入数据
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - buf: 输入缓冲区
|
||||
/// - bytes_offset: 分区内的字节偏移量
|
||||
pub fn write_at_bytes(&self, buf: &[u8], bytes_offset: usize) -> Result<usize, SystemError> {
|
||||
let start_lba = self.range.lba_start;
|
||||
let bytes_offset = self.disk_blkid_2_bytes(start_lba) + bytes_offset;
|
||||
return self
|
||||
.block_device()
|
||||
.write_at_bytes(bytes_offset, buf.len(), buf);
|
||||
}
|
||||
|
||||
/// # write_at
|
||||
///
|
||||
/// 向分区内写入数据
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - buf: 输入缓冲区,大小必须为LBA_SIZE的整数倍,否则返回EINVAL
|
||||
/// - start_block_offset: 分区内的块号
|
||||
pub fn write_at(&self, buf: &[u8], start_block_offset: BlockId) -> Result<usize, SystemError> {
|
||||
if (buf.len() & (LBA_SIZE - 1)) > 0 {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let blocks = buf.len() / (1 << self.block_size_log2 as usize);
|
||||
let lba = self.block_offset_2_disk_blkid(start_block_offset);
|
||||
return self.block_device().write_at(lba, blocks, buf);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn block_offset_2_disk_blkid(&self, block_offset: BlockId) -> BlockId {
|
||||
self.range.lba_start + block_offset
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn disk_blkid_2_bytes(&self, disk_blkid: BlockId) -> usize {
|
||||
disk_blkid * LBA_SIZE
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn idx(&self) -> u32 {
|
||||
self.idx.unwrap_or(Self::ENTIRE_DISK_IDX)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn range(&self) -> &GeneralBlockRange {
|
||||
&self.range
|
||||
}
|
||||
|
||||
/// # sync
|
||||
/// 同步磁盘
|
||||
pub fn sync(&self) -> Result<(), SystemError> {
|
||||
self.block_device().sync()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct GenDiskMap {
|
||||
data: HashMap<u32, Arc<GenDisk>>,
|
||||
max_idx: AtomicU32,
|
||||
}
|
||||
|
||||
impl GenDiskMap {
|
||||
pub fn new() -> Self {
|
||||
GenDiskMap {
|
||||
data: HashMap::new(),
|
||||
max_idx: AtomicU32::new(1),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn max_idx(&self) -> u32 {
|
||||
self.max_idx.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn alloc_idx(&self) -> u32 {
|
||||
self.max_idx.fetch_add(1, Ordering::SeqCst)
|
||||
}
|
||||
|
||||
pub fn intersects(&self, range: &GeneralBlockRange) -> bool {
|
||||
for (_, v) in self.iter() {
|
||||
if range.intersects_with(&v.range).is_some() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for GenDiskMap {
|
||||
type Target = HashMap<u32, Arc<GenDisk>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for GenDiskMap {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.data
|
||||
}
|
||||
}
|
238
kernel/src/driver/base/block/manager.rs
Normal file
238
kernel/src/driver/base/block/manager.rs
Normal file
@ -0,0 +1,238 @@
|
||||
use core::fmt::Formatter;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use hashbrown::HashMap;
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
use crate::{
|
||||
driver::base::block::gendisk::GenDisk,
|
||||
filesystem::mbr::MbrDiskPartionTable,
|
||||
init::initcall::INITCALL_POSTCORE,
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
};
|
||||
|
||||
use super::{
|
||||
block_device::{BlockDevName, BlockDevice, GeneralBlockRange},
|
||||
gendisk::GenDiskMap,
|
||||
};
|
||||
|
||||
static mut BLOCK_DEV_MANAGER: Option<BlockDevManager> = None;
|
||||
|
||||
#[inline]
|
||||
pub fn block_dev_manager() -> &'static BlockDevManager {
|
||||
unsafe { BLOCK_DEV_MANAGER.as_ref().unwrap() }
|
||||
}
|
||||
|
||||
#[unified_init(INITCALL_POSTCORE)]
|
||||
pub fn block_dev_manager_init() -> Result<(), SystemError> {
|
||||
unsafe {
|
||||
BLOCK_DEV_MANAGER = Some(BlockDevManager::new());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 磁盘设备管理器
|
||||
pub struct BlockDevManager {
|
||||
inner: SpinLock<InnerBlockDevManager>,
|
||||
}
|
||||
|
||||
struct InnerBlockDevManager {
|
||||
disks: HashMap<BlockDevName, Arc<dyn BlockDevice>>,
|
||||
}
|
||||
impl BlockDevManager {
|
||||
pub fn new() -> Self {
|
||||
BlockDevManager {
|
||||
inner: SpinLock::new(InnerBlockDevManager {
|
||||
disks: HashMap::new(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn inner(&self) -> SpinLockGuard<InnerBlockDevManager> {
|
||||
self.inner.lock()
|
||||
}
|
||||
|
||||
/// 注册磁盘设备
|
||||
pub fn register(&self, dev: Arc<dyn BlockDevice>) -> Result<(), SystemError> {
|
||||
let mut inner = self.inner();
|
||||
let dev_name = dev.dev_name();
|
||||
if inner.disks.contains_key(dev_name) {
|
||||
return Err(SystemError::EEXIST);
|
||||
}
|
||||
inner.disks.insert(dev_name.clone(), dev.clone());
|
||||
|
||||
let mut out_remove = || {
|
||||
inner.disks.remove(dev_name);
|
||||
};
|
||||
|
||||
// 检测分区表,并创建gendisk
|
||||
self.check_partitions(&dev).inspect_err(|_| out_remove())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 检测分区表,并创建gendisk
|
||||
fn check_partitions(&self, dev: &Arc<dyn BlockDevice>) -> Result<(), SystemError> {
|
||||
if self.check_mbr(dev).is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// use entire disk as a gendisk
|
||||
self.register_entire_disk_as_gendisk(dev)
|
||||
}
|
||||
|
||||
fn check_mbr(&self, dev: &Arc<dyn BlockDevice>) -> Result<(), SystemError> {
|
||||
let mbr = MbrDiskPartionTable::from_disk(dev.clone())?;
|
||||
let piter = mbr.partitions_raw();
|
||||
for p in piter {
|
||||
self.register_gendisk_with_range(dev, p.try_into()?)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 将整个磁盘注册为gendisk
|
||||
fn register_entire_disk_as_gendisk(
|
||||
&self,
|
||||
dev: &Arc<dyn BlockDevice>,
|
||||
) -> Result<(), SystemError> {
|
||||
let range = dev.disk_range();
|
||||
self.register_gendisk_with_range(dev, range)
|
||||
}
|
||||
|
||||
fn register_gendisk_with_range(
|
||||
&self,
|
||||
dev: &Arc<dyn BlockDevice>,
|
||||
range: GeneralBlockRange,
|
||||
) -> Result<(), SystemError> {
|
||||
let weak_dev = Arc::downgrade(dev);
|
||||
let gendisk = GenDisk::new(
|
||||
weak_dev,
|
||||
range,
|
||||
Some(dev.blkdev_meta().inner().gendisks.alloc_idx()),
|
||||
);
|
||||
self.register_gendisk(dev, gendisk)
|
||||
}
|
||||
|
||||
fn register_gendisk(
|
||||
&self,
|
||||
dev: &Arc<dyn BlockDevice>,
|
||||
gendisk: Arc<GenDisk>,
|
||||
) -> Result<(), SystemError> {
|
||||
let blk_meta = dev.blkdev_meta();
|
||||
let idx = gendisk.idx();
|
||||
let mut meta_inner = blk_meta.inner();
|
||||
// 检查是否重复
|
||||
if meta_inner.gendisks.intersects(gendisk.range()) {
|
||||
return Err(SystemError::EEXIST);
|
||||
}
|
||||
|
||||
meta_inner.gendisks.insert(idx, gendisk.clone());
|
||||
dev.callback_gendisk_registered(&gendisk).inspect_err(|_| {
|
||||
meta_inner.gendisks.remove(&idx);
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 卸载磁盘设备
|
||||
pub fn unregister(&self, dev: &Arc<dyn BlockDevice>) {
|
||||
let mut inner = self.inner();
|
||||
inner.disks.remove(dev.dev_name());
|
||||
// todo: 这里应该callback一下磁盘设备,但是现在还没实现热插拔,所以暂时没做这里
|
||||
todo!("BlockDevManager: unregister disk")
|
||||
}
|
||||
|
||||
/// 通过路径查找gendisk
|
||||
///
|
||||
/// # 参数
|
||||
///
|
||||
/// - `path`: 分区路径 `/dev/sda1` 或者 `sda1`,或者是`/dev/sda`
|
||||
pub fn lookup_gendisk_by_path(&self, path: &str) -> Option<Arc<GenDisk>> {
|
||||
let (devname, partno) = self.path2devname(path)?;
|
||||
let inner = self.inner();
|
||||
for dev in inner.disks.values() {
|
||||
if dev.dev_name().as_str() == devname {
|
||||
return dev.blkdev_meta().inner().gendisks.get(&partno).cloned();
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// 打印所有的gendisk的路径
|
||||
pub fn print_gendisks(&self) {
|
||||
let mut disks = alloc::vec::Vec::new();
|
||||
|
||||
let inner = self.inner();
|
||||
for dev in inner.disks.values() {
|
||||
let meta = dev.blkdev_meta().inner();
|
||||
for idx in meta.gendisks.keys() {
|
||||
if idx == &GenDisk::ENTIRE_DISK_IDX {
|
||||
disks.push(format!("/dev/{}", dev.dev_name()));
|
||||
} else {
|
||||
disks.push(format!("/dev/{}{}", dev.dev_name(), idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log::debug!("All gendisks: {:?}", disks);
|
||||
}
|
||||
|
||||
/// 将路径转换为设备名以及分区号
|
||||
///
|
||||
/// 例如: sda1 -> (sda, 1) nvme0n1p1 -> (nvme0n1, 1)
|
||||
fn path2devname<'a>(&self, mut path: &'a str) -> Option<(&'a str, u32)> {
|
||||
// 去除开头的"/dev/"
|
||||
if path.starts_with("/dev/") {
|
||||
path = path.strip_prefix("/dev/")?;
|
||||
}
|
||||
|
||||
let mut partno = GenDisk::ENTIRE_DISK_IDX;
|
||||
// 截取末尾数字
|
||||
let mut last_digit = path.len();
|
||||
while last_digit > 0 && path.chars().nth(last_digit - 1).unwrap().is_ascii_digit() {
|
||||
last_digit -= 1;
|
||||
}
|
||||
if last_digit == 0 {
|
||||
return (path, GenDisk::ENTIRE_DISK_IDX).into();
|
||||
}
|
||||
|
||||
if last_digit < path.len() {
|
||||
partno = path[last_digit..].parse().ok()?;
|
||||
}
|
||||
|
||||
let path = &path[..last_digit];
|
||||
|
||||
Some((path, partno))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BlockDevMeta {
|
||||
pub devname: BlockDevName,
|
||||
inner: SpinLock<InnerBlockDevMeta>,
|
||||
}
|
||||
|
||||
pub struct InnerBlockDevMeta {
|
||||
pub gendisks: GenDiskMap,
|
||||
}
|
||||
|
||||
impl BlockDevMeta {
|
||||
pub fn new(devname: BlockDevName) -> Self {
|
||||
BlockDevMeta {
|
||||
devname,
|
||||
inner: SpinLock::new(InnerBlockDevMeta {
|
||||
gendisks: GenDiskMap::new(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn inner(&self) -> SpinLockGuard<InnerBlockDevMeta> {
|
||||
self.inner.lock()
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for BlockDevMeta {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("BlockDevMeta")
|
||||
.field("devname", &self.devname)
|
||||
.finish()
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
pub mod block_device;
|
||||
pub mod disk_info;
|
||||
pub mod gendisk;
|
||||
pub mod manager;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum SeekFrom {
|
||||
|
@ -5,17 +5,19 @@ use alloc::{
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use log::{debug, error};
|
||||
use bitmap::traits::BitMapOps;
|
||||
use log::error;
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
use virtio_drivers::device::blk::VirtIOBlk;
|
||||
use virtio_drivers::device::blk::{VirtIOBlk, SECTOR_SIZE};
|
||||
|
||||
use crate::{
|
||||
driver::{
|
||||
base::{
|
||||
block::{
|
||||
block_device::{BlockDevice, BlockId, LBA_SIZE},
|
||||
block_device::{BlockDevName, BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE},
|
||||
disk_info::Partition,
|
||||
manager::{block_dev_manager, BlockDevMeta},
|
||||
},
|
||||
class::Class,
|
||||
device::{
|
||||
@ -64,18 +66,82 @@ pub fn virtio_blk_0() -> Option<Arc<VirtIOBlkDevice>> {
|
||||
pub fn virtio_blk(transport: VirtIOTransport, dev_id: Arc<DeviceId>) {
|
||||
let device = VirtIOBlkDevice::new(transport, dev_id);
|
||||
if let Some(device) = device {
|
||||
debug!("VirtIOBlkDevice '{:?}' created", device.dev_id);
|
||||
virtio_device_manager()
|
||||
.device_add(device.clone() as Arc<dyn VirtIODevice>)
|
||||
.expect("Add virtio blk failed");
|
||||
}
|
||||
}
|
||||
|
||||
static mut VIRTIOBLK_MANAGER: Option<VirtIOBlkManager> = None;
|
||||
|
||||
#[inline]
|
||||
fn virtioblk_manager() -> &'static VirtIOBlkManager {
|
||||
unsafe { VIRTIOBLK_MANAGER.as_ref().unwrap() }
|
||||
}
|
||||
|
||||
#[unified_init(INITCALL_POSTCORE)]
|
||||
fn virtioblk_manager_init() -> Result<(), SystemError> {
|
||||
unsafe {
|
||||
VIRTIOBLK_MANAGER = Some(VirtIOBlkManager::new());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct VirtIOBlkManager {
|
||||
inner: SpinLock<InnerVirtIOBlkManager>,
|
||||
}
|
||||
|
||||
struct InnerVirtIOBlkManager {
|
||||
id_bmp: bitmap::StaticBitmap<{ VirtIOBlkManager::MAX_DEVICES }>,
|
||||
devname: [Option<BlockDevName>; VirtIOBlkManager::MAX_DEVICES],
|
||||
}
|
||||
|
||||
impl VirtIOBlkManager {
|
||||
pub const MAX_DEVICES: usize = 25;
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: SpinLock::new(InnerVirtIOBlkManager {
|
||||
id_bmp: bitmap::StaticBitmap::new(),
|
||||
devname: [const { None }; Self::MAX_DEVICES],
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn inner(&self) -> SpinLockGuard<InnerVirtIOBlkManager> {
|
||||
self.inner.lock()
|
||||
}
|
||||
|
||||
pub fn alloc_id(&self) -> Option<BlockDevName> {
|
||||
let mut inner = self.inner();
|
||||
let idx = inner.id_bmp.first_false_index()?;
|
||||
inner.id_bmp.set(idx, true);
|
||||
let name = Self::format_name(idx);
|
||||
inner.devname[idx] = Some(name.clone());
|
||||
Some(name)
|
||||
}
|
||||
|
||||
/// Generate a new block device name like 'vda', 'vdb', etc.
|
||||
fn format_name(id: usize) -> BlockDevName {
|
||||
let x = (b'a' + id as u8) as char;
|
||||
BlockDevName::new(format!("vd{}", x), id)
|
||||
}
|
||||
|
||||
pub fn free_id(&self, id: usize) {
|
||||
if id >= Self::MAX_DEVICES {
|
||||
return;
|
||||
}
|
||||
self.inner().id_bmp.set(id, false);
|
||||
self.inner().devname[id] = None;
|
||||
}
|
||||
}
|
||||
|
||||
/// virtio block device
|
||||
#[derive(Debug)]
|
||||
#[cast_to([sync] VirtIODevice)]
|
||||
#[cast_to([sync] Device)]
|
||||
pub struct VirtIOBlkDevice {
|
||||
blkdev_meta: BlockDevMeta,
|
||||
dev_id: Arc<DeviceId>,
|
||||
inner: SpinLock<InnerVirtIOBlkDevice>,
|
||||
locked_kobj_state: LockedKObjectState,
|
||||
@ -87,6 +153,7 @@ unsafe impl Sync for VirtIOBlkDevice {}
|
||||
|
||||
impl VirtIOBlkDevice {
|
||||
pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
|
||||
let devname = virtioblk_manager().alloc_id()?;
|
||||
let irq = transport.irq().map(|irq| IrqNumber::new(irq.data()));
|
||||
let device_inner = VirtIOBlk::<HalImpl, VirtIOTransport>::new(transport);
|
||||
if let Err(e) = device_inner {
|
||||
@ -97,6 +164,7 @@ impl VirtIOBlkDevice {
|
||||
let mut device_inner: VirtIOBlk<HalImpl, VirtIOTransport> = device_inner.unwrap();
|
||||
device_inner.enable_interrupts();
|
||||
let dev = Arc::new_cyclic(|self_ref| Self {
|
||||
blkdev_meta: BlockDevMeta::new(devname),
|
||||
self_ref: self_ref.clone(),
|
||||
dev_id,
|
||||
locked_kobj_state: LockedKObjectState::default(),
|
||||
@ -123,6 +191,26 @@ impl VirtIOBlkDevice {
|
||||
}
|
||||
|
||||
impl BlockDevice for VirtIOBlkDevice {
|
||||
fn dev_name(&self) -> &BlockDevName {
|
||||
&self.blkdev_meta.devname
|
||||
}
|
||||
|
||||
fn blkdev_meta(&self) -> &BlockDevMeta {
|
||||
&self.blkdev_meta
|
||||
}
|
||||
|
||||
fn disk_range(&self) -> GeneralBlockRange {
|
||||
let inner = self.inner();
|
||||
let blocks = inner.device_inner.capacity() as usize * SECTOR_SIZE / LBA_SIZE;
|
||||
drop(inner);
|
||||
log::debug!(
|
||||
"VirtIOBlkDevice '{:?}' disk_range: 0..{}",
|
||||
self.dev_name(),
|
||||
blocks
|
||||
);
|
||||
GeneralBlockRange::new(0, blocks).unwrap()
|
||||
}
|
||||
|
||||
fn read_at_sync(
|
||||
&self,
|
||||
lba_id_start: BlockId,
|
||||
@ -411,7 +499,7 @@ struct InnerVirtIOBlkDriver {
|
||||
|
||||
impl VirtIODriver for VirtIOBlkDriver {
|
||||
fn probe(&self, device: &Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
|
||||
let _dev = device
|
||||
let dev = device
|
||||
.clone()
|
||||
.arc_any()
|
||||
.downcast::<VirtIOBlkDevice>()
|
||||
@ -423,6 +511,7 @@ impl VirtIODriver for VirtIOBlkDriver {
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
block_dev_manager().register(dev as Arc<dyn BlockDevice>)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
use super::{_port, hba::HbaCmdTable};
|
||||
use crate::arch::MMArch;
|
||||
use crate::driver::base::block::block_device::{BlockDevice, BlockId};
|
||||
use crate::driver::base::block::block_device::{
|
||||
BlockDevName, BlockDevice, BlockId, GeneralBlockRange,
|
||||
};
|
||||
use crate::driver::base::block::disk_info::Partition;
|
||||
use crate::driver::base::block::manager::BlockDevMeta;
|
||||
use crate::driver::base::class::Class;
|
||||
use crate::driver::base::device::bus::Bus;
|
||||
|
||||
@ -11,6 +14,7 @@ use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
|
||||
use crate::driver::base::kset::KSet;
|
||||
use crate::driver::disk::ahci::HBA_PxIS_TFES;
|
||||
|
||||
use crate::driver::scsi::scsi_manager;
|
||||
use crate::filesystem::kernfs::KernFSInode;
|
||||
use crate::filesystem::mbr::MbrDiskPartionTable;
|
||||
|
||||
@ -19,13 +23,13 @@ use crate::driver::disk::ahci::hba::{
|
||||
ATA_DEV_DRQ,
|
||||
};
|
||||
use crate::libs::rwlock::{RwLockReadGuard, RwLockWriteGuard};
|
||||
use crate::libs::spinlock::SpinLock;
|
||||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||
use crate::mm::{verify_area, MemoryManagementArch, PhysAddr, VirtAddr};
|
||||
use log::error;
|
||||
use system_error::SystemError;
|
||||
|
||||
use alloc::sync::Weak;
|
||||
use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
|
||||
use core::fmt::Debug;
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
@ -33,8 +37,7 @@ use core::{mem::size_of, ptr::write_bytes};
|
||||
|
||||
/// @brief: 只支持MBR分区格式的磁盘结构体
|
||||
pub struct AhciDisk {
|
||||
pub name: String,
|
||||
pub flags: u16, // 磁盘的状态flags
|
||||
// 磁盘的状态flags
|
||||
pub partitions: Vec<Arc<Partition>>, // 磁盘分区数组
|
||||
// port: &'static mut HbaPort, // 控制硬盘的端口
|
||||
pub ctrl_num: u8,
|
||||
@ -45,16 +48,21 @@ pub struct AhciDisk {
|
||||
|
||||
/// @brief: 带锁的AhciDisk
|
||||
#[derive(Debug)]
|
||||
pub struct LockedAhciDisk(pub SpinLock<AhciDisk>);
|
||||
pub struct LockedAhciDisk {
|
||||
blkdev_meta: BlockDevMeta,
|
||||
inner: SpinLock<AhciDisk>,
|
||||
}
|
||||
|
||||
impl LockedAhciDisk {
|
||||
pub fn inner(&self) -> SpinLockGuard<AhciDisk> {
|
||||
self.inner.lock()
|
||||
}
|
||||
}
|
||||
|
||||
/// 函数实现
|
||||
impl Debug for AhciDisk {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{{ name: {}, flags: {}, part_s: {:?} }}",
|
||||
self.name, self.flags, self.partitions
|
||||
)?;
|
||||
return Ok(());
|
||||
write!(f, "AhciDisk")
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,35 +379,30 @@ impl AhciDisk {
|
||||
}
|
||||
|
||||
impl LockedAhciDisk {
|
||||
pub fn new(
|
||||
name: String,
|
||||
flags: u16,
|
||||
ctrl_num: u8,
|
||||
port_num: u8,
|
||||
) -> Result<Arc<LockedAhciDisk>, SystemError> {
|
||||
pub fn new(ctrl_num: u8, port_num: u8) -> Result<Arc<LockedAhciDisk>, SystemError> {
|
||||
let devname = scsi_manager().alloc_id().ok_or(SystemError::EBUSY)?;
|
||||
// 构建磁盘结构体
|
||||
let result: Arc<LockedAhciDisk> = Arc::new_cyclic(|self_ref| {
|
||||
LockedAhciDisk(SpinLock::new(AhciDisk {
|
||||
name,
|
||||
flags,
|
||||
partitions: Default::default(),
|
||||
let result: Arc<LockedAhciDisk> = Arc::new_cyclic(|self_ref| LockedAhciDisk {
|
||||
blkdev_meta: BlockDevMeta::new(devname),
|
||||
inner: SpinLock::new(AhciDisk {
|
||||
partitions: Vec::new(),
|
||||
ctrl_num,
|
||||
port_num,
|
||||
self_ref: self_ref.clone(),
|
||||
}))
|
||||
}),
|
||||
});
|
||||
let table: MbrDiskPartionTable = result.read_mbr_table()?;
|
||||
|
||||
// 求出有多少可用分区
|
||||
let partitions = table.partitions(Arc::downgrade(&result) as Weak<dyn BlockDevice>);
|
||||
result.0.lock().partitions = partitions;
|
||||
result.inner().partitions = partitions;
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// @brief: 从磁盘中读取 MBR 分区表结构体
|
||||
pub fn read_mbr_table(&self) -> Result<MbrDiskPartionTable, SystemError> {
|
||||
let disk = self.0.lock().self_ref.upgrade().unwrap() as Arc<dyn BlockDevice>;
|
||||
let disk = self.inner().self_ref.upgrade().unwrap() as Arc<dyn BlockDevice>;
|
||||
MbrDiskPartionTable::from_disk(disk)
|
||||
}
|
||||
}
|
||||
@ -509,6 +512,18 @@ impl Device for LockedAhciDisk {
|
||||
}
|
||||
|
||||
impl BlockDevice for LockedAhciDisk {
|
||||
fn dev_name(&self) -> &BlockDevName {
|
||||
&self.blkdev_meta.devname
|
||||
}
|
||||
|
||||
fn blkdev_meta(&self) -> &BlockDevMeta {
|
||||
&self.blkdev_meta
|
||||
}
|
||||
|
||||
fn disk_range(&self) -> GeneralBlockRange {
|
||||
todo!("Get ahci blk disk range")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
self
|
||||
@ -520,12 +535,12 @@ impl BlockDevice for LockedAhciDisk {
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<(), SystemError> {
|
||||
return self.0.lock().sync();
|
||||
return self.inner().sync();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn device(&self) -> Arc<dyn Device> {
|
||||
return self.0.lock().self_ref.upgrade().unwrap();
|
||||
return self.inner().self_ref.upgrade().unwrap();
|
||||
}
|
||||
|
||||
fn block_size(&self) -> usize {
|
||||
@ -533,7 +548,7 @@ impl BlockDevice for LockedAhciDisk {
|
||||
}
|
||||
|
||||
fn partitions(&self) -> Vec<Arc<Partition>> {
|
||||
return self.0.lock().partitions.clone();
|
||||
return self.inner().partitions.clone();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -543,7 +558,7 @@ impl BlockDevice for LockedAhciDisk {
|
||||
count: usize, // 读取lba的数量
|
||||
buf: &mut [u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
self.0.lock().read_at(lba_id_start, count, buf)
|
||||
self.inner().read_at(lba_id_start, count, buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -553,6 +568,6 @@ impl BlockDevice for LockedAhciDisk {
|
||||
count: usize,
|
||||
buf: &[u8],
|
||||
) -> Result<usize, SystemError> {
|
||||
self.0.lock().write_at(lba_id_start, count, buf)
|
||||
self.inner().write_at(lba_id_start, count, buf)
|
||||
}
|
||||
}
|
||||
|
@ -4,31 +4,27 @@ pub mod ahcidisk;
|
||||
pub mod hba;
|
||||
|
||||
use crate::arch::MMArch;
|
||||
use crate::driver::base::block::disk_info::BLK_GF_AHCI;
|
||||
use crate::driver::base::block::manager::block_dev_manager;
|
||||
use crate::driver::block::cache::cached_block_device::BlockCache;
|
||||
// 依赖的rust工具包
|
||||
use crate::driver::disk::ahci::ahcidisk::LockedAhciDisk;
|
||||
use crate::driver::pci::pci::{
|
||||
get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
|
||||
};
|
||||
use crate::filesystem::devfs::devfs_register;
|
||||
|
||||
use crate::driver::disk::ahci::{
|
||||
ahcidisk::LockedAhciDisk,
|
||||
hba::HbaMem,
|
||||
hba::{HbaPort, HbaPortType},
|
||||
};
|
||||
use crate::libs::rwlock::RwLockWriteGuard;
|
||||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||
use crate::mm::{MemoryManagementArch, VirtAddr};
|
||||
use ahci_inode::LockedAhciInode;
|
||||
use alloc::{boxed::Box, collections::LinkedList, format, string::String, sync::Arc, vec::Vec};
|
||||
use alloc::{boxed::Box, collections::LinkedList, vec::Vec};
|
||||
use core::sync::atomic::compiler_fence;
|
||||
use log::{debug, error};
|
||||
use log::debug;
|
||||
use system_error::SystemError;
|
||||
|
||||
// 仅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;
|
||||
@ -56,8 +52,6 @@ fn ahci_device_search<'a>(
|
||||
pub fn ahci_init() -> Result<(), SystemError> {
|
||||
let mut list = PCI_DEVICE_LINKEDLIST.write();
|
||||
let ahci_device = ahci_device_search(&mut list)?;
|
||||
// 全局数据 - 列表
|
||||
let mut disks_list = LOCKED_DISKS_LIST.lock();
|
||||
|
||||
for device in ahci_device {
|
||||
let standard_device = device.as_standard_device_mut().unwrap();
|
||||
@ -81,7 +75,6 @@ pub fn ahci_init() -> Result<(), SystemError> {
|
||||
let hba_mem_index = hba_mem_list.len() - 1;
|
||||
drop(hba_mem_list);
|
||||
// 初始化所有的port
|
||||
let mut id = 0;
|
||||
for j in 0..32 {
|
||||
if (pi >> j) & 1 > 0 {
|
||||
let hba_mem_list = LOCKED_HBA_MEM_LIST.lock();
|
||||
@ -124,31 +117,12 @@ pub fn ahci_init() -> Result<(), SystemError> {
|
||||
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,
|
||||
hba_mem_index as u8,
|
||||
j as u8,
|
||||
)?);
|
||||
id += 1; // ID 从0开始
|
||||
let ahci_disk = LockedAhciDisk::new(hba_mem_index as u8, j as u8)?;
|
||||
block_dev_manager()
|
||||
.register(ahci_disk)
|
||||
.expect("register ahci disk failed");
|
||||
|
||||
debug!("start register ahci device");
|
||||
|
||||
// 挂载到devfs上面去
|
||||
let ret = devfs_register(
|
||||
format!("ahci_{}", id).as_str(),
|
||||
LockedAhciInode::new(disks_list.last().unwrap().clone()),
|
||||
);
|
||||
if let Err(err) = ret {
|
||||
error!(
|
||||
"Ahci_{} ctrl = {}, port = {} failed to register, error code = {:?}",
|
||||
id,
|
||||
hba_mem_index as u8,
|
||||
j,
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,24 +134,6 @@ pub fn ahci_init() -> Result<(), SystemError> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// @brief: 获取所有的 disk
|
||||
#[allow(dead_code)]
|
||||
pub fn disks() -> Vec<Arc<LockedAhciDisk>> {
|
||||
let disks_list = LOCKED_DISKS_LIST.lock();
|
||||
return disks_list.clone();
|
||||
}
|
||||
|
||||
/// @brief: 通过 name 获取 disk
|
||||
pub fn get_disks_by_name(name: String) -> Result<Arc<LockedAhciDisk>, SystemError> {
|
||||
let disks_list: SpinLockGuard<Vec<Arc<LockedAhciDisk>>> = LOCKED_DISKS_LIST.lock();
|
||||
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
|
||||
fn _port(ctrl_num: u8, port_num: u8) -> &'static mut HbaPort {
|
||||
let list: SpinLockGuard<Vec<&mut HbaMem>> = LOCKED_HBA_MEM_LIST.lock();
|
||||
|
@ -11,6 +11,7 @@ pub mod net;
|
||||
pub mod open_firmware;
|
||||
pub mod pci;
|
||||
pub mod rtc;
|
||||
pub mod scsi;
|
||||
pub mod serial;
|
||||
pub mod timers;
|
||||
pub mod tty;
|
||||
|
74
kernel/src/driver/scsi/mod.rs
Normal file
74
kernel/src/driver/scsi/mod.rs
Normal file
@ -0,0 +1,74 @@
|
||||
use bitmap::traits::BitMapOps;
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
use crate::{
|
||||
init::initcall::INITCALL_POSTCORE,
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
};
|
||||
|
||||
use super::base::block::block_device::BlockDevName;
|
||||
|
||||
static mut SCSI_MANAGER: Option<ScsiManager> = None;
|
||||
|
||||
#[inline]
|
||||
pub fn scsi_manager() -> &'static ScsiManager {
|
||||
unsafe { SCSI_MANAGER.as_ref().unwrap() }
|
||||
}
|
||||
|
||||
#[unified_init(INITCALL_POSTCORE)]
|
||||
fn scsi_manager_init() -> Result<(), SystemError> {
|
||||
unsafe {
|
||||
SCSI_MANAGER = Some(ScsiManager::new());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct ScsiManager {
|
||||
inner: SpinLock<InnerScsiManager>,
|
||||
}
|
||||
|
||||
struct InnerScsiManager {
|
||||
id_bmp: bitmap::StaticBitmap<{ ScsiManager::MAX_DEVICES }>,
|
||||
devname: [Option<BlockDevName>; ScsiManager::MAX_DEVICES],
|
||||
}
|
||||
|
||||
impl ScsiManager {
|
||||
pub const MAX_DEVICES: usize = 25;
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: SpinLock::new(InnerScsiManager {
|
||||
id_bmp: bitmap::StaticBitmap::new(),
|
||||
devname: [const { None }; Self::MAX_DEVICES],
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn inner(&self) -> SpinLockGuard<InnerScsiManager> {
|
||||
self.inner.lock()
|
||||
}
|
||||
|
||||
pub fn alloc_id(&self) -> Option<BlockDevName> {
|
||||
let mut inner = self.inner();
|
||||
let idx = inner.id_bmp.first_false_index()?;
|
||||
inner.id_bmp.set(idx, true);
|
||||
let name = Self::format_name(idx);
|
||||
inner.devname[idx] = Some(name.clone());
|
||||
Some(name)
|
||||
}
|
||||
|
||||
/// Generate a new block device name like 'sda', 'sdb', etc.
|
||||
fn format_name(id: usize) -> BlockDevName {
|
||||
let x = (b'a' + id as u8) as char;
|
||||
BlockDevName::new(format!("sd{}", x), id)
|
||||
}
|
||||
|
||||
pub fn free_id(&self, id: usize) {
|
||||
if id >= Self::MAX_DEVICES {
|
||||
return;
|
||||
}
|
||||
self.inner().id_bmp.set(id, false);
|
||||
self.inner().devname[id] = None;
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
use alloc::sync::Arc;
|
||||
use hashbrown::HashMap;
|
||||
use log::warn;
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
@ -121,7 +120,7 @@ impl IrqHandler for DefaultVirtioIrqHandler {
|
||||
return dev.handle_irq(irq);
|
||||
} else {
|
||||
// 未绑定具体设备,因此无法处理中断
|
||||
warn!("No device found for IRQ: {:?}", irq);
|
||||
// warn!("No device found for IRQ: {:?}", irq);
|
||||
return Ok(IrqReturn::NotHandled);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user