mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 07:06:47 +00:00
添加帧缓冲区抽象并实现vesafb的驱动 (#483)
- 添加bootparams对象 - 修正由于bus的driver、device强弱引用关系 不正确从而导致对象被释放的bug - 添加vesafb的驱动 - 实现framebuffer抽象层 - 为通用帧缓冲区抽象实现sysfs的属性 - 修改设备号DeviceNumber的定义 - 仿照linux,添加initcall,并在第一个内核线程中,调用他们。
This commit is contained in:
parent
e3eb08d4d7
commit
c566df451c
@ -2,3 +2,4 @@ pub mod apic;
|
||||
mod c_adapter;
|
||||
pub mod hpet;
|
||||
pub mod tsc;
|
||||
pub mod video;
|
||||
|
9
kernel/src/arch/x86_64/driver/video/mod.rs
Normal file
9
kernel/src/arch/x86_64/driver/video/mod.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::driver::video::fbdev::vesafb::vesafb_early_init;
|
||||
|
||||
/// 在内存管理初始化之前,初始化视频驱动(架构相关)
|
||||
pub fn arch_video_early_init() -> Result<(), SystemError> {
|
||||
vesafb_early_init()?;
|
||||
return Ok(());
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
/// 引入Module
|
||||
use crate::{
|
||||
driver::base::{
|
||||
device::{mkdev, Device, DeviceError, DeviceNumber, IdTable, BLOCKDEVS},
|
||||
device::{
|
||||
device_number::{DeviceNumber, Major},
|
||||
Device, DeviceError, IdTable, BLOCKDEVS,
|
||||
},
|
||||
map::{
|
||||
DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START,
|
||||
DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX, MINOR_MASK,
|
||||
DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX,
|
||||
},
|
||||
},
|
||||
kerror,
|
||||
@ -328,37 +331,40 @@ impl BlockDeviceOps {
|
||||
/// @parameter: major: 主设备号
|
||||
/// @return: 返回下标
|
||||
#[allow(dead_code)]
|
||||
fn major_to_index(major: usize) -> usize {
|
||||
return major % DEV_MAJOR_HASH_SIZE;
|
||||
fn major_to_index(major: Major) -> usize {
|
||||
return (major.data() % DEV_MAJOR_HASH_SIZE as u32) as usize;
|
||||
}
|
||||
|
||||
/// @brief: 动态获取主设备号
|
||||
/// @parameter: None
|
||||
/// @return: 如果成功,返回主设备号,否则,返回错误码
|
||||
#[allow(dead_code)]
|
||||
fn find_dynamic_major() -> Result<usize, SystemError> {
|
||||
fn find_dynamic_major() -> Result<Major, SystemError> {
|
||||
let blockdevs = BLOCKDEVS.lock();
|
||||
// 寻找主设备号为234~255的设备
|
||||
for index in (DEV_MAJOR_DYN_END..DEV_MAJOR_HASH_SIZE).rev() {
|
||||
if let Some(item) = blockdevs.get(index) {
|
||||
for index in ((DEV_MAJOR_DYN_END.data())..DEV_MAJOR_HASH_SIZE).rev() {
|
||||
if let Some(item) = blockdevs.get(index as usize) {
|
||||
if item.is_empty() {
|
||||
return Ok(index); // 返回可用的主设备号
|
||||
return Ok(Major::new(index)); // 返回可用的主设备号
|
||||
}
|
||||
}
|
||||
}
|
||||
// 寻找主设备号在384~511的设备
|
||||
for index in (DEV_MAJOR_DYN_EXT_END + 1..DEV_MAJOR_DYN_EXT_START + 1).rev() {
|
||||
if let Some(blockdevss) = blockdevs.get(Self::major_to_index(index)) {
|
||||
for index in
|
||||
((DEV_MAJOR_DYN_EXT_END.data() + 1)..(DEV_MAJOR_DYN_EXT_START.data() + 1)).rev()
|
||||
{
|
||||
if let Some(blockdevss) = blockdevs.get(Self::major_to_index(Major::new(index as u32)))
|
||||
{
|
||||
let mut flag = true;
|
||||
for item in blockdevss {
|
||||
if item.device_number().major() == index {
|
||||
if item.device_number().major() == Major::new(index as u32) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if flag {
|
||||
// 如果数组中不存在主设备号等于index的设备
|
||||
return Ok(index); // 返回可用的主设备号
|
||||
return Ok(Major::new(index)); // 返回可用的主设备号
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -373,7 +379,7 @@ impl BlockDeviceOps {
|
||||
#[allow(dead_code)]
|
||||
pub fn register_blockdev_region(
|
||||
from: DeviceNumber,
|
||||
count: usize,
|
||||
count: u32,
|
||||
name: &'static str,
|
||||
) -> Result<DeviceNumber, SystemError> {
|
||||
Self::__register_blockdev_region(from, count, name)
|
||||
@ -386,11 +392,15 @@ impl BlockDeviceOps {
|
||||
/// @return: 如果注册成功,返回,否则,返回false
|
||||
#[allow(dead_code)]
|
||||
pub fn alloc_blockdev_region(
|
||||
baseminor: usize,
|
||||
count: usize,
|
||||
baseminor: u32,
|
||||
count: u32,
|
||||
name: &'static str,
|
||||
) -> Result<DeviceNumber, SystemError> {
|
||||
Self::__register_blockdev_region(mkdev(0, baseminor), count, name)
|
||||
Self::__register_blockdev_region(
|
||||
DeviceNumber::new(Major::UNNAMED_MAJOR, baseminor),
|
||||
count,
|
||||
name,
|
||||
)
|
||||
}
|
||||
|
||||
/// @brief: 注册设备号
|
||||
@ -400,25 +410,25 @@ impl BlockDeviceOps {
|
||||
/// @return: 如果注册成功,返回设备号,否则,返回错误码
|
||||
fn __register_blockdev_region(
|
||||
device_number: DeviceNumber,
|
||||
minorct: usize,
|
||||
minorct: u32,
|
||||
name: &'static str,
|
||||
) -> Result<DeviceNumber, SystemError> {
|
||||
let mut major = device_number.major();
|
||||
let baseminor = device_number.minor();
|
||||
if major >= DEV_MAJOR_MAX {
|
||||
kerror!(
|
||||
"DEV {} major requested {} is greater than the maximum {}\n",
|
||||
"DEV {} major requested {:?} is greater than the maximum {}\n",
|
||||
name,
|
||||
major,
|
||||
DEV_MAJOR_MAX - 1
|
||||
DEV_MAJOR_MAX.data() - 1
|
||||
);
|
||||
}
|
||||
if minorct > MINOR_MASK + 1 - baseminor {
|
||||
if minorct > DeviceNumber::MINOR_MASK + 1 - baseminor {
|
||||
kerror!("DEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n",
|
||||
name, baseminor, baseminor + minorct - 1, 0, MINOR_MASK);
|
||||
name, baseminor, baseminor + minorct - 1, 0, DeviceNumber::MINOR_MASK);
|
||||
}
|
||||
let blockdev = DeviceStruct::new(mkdev(major, baseminor), minorct, name);
|
||||
if major == 0 {
|
||||
let blockdev = DeviceStruct::new(DeviceNumber::new(major, baseminor), minorct, name);
|
||||
if major == Major::UNNAMED_MAJOR {
|
||||
// 如果主设备号为0,则自动分配主设备号
|
||||
major = Self::find_dynamic_major().expect("Find synamic major error.\n");
|
||||
}
|
||||
@ -444,7 +454,8 @@ impl BlockDeviceOps {
|
||||
}
|
||||
items.insert(insert_index, blockdev);
|
||||
}
|
||||
return Ok(mkdev(major, baseminor));
|
||||
|
||||
return Ok(DeviceNumber::new(major, baseminor));
|
||||
}
|
||||
|
||||
/// @brief: 注销设备号
|
||||
@ -454,7 +465,7 @@ impl BlockDeviceOps {
|
||||
/// @return: 如果注销成功,返回(),否则,返回错误码
|
||||
fn __unregister_blockdev_region(
|
||||
device_number: DeviceNumber,
|
||||
minorct: usize,
|
||||
minorct: u32,
|
||||
) -> Result<(), SystemError> {
|
||||
if let Some(items) = BLOCKDEVS
|
||||
.lock()
|
||||
@ -478,7 +489,7 @@ impl BlockDeviceOps {
|
||||
/// @return: none
|
||||
#[allow(dead_code)]
|
||||
pub fn bdev_add(_bdev: Arc<dyn BlockDevice>, id_table: IdTable) -> Result<(), DeviceError> {
|
||||
if Into::<usize>::into(id_table.device_number()) == 0 {
|
||||
if id_table.device_number().data() == 0 {
|
||||
kerror!("Device number can't be 0!\n");
|
||||
}
|
||||
todo!("bdev_add")
|
||||
|
@ -4,10 +4,14 @@ use crate::kerror;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::{
|
||||
device::{device_manager, mkdev, Device, DeviceNumber, IdTable, CHARDEVS, DEVMAP},
|
||||
device::{
|
||||
device_manager,
|
||||
device_number::{DeviceNumber, Major},
|
||||
Device, IdTable, CHARDEVS, DEVMAP,
|
||||
},
|
||||
map::{
|
||||
kobj_map, kobj_unmap, DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END,
|
||||
DEV_MAJOR_DYN_EXT_START, DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX, MINOR_MASK,
|
||||
DEV_MAJOR_DYN_EXT_START, DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX,
|
||||
},
|
||||
};
|
||||
|
||||
@ -41,37 +45,39 @@ impl CharDevOps {
|
||||
/// @parameter: major: 主设备号
|
||||
/// @return: 返回下标
|
||||
#[allow(dead_code)]
|
||||
fn major_to_index(major: usize) -> usize {
|
||||
return major % DEV_MAJOR_HASH_SIZE;
|
||||
fn major_to_index(major: Major) -> usize {
|
||||
return (major.data() % DEV_MAJOR_HASH_SIZE) as usize;
|
||||
}
|
||||
|
||||
/// @brief: 动态获取主设备号
|
||||
/// @parameter: None
|
||||
/// @return: 如果成功,返回主设备号,否则,返回错误码
|
||||
#[allow(dead_code)]
|
||||
fn find_dynamic_major() -> Result<usize, SystemError> {
|
||||
fn find_dynamic_major() -> Result<Major, SystemError> {
|
||||
let chardevs = CHARDEVS.lock();
|
||||
// 寻找主设备号为234~255的设备
|
||||
for index in (DEV_MAJOR_DYN_END..DEV_MAJOR_HASH_SIZE).rev() {
|
||||
if let Some(item) = chardevs.get(index) {
|
||||
for index in (DEV_MAJOR_DYN_END.data()..DEV_MAJOR_HASH_SIZE).rev() {
|
||||
if let Some(item) = chardevs.get(index as usize) {
|
||||
if item.is_empty() {
|
||||
return Ok(index); // 返回可用的主设备号
|
||||
return Ok(Major::new(index)); // 返回可用的主设备号
|
||||
}
|
||||
}
|
||||
}
|
||||
// 寻找主设备号在384~511的设备
|
||||
for index in (DEV_MAJOR_DYN_EXT_END + 1..DEV_MAJOR_DYN_EXT_START + 1).rev() {
|
||||
if let Some(chardevss) = chardevs.get(Self::major_to_index(index)) {
|
||||
for index in
|
||||
((DEV_MAJOR_DYN_EXT_END.data() + 1)..(DEV_MAJOR_DYN_EXT_START.data() + 1)).rev()
|
||||
{
|
||||
if let Some(chardevss) = chardevs.get(Self::major_to_index(Major::new(index))) {
|
||||
let mut flag = true;
|
||||
for item in chardevss {
|
||||
if item.device_number().major() == index {
|
||||
if item.device_number().major().data() == index {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if flag {
|
||||
// 如果数组中不存在主设备号等于index的设备
|
||||
return Ok(index); // 返回可用的主设备号
|
||||
return Ok(Major::new(index)); // 返回可用的主设备号
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,7 +92,7 @@ impl CharDevOps {
|
||||
#[allow(dead_code)]
|
||||
pub fn register_chardev_region(
|
||||
from: DeviceNumber,
|
||||
count: usize,
|
||||
count: u32,
|
||||
name: &'static str,
|
||||
) -> Result<DeviceNumber, SystemError> {
|
||||
Self::__register_chardev_region(from, count, name)
|
||||
@ -99,11 +105,15 @@ impl CharDevOps {
|
||||
/// @return: 如果注册成功,返回,否则,返回false
|
||||
#[allow(dead_code)]
|
||||
pub fn alloc_chardev_region(
|
||||
baseminor: usize,
|
||||
count: usize,
|
||||
baseminor: u32,
|
||||
count: u32,
|
||||
name: &'static str,
|
||||
) -> Result<DeviceNumber, SystemError> {
|
||||
Self::__register_chardev_region(mkdev(0, baseminor), count, name)
|
||||
Self::__register_chardev_region(
|
||||
DeviceNumber::new(Major::UNNAMED_MAJOR, baseminor),
|
||||
count,
|
||||
name,
|
||||
)
|
||||
}
|
||||
|
||||
/// @brief: 注册设备号
|
||||
@ -113,25 +123,25 @@ impl CharDevOps {
|
||||
/// @return: 如果注册成功,返回设备号,否则,返回错误码
|
||||
fn __register_chardev_region(
|
||||
device_number: DeviceNumber,
|
||||
minorct: usize,
|
||||
minorct: u32,
|
||||
name: &'static str,
|
||||
) -> Result<DeviceNumber, SystemError> {
|
||||
let mut major = device_number.major();
|
||||
let baseminor = device_number.minor();
|
||||
if major >= DEV_MAJOR_MAX {
|
||||
kerror!(
|
||||
"DEV {} major requested {} is greater than the maximum {}\n",
|
||||
"DEV {} major requested {:?} is greater than the maximum {}\n",
|
||||
name,
|
||||
major,
|
||||
DEV_MAJOR_MAX - 1
|
||||
DEV_MAJOR_MAX.data() - 1
|
||||
);
|
||||
}
|
||||
if minorct > MINOR_MASK + 1 - baseminor {
|
||||
if minorct > DeviceNumber::MINOR_MASK + 1 - baseminor {
|
||||
kerror!("DEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n",
|
||||
name, baseminor, baseminor + minorct - 1, 0, MINOR_MASK);
|
||||
name, baseminor, baseminor + minorct - 1, 0, DeviceNumber::MINOR_MASK);
|
||||
}
|
||||
let chardev = DeviceStruct::new(mkdev(major, baseminor), minorct, name);
|
||||
if major == 0 {
|
||||
let chardev = DeviceStruct::new(DeviceNumber::new(major, baseminor), minorct, name);
|
||||
if major == Major::UNNAMED_MAJOR {
|
||||
// 如果主设备号为0,则自动分配主设备号
|
||||
major = Self::find_dynamic_major().expect("Find synamic major error.\n");
|
||||
}
|
||||
@ -157,7 +167,8 @@ impl CharDevOps {
|
||||
}
|
||||
items.insert(insert_index, chardev);
|
||||
}
|
||||
return Ok(mkdev(major, baseminor));
|
||||
|
||||
return Ok(DeviceNumber::new(major, baseminor));
|
||||
}
|
||||
|
||||
/// @brief: 注销设备号
|
||||
@ -167,7 +178,7 @@ impl CharDevOps {
|
||||
/// @return: 如果注销成功,返回(),否则,返回错误码
|
||||
fn __unregister_chardev_region(
|
||||
device_number: DeviceNumber,
|
||||
minorct: usize,
|
||||
minorct: u32,
|
||||
) -> Result<(), SystemError> {
|
||||
if let Some(items) = CHARDEVS
|
||||
.lock()
|
||||
@ -195,7 +206,7 @@ impl CharDevOps {
|
||||
id_table: IdTable,
|
||||
range: usize,
|
||||
) -> Result<(), SystemError> {
|
||||
if Into::<usize>::into(id_table.device_number()) == 0 {
|
||||
if id_table.device_number().data() == 0 {
|
||||
kerror!("Device number can't be 0!\n");
|
||||
}
|
||||
device_manager().add_device(cdev.clone())?;
|
||||
|
@ -85,11 +85,8 @@ impl dyn Class {
|
||||
let subsys = self.subsystem();
|
||||
let guard = subsys.devices();
|
||||
for dev in guard.iter() {
|
||||
let dev = dev.upgrade();
|
||||
if let Some(dev) = dev {
|
||||
if matcher.match_device(&dev, data) {
|
||||
return Some(dev.clone());
|
||||
}
|
||||
if matcher.match_device(&dev, data) {
|
||||
return Some(dev.clone());
|
||||
}
|
||||
}
|
||||
return None;
|
||||
|
@ -18,7 +18,7 @@ use super::{
|
||||
device::{
|
||||
bus::{subsystem_manager, Bus},
|
||||
driver::Driver,
|
||||
Device, DeviceNumber, DeviceType, IdTable,
|
||||
Device, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
@ -124,7 +124,7 @@ impl CpuSubSystemFakeRootDevice {
|
||||
#[derive(Debug)]
|
||||
struct InnerCpuSubSystemFakeRootDevice {
|
||||
parent_kobj: Option<Weak<dyn KObject>>,
|
||||
bus: Option<Arc<dyn Bus>>,
|
||||
bus: Option<Weak<dyn Bus>>,
|
||||
kset: Option<Arc<KSet>>,
|
||||
name: String,
|
||||
kern_inode: Option<Arc<KernFSInode>>,
|
||||
@ -150,13 +150,17 @@ impl Device for CpuSubSystemFakeRootDevice {
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
IdTable::new("cpu".to_string(), Some(DeviceNumber::new(0)))
|
||||
IdTable::new("cpu".to_string(), None)
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>) {
|
||||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
|
||||
self.inner.write().bus = bus;
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
self.inner.read().bus.clone()
|
||||
}
|
||||
|
||||
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||
None
|
||||
}
|
||||
|
@ -159,11 +159,14 @@ pub trait Bus: Debug + Send + Sync {
|
||||
/// - `Ok(true)` - 匹配成功
|
||||
/// - `Ok(false)` - 匹配失败
|
||||
/// - `Err(_)` - 由于内部错误导致匹配失败
|
||||
/// - `Err(SystemError::ENOSYS)` - 该总线不支持该操作
|
||||
fn match_device(
|
||||
&self,
|
||||
device: &Arc<dyn Device>,
|
||||
driver: &Arc<dyn Driver>,
|
||||
) -> Result<bool, SystemError>;
|
||||
_device: &Arc<dyn Device>,
|
||||
_driver: &Arc<dyn Driver>,
|
||||
) -> Result<bool, SystemError> {
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
|
||||
fn subsystem(&self) -> &SubSysPrivate;
|
||||
|
||||
@ -188,11 +191,8 @@ impl dyn Bus {
|
||||
let subsys = self.subsystem();
|
||||
let guard = subsys.devices();
|
||||
for dev in guard.iter() {
|
||||
let dev = dev.upgrade();
|
||||
if let Some(dev) = dev {
|
||||
if matcher.match_device(&dev, data) {
|
||||
return Some(dev.clone());
|
||||
}
|
||||
if matcher.match_device(&dev, data) {
|
||||
return Some(dev.clone());
|
||||
}
|
||||
}
|
||||
return None;
|
||||
@ -221,11 +221,8 @@ impl dyn Bus {
|
||||
let subsys = self.subsystem();
|
||||
let guard = subsys.drivers();
|
||||
for drv in guard.iter() {
|
||||
let drv = drv.upgrade();
|
||||
if let Some(drv) = drv {
|
||||
if matcher.match_driver(&drv, data) {
|
||||
return Some(drv.clone());
|
||||
}
|
||||
if matcher.match_driver(&drv, data) {
|
||||
return Some(drv.clone());
|
||||
}
|
||||
}
|
||||
return None;
|
||||
@ -265,7 +262,7 @@ impl BusManager {
|
||||
///
|
||||
/// - `dev` - 要被添加的设备
|
||||
pub fn add_device(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let bus = dev.bus();
|
||||
let bus = dev.bus().map(|bus| bus.upgrade()).flatten();
|
||||
if let Some(bus) = bus {
|
||||
device_manager().add_groups(dev, bus.dev_groups())?;
|
||||
|
||||
@ -295,7 +292,11 @@ impl BusManager {
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_add_driver#590
|
||||
pub fn add_driver(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
|
||||
let bus = driver.bus().ok_or(SystemError::EINVAL)?;
|
||||
let bus = driver
|
||||
.bus()
|
||||
.map(|bus| bus.upgrade())
|
||||
.flatten()
|
||||
.ok_or(SystemError::EINVAL)?;
|
||||
kdebug!("bus '{}' add driver '{}'", bus.name(), driver.name());
|
||||
|
||||
driver.set_kobj_type(Some(&BusDriverKType));
|
||||
@ -435,10 +436,7 @@ impl BusManager {
|
||||
#[allow(dead_code)]
|
||||
pub fn rescan_devices(&self, bus: &Arc<dyn Bus>) -> Result<(), SystemError> {
|
||||
for dev in bus.subsystem().devices().iter() {
|
||||
let dev = dev.upgrade();
|
||||
if let Some(dev) = dev {
|
||||
rescan_devices_helper(dev)?;
|
||||
}
|
||||
rescan_devices_helper(dev)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
@ -447,7 +445,7 @@ impl BusManager {
|
||||
///
|
||||
/// Automatically probe for a driver if the bus allows it.
|
||||
pub fn probe_device(&self, dev: &Arc<dyn Device>) {
|
||||
let bus = dev.bus();
|
||||
let bus = dev.bus().map(|bus| bus.upgrade()).flatten();
|
||||
if bus.is_none() {
|
||||
return;
|
||||
}
|
||||
@ -490,9 +488,12 @@ impl BusManager {
|
||||
}
|
||||
|
||||
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?r=&mo=5649&fi=241#684
|
||||
fn rescan_devices_helper(dev: Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
fn rescan_devices_helper(dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
if dev.driver().is_none() {
|
||||
let need_parent_lock = dev.bus().map(|bus| bus.need_parent_lock()).unwrap_or(false);
|
||||
let need_parent_lock = dev
|
||||
.bus()
|
||||
.map(|bus| bus.upgrade().unwrap().need_parent_lock())
|
||||
.unwrap_or(false);
|
||||
if unlikely(need_parent_lock) {
|
||||
// todo: lock device parent
|
||||
unimplemented!()
|
||||
@ -580,6 +581,7 @@ pub fn bus_add_device(dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
///
|
||||
/// 参考: https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/bus.c?fi=bus_probe_device#478
|
||||
pub fn bus_probe_device(dev: &Arc<dyn Device>) {
|
||||
kinfo!("bus_probe_device: dev: {:?}", dev.name());
|
||||
bus_manager().probe_device(dev);
|
||||
}
|
||||
|
||||
@ -613,7 +615,7 @@ impl Attribute for BusAttrDriversProbe {
|
||||
|
||||
let device = bus.find_device_by_name(name).ok_or(SystemError::ENODEV)?;
|
||||
|
||||
if rescan_devices_helper(device).is_ok() {
|
||||
if rescan_devices_helper(&device).is_ok() {
|
||||
return Ok(buf.len());
|
||||
}
|
||||
|
||||
@ -752,7 +754,11 @@ impl Attribute for DriverAttrUnbind {
|
||||
SystemError::EOPNOTSUPP_OR_ENOTSUP
|
||||
})?;
|
||||
|
||||
let bus = driver.bus().ok_or(SystemError::ENODEV)?;
|
||||
let bus = driver
|
||||
.bus()
|
||||
.map(|bus| bus.upgrade())
|
||||
.flatten()
|
||||
.ok_or(SystemError::ENODEV)?;
|
||||
|
||||
let s = CStr::from_bytes_with_nul(buf)
|
||||
.map_err(|_| SystemError::EINVAL)?
|
||||
@ -798,7 +804,11 @@ impl Attribute for DriverAttrBind {
|
||||
SystemError::EOPNOTSUPP_OR_ENOTSUP
|
||||
})?;
|
||||
|
||||
let bus = driver.bus().ok_or(SystemError::ENODEV)?;
|
||||
let bus = driver
|
||||
.bus()
|
||||
.map(|bus| bus.upgrade())
|
||||
.flatten()
|
||||
.ok_or(SystemError::ENODEV)?;
|
||||
let device = bus
|
||||
.find_device_by_name(
|
||||
CStr::from_bytes_with_nul(buf)
|
||||
|
@ -63,6 +63,8 @@ impl DeviceManager {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
kwarn!("do_device_attach: dev: '{}'", dev.name());
|
||||
|
||||
let mut do_async = false;
|
||||
let mut r = Ok(false);
|
||||
|
||||
@ -78,14 +80,21 @@ impl DeviceManager {
|
||||
return Ok(false);
|
||||
}
|
||||
} else {
|
||||
let bus = dev.bus().ok_or(SystemError::EINVAL)?;
|
||||
let bus = dev
|
||||
.bus()
|
||||
.map(|bus| bus.upgrade())
|
||||
.flatten()
|
||||
.ok_or(SystemError::EINVAL)?;
|
||||
let mut data = DeviceAttachData::new(dev.clone(), allow_async, false);
|
||||
let mut flag = true;
|
||||
let mut flag = false;
|
||||
for driver in bus.subsystem().drivers().iter() {
|
||||
if let Some(driver) = driver.upgrade() {
|
||||
let r = self.do_device_attach_driver(&driver, &mut data);
|
||||
if unlikely(r.is_err()) {
|
||||
flag = false;
|
||||
let r = self.do_device_attach_driver(&driver, &mut data);
|
||||
if unlikely(r.is_err()) {
|
||||
flag = false;
|
||||
break;
|
||||
} else {
|
||||
if r.unwrap() == true {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -116,13 +125,52 @@ impl DeviceManager {
|
||||
return r;
|
||||
}
|
||||
|
||||
/// 匹配设备和驱动
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `driver`: 驱动
|
||||
/// - `data`: 匹配数据
|
||||
///
|
||||
/// ## 返回
|
||||
///
|
||||
/// - Ok(true): 匹配成功
|
||||
/// - Ok(false): 没有匹配成功
|
||||
/// - Err(SystemError): 匹配过程中出现意外错误,没有匹配成功
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/dd.c#899
|
||||
fn do_device_attach_driver(
|
||||
&self,
|
||||
_driver: &Arc<dyn Driver>,
|
||||
_data: &mut DeviceAttachData,
|
||||
) -> Result<(), SystemError> {
|
||||
todo!("do_device_attach_driver")
|
||||
driver: &Arc<dyn Driver>,
|
||||
data: &mut DeviceAttachData,
|
||||
) -> Result<bool, SystemError> {
|
||||
if let Some(bus) = driver.bus().map(|bus| bus.upgrade()).flatten() {
|
||||
let r = bus.match_device(&data.dev, driver);
|
||||
|
||||
if let Err(e) = r {
|
||||
// 如果不是ENOSYS,则总线出错
|
||||
if e != SystemError::ENOSYS {
|
||||
kdebug!(
|
||||
"do_device_attach_driver: bus.match_device() failed, dev: '{}', err: {:?}",
|
||||
data.dev.name(),
|
||||
e
|
||||
);
|
||||
return Err(e);
|
||||
}
|
||||
} else {
|
||||
if r.unwrap() == false {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let async_allowed = driver.allows_async_probing();
|
||||
if data.check_async && async_allowed != data.want_async {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
return driver_manager()
|
||||
.probe_device(driver, &data.dev)
|
||||
.map(|_| true);
|
||||
}
|
||||
|
||||
/// 检查设备是否绑定到驱动程序
|
||||
@ -162,7 +210,7 @@ impl DeviceManager {
|
||||
driver_manager().driver_bound(dev);
|
||||
return Err(e);
|
||||
} else {
|
||||
if let Some(bus) = dev.bus() {
|
||||
if let Some(bus) = dev.bus().map(|bus| bus.upgrade()).flatten() {
|
||||
bus.subsystem().bus_notifier().call_chain(
|
||||
BusNotifyEvent::DriverNotBound,
|
||||
Some(dev),
|
||||
@ -233,13 +281,15 @@ impl DriverManager {
|
||||
/// 这个函数会遍历驱动现有的全部设备,然后尝试把他们匹配。
|
||||
/// 一旦有一个设备匹配成功,就会返回,并且设备的driver字段会被设置。
|
||||
pub fn driver_attach(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
|
||||
let bus = driver.bus().ok_or(SystemError::EINVAL)?;
|
||||
let bus = driver
|
||||
.bus()
|
||||
.map(|bus| bus.upgrade())
|
||||
.flatten()
|
||||
.ok_or(SystemError::EINVAL)?;
|
||||
for dev in bus.subsystem().devices().iter() {
|
||||
if let Some(dev) = dev.upgrade() {
|
||||
if self.do_driver_attach(&dev, &driver) {
|
||||
// 匹配成功
|
||||
return Ok(());
|
||||
}
|
||||
if self.do_driver_attach(&dev, &driver) {
|
||||
// 匹配成功
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,7 +324,12 @@ impl DriverManager {
|
||||
driver: &Arc<dyn Driver>,
|
||||
device: &Arc<dyn Device>,
|
||||
) -> Result<bool, SystemError> {
|
||||
return driver.bus().unwrap().match_device(device, driver);
|
||||
return driver
|
||||
.bus()
|
||||
.map(|bus| bus.upgrade())
|
||||
.flatten()
|
||||
.unwrap()
|
||||
.match_device(device, driver);
|
||||
}
|
||||
|
||||
/// 尝试把设备和驱动绑定在一起
|
||||
@ -327,7 +382,7 @@ impl DriverManager {
|
||||
};
|
||||
|
||||
let sysfs_failed = || {
|
||||
if let Some(bus) = device.bus() {
|
||||
if let Some(bus) = device.bus().map(|bus| bus.upgrade()).flatten() {
|
||||
bus.subsystem().bus_notifier().call_chain(
|
||||
BusNotifyEvent::DriverNotBound,
|
||||
Some(device),
|
||||
@ -385,7 +440,7 @@ impl DriverManager {
|
||||
e
|
||||
})?;
|
||||
|
||||
// 我们假设所有的设备都有sync_state这个属性。如果没有的话,也创建属性文件。
|
||||
// 我们假设所有的设备都有 sync_state 这个属性。如果没有的话,也创建属性文件。
|
||||
device_manager()
|
||||
.create_file(device, &DeviceAttrStateSynced)
|
||||
.map_err(|e| {
|
||||
@ -410,7 +465,7 @@ impl DriverManager {
|
||||
fn add_to_sysfs(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let driver = device.driver().ok_or(SystemError::EINVAL)?;
|
||||
|
||||
if let Some(bus) = device.bus() {
|
||||
if let Some(bus) = device.bus().map(|bus| bus.upgrade()).flatten() {
|
||||
bus.subsystem().bus_notifier().call_chain(
|
||||
BusNotifyEvent::BindDriver,
|
||||
Some(&device),
|
||||
@ -455,7 +510,11 @@ impl DriverManager {
|
||||
device: &Arc<dyn Device>,
|
||||
driver: &Arc<dyn Driver>,
|
||||
) -> Result<(), SystemError> {
|
||||
let bus = device.bus().ok_or(SystemError::EINVAL)?;
|
||||
let bus = device
|
||||
.bus()
|
||||
.map(|bus| bus.upgrade())
|
||||
.flatten()
|
||||
.ok_or(SystemError::EINVAL)?;
|
||||
let r = bus.probe(device);
|
||||
if r == Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) {
|
||||
kerror!(
|
||||
@ -505,7 +564,7 @@ impl DriverManager {
|
||||
let driver = device.driver().unwrap();
|
||||
driver.add_device(device.clone());
|
||||
|
||||
if let Some(bus) = device.bus() {
|
||||
if let Some(bus) = device.bus().map(|bus| bus.upgrade()).flatten() {
|
||||
bus.subsystem().bus_notifier().call_chain(
|
||||
BusNotifyEvent::BoundDriver,
|
||||
Some(device),
|
||||
|
60
kernel/src/driver/base/device/device_number.rs
Normal file
60
kernel/src/driver/base/device/device_number.rs
Normal file
@ -0,0 +1,60 @@
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Major(u32);
|
||||
|
||||
impl Major {
|
||||
// 常量定义参考:
|
||||
//
|
||||
// https://code.dragonos.org.cn/xref/linux-6.1.9/include/uapi/linux/major.h
|
||||
|
||||
/// 未命名的主设备
|
||||
pub const UNNAMED_MAJOR: Self = Self::new(0);
|
||||
/// /dev/fb* framebuffers
|
||||
pub const FB_MAJOR: Self = Self::new(29);
|
||||
|
||||
pub const fn new(x: u32) -> Self {
|
||||
Major(x)
|
||||
}
|
||||
pub const fn data(&self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceNumber {
|
||||
data: u32,
|
||||
}
|
||||
|
||||
impl DeviceNumber {
|
||||
pub const MINOR_BITS: u32 = 20;
|
||||
pub const MINOR_MASK: u32 = 1 << Self::MINOR_BITS - 1;
|
||||
|
||||
pub const fn new(major: Major, minor: u32) -> Self {
|
||||
Self {
|
||||
data: (major.data() << Self::MINOR_BITS) | minor,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn major(&self) -> Major {
|
||||
Major::new(self.data >> Self::MINOR_BITS)
|
||||
}
|
||||
|
||||
pub const fn minor(&self) -> u32 {
|
||||
self.data & 0xfffff
|
||||
}
|
||||
|
||||
pub const fn data(&self) -> u32 {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DeviceNumber {
|
||||
fn default() -> Self {
|
||||
Self::new(Major::UNNAMED_MAJOR, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for DeviceNumber {
|
||||
fn from(x: u32) -> Self {
|
||||
Self { data: x }
|
||||
}
|
||||
}
|
@ -6,7 +6,10 @@ use crate::{
|
||||
driver::base::kobject::KObject,
|
||||
filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup},
|
||||
};
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use alloc::{
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::fmt::Debug;
|
||||
use system_error::SystemError;
|
||||
|
||||
@ -86,11 +89,11 @@ pub trait Driver: Sync + Send + Debug + KObject {
|
||||
false
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>);
|
||||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>);
|
||||
|
||||
fn groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||
&[]
|
||||
@ -171,13 +174,17 @@ impl DriverManager {
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/driver.c#222
|
||||
pub fn register(&self, driver: Arc<dyn Driver>) -> Result<(), SystemError> {
|
||||
let bus = driver.bus().ok_or_else(|| {
|
||||
kerror!(
|
||||
"DriverManager::register() failed: driver.bus() is None. Driver: '{:?}'",
|
||||
driver.name()
|
||||
);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
let bus = driver
|
||||
.bus()
|
||||
.map(|bus| bus.upgrade())
|
||||
.flatten()
|
||||
.ok_or_else(|| {
|
||||
kerror!(
|
||||
"DriverManager::register() failed: driver.bus() is None. Driver: '{:?}'",
|
||||
driver.name()
|
||||
);
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
|
||||
let drv_name = driver.name();
|
||||
let other = bus.find_driver_by_name(&drv_name);
|
||||
|
@ -24,6 +24,7 @@ use system_error::SystemError;
|
||||
|
||||
use self::{
|
||||
bus::{bus_add_device, bus_probe_device, Bus},
|
||||
device_number::{DeviceNumber, Major},
|
||||
driver::Driver,
|
||||
};
|
||||
|
||||
@ -36,6 +37,7 @@ use super::{
|
||||
|
||||
pub mod bus;
|
||||
pub mod dd;
|
||||
pub mod device_number;
|
||||
pub mod driver;
|
||||
pub mod init;
|
||||
|
||||
@ -143,14 +145,16 @@ pub trait Device: KObject {
|
||||
}
|
||||
|
||||
/// 获取当前设备所属的总线
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
return None;
|
||||
}
|
||||
|
||||
/// 设置当前设备所属的总线
|
||||
///
|
||||
/// (一定要传入Arc,因为bus的subsysprivate里面存储的是Device的Weak指针)
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>);
|
||||
/// (一定要传入Arc,因为bus的subsysprivate里面存储的是Device的Arc指针)
|
||||
///
|
||||
/// 注意,如果实现了当前方法,那么必须实现`bus()`方法
|
||||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>);
|
||||
|
||||
/// 获取当前设备所属的类
|
||||
fn class(&self) -> Option<Arc<dyn Class>> {
|
||||
@ -158,6 +162,8 @@ pub trait Device: KObject {
|
||||
}
|
||||
|
||||
/// 设置当前设备所属的类
|
||||
///
|
||||
/// 注意,如果实现了当前方法,那么必须实现`class()`方法
|
||||
fn set_class(&self, class: Option<Arc<dyn Class>>);
|
||||
|
||||
/// 返回已经与当前设备匹配好的驱动程序
|
||||
@ -221,62 +227,6 @@ impl DevicePrivateData {
|
||||
}
|
||||
}
|
||||
|
||||
int_like!(DeviceNumber, usize);
|
||||
|
||||
impl Default for DeviceNumber {
|
||||
fn default() -> Self {
|
||||
DeviceNumber(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for DeviceNumber {
|
||||
fn from(dev_t: usize) -> Self {
|
||||
DeviceNumber(dev_t)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<usize> for DeviceNumber {
|
||||
fn into(self) -> usize {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl core::hash::Hash for DeviceNumber {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceNumber {
|
||||
/// @brief: 获取主设备号
|
||||
/// @parameter: none
|
||||
/// @return: 主设备号
|
||||
pub fn major(&self) -> usize {
|
||||
(self.0 >> 8) & 0xffffff
|
||||
}
|
||||
|
||||
/// @brief: 获取次设备号
|
||||
/// @parameter: none
|
||||
/// @return: 次设备号
|
||||
pub fn minor(&self) -> usize {
|
||||
self.0 & 0xff
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn from_major_minor(major: usize, minor: usize) -> usize {
|
||||
((major & 0xffffff) << 8) | (minor & 0xff)
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief: 根据主次设备号创建设备号实例
|
||||
/// @parameter: major: 主设备号
|
||||
/// minor: 次设备号
|
||||
/// @return: 设备号实例
|
||||
pub fn mkdev(major: usize, minor: usize) -> DeviceNumber {
|
||||
DeviceNumber(((major & 0xfff) << 20) | (minor & 0xfffff))
|
||||
}
|
||||
|
||||
/// @brief: 设备类型
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
@ -317,12 +267,13 @@ impl IdTable {
|
||||
if self.id.is_none() {
|
||||
return self.basename.clone();
|
||||
} else {
|
||||
return format!("{}:{}", self.basename, self.id.unwrap().data());
|
||||
let id = self.id.unwrap();
|
||||
return format!("{}:{}", id.major().data(), id.minor());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn device_number(&self) -> DeviceNumber {
|
||||
return self.id.unwrap_or(DeviceNumber::new(0));
|
||||
return self.id.unwrap_or(DeviceNumber::default());
|
||||
}
|
||||
}
|
||||
|
||||
@ -460,16 +411,10 @@ impl DeviceManager {
|
||||
}
|
||||
|
||||
pub fn register(&self, device: Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
self.device_initialize(&device);
|
||||
self.device_default_initialize(&device);
|
||||
return self.add_device(device);
|
||||
}
|
||||
|
||||
/// device_initialize - init device structure.
|
||||
pub fn device_initialize(&self, device: &Arc<dyn Device>) {
|
||||
device.set_kset(Some(sys_devices_kset()));
|
||||
device.set_kobj_type(Some(&DeviceKObjType));
|
||||
}
|
||||
|
||||
/// @brief: 添加设备
|
||||
/// @parameter id_table: 总线标识符,用于唯一标识该总线
|
||||
/// @parameter dev: 设备实例
|
||||
@ -514,14 +459,14 @@ impl DeviceManager {
|
||||
|
||||
bus_add_device(&device)?;
|
||||
|
||||
if device.id_table().device_number().major() != 0 {
|
||||
if device.id_table().device_number().major() != Major::UNNAMED_MAJOR {
|
||||
self.create_file(&device, &DeviceAttrDev)?;
|
||||
|
||||
self.create_sys_dev_entry(&device)?;
|
||||
}
|
||||
|
||||
// 通知客户端有关设备添加的信息。此调用必须在 dpm_sysfs_add() 之后且在 kobject_uevent() 之前执行。
|
||||
if let Some(bus) = device.bus() {
|
||||
if let Some(bus) = device.bus().map(|bus| bus.upgrade()).flatten() {
|
||||
bus.subsystem().bus_notifier().call_chain(
|
||||
bus::BusNotifyEvent::AddDevice,
|
||||
Some(&device),
|
||||
@ -585,7 +530,7 @@ impl DeviceManager {
|
||||
|
||||
// subsystems can specify a default root directory for their devices
|
||||
if current_parent.is_none() {
|
||||
if let Some(bus) = device.bus() {
|
||||
if let Some(bus) = device.bus().map(|bus| bus.upgrade()).flatten() {
|
||||
if let Some(root) = bus.root_device().map(|x| x.upgrade()).flatten() {
|
||||
return Ok(Some(root as Arc<dyn KObject>));
|
||||
}
|
||||
@ -627,6 +572,7 @@ impl DeviceManager {
|
||||
software_node_notify(dev);
|
||||
}
|
||||
|
||||
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/core.c#3224
|
||||
fn add_class_symlinks(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let class = dev.class();
|
||||
if class.is_none() {
|
||||
@ -635,6 +581,10 @@ impl DeviceManager {
|
||||
|
||||
// 定义错误处理函数,用于在添加符号链接失败时,移除已经添加的符号链接
|
||||
|
||||
let err_remove_device = |dev_kobj: &Arc<dyn KObject>| {
|
||||
sysfs_instance().remove_link(dev_kobj, "device".to_string());
|
||||
};
|
||||
|
||||
let err_remove_subsystem = |dev_kobj: &Arc<dyn KObject>| {
|
||||
sysfs_instance().remove_link(dev_kobj, "subsystem".to_string());
|
||||
};
|
||||
@ -645,11 +595,20 @@ impl DeviceManager {
|
||||
sysfs_instance().create_link(Some(&dev_kobj), &subsys_kobj, "subsystem".to_string())?;
|
||||
|
||||
// todo: 这里需要处理class的parent逻辑, 添加device链接
|
||||
// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/core.c#3245
|
||||
if let Some(parent) = dev.parent().map(|x| x.upgrade()).flatten() {
|
||||
let parent_kobj = parent.clone() as Arc<dyn KObject>;
|
||||
sysfs_instance()
|
||||
.create_link(Some(&dev_kobj), &&parent_kobj, "device".to_string())
|
||||
.map_err(|e| {
|
||||
err_remove_subsystem(&dev_kobj);
|
||||
e
|
||||
})?;
|
||||
}
|
||||
|
||||
sysfs_instance()
|
||||
.create_link(Some(&subsys_kobj), &dev_kobj, dev.name())
|
||||
.map_err(|e| {
|
||||
err_remove_device(&dev_kobj);
|
||||
err_remove_subsystem(&dev_kobj);
|
||||
e
|
||||
})?;
|
||||
@ -776,7 +735,7 @@ impl DeviceManager {
|
||||
let target_kobj = self.device_to_dev_kobj(dev);
|
||||
let name = dev.id_table().name();
|
||||
let current_kobj = dev.clone() as Arc<dyn KObject>;
|
||||
return sysfs_instance().create_link(Some(¤t_kobj), &target_kobj, name);
|
||||
return sysfs_instance().create_link(Some(&target_kobj), ¤t_kobj, name);
|
||||
}
|
||||
|
||||
/// Delete symlink for device in `/sys/dev` or `/sys/class/<class_name>`
|
||||
@ -810,6 +769,7 @@ impl DeviceManager {
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/core.c?fi=device_initialize#2976
|
||||
pub fn device_default_initialize(&self, dev: &Arc<dyn Device>) {
|
||||
dev.set_kset(Some(sys_devices_kset()));
|
||||
dev.set_kobj_type(Some(&DeviceKObjType));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -874,7 +834,11 @@ impl Attribute for DeviceAttrDev {
|
||||
})?;
|
||||
|
||||
let device_number = dev.id_table().device_number();
|
||||
let s = format!("{}:{}\n", device_number.major(), device_number.minor());
|
||||
let s = format!(
|
||||
"{}:{}\n",
|
||||
device_number.major().data(),
|
||||
device_number.minor()
|
||||
);
|
||||
|
||||
return sysfs_emit_str(buf, &s);
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
use crate::driver::tty::tty_device::tty_init;
|
||||
use system_error::SystemError;
|
||||
use unified_init::{define_public_unified_initializer_slice, unified_init};
|
||||
|
||||
use super::{
|
||||
class::classes_init,
|
||||
@ -11,8 +9,6 @@ use super::{
|
||||
platform::platform_bus_init,
|
||||
};
|
||||
|
||||
define_public_unified_initializer_slice!(SUBSYSTEM_INITIALIZER_SLICE);
|
||||
|
||||
pub(super) fn driver_init() -> Result<(), SystemError> {
|
||||
devices_init()?;
|
||||
buses_init()?;
|
||||
@ -21,7 +17,7 @@ pub(super) fn driver_init() -> Result<(), SystemError> {
|
||||
hypervisor_init()?;
|
||||
platform_bus_init()?;
|
||||
cpu_device_manager().init()?;
|
||||
subsystem_init()?;
|
||||
|
||||
// 至此,已完成设备驱动模型的初始化
|
||||
// 接下来,初始化设备
|
||||
actual_device_init()?;
|
||||
@ -29,12 +25,6 @@ pub(super) fn driver_init() -> Result<(), SystemError> {
|
||||
}
|
||||
|
||||
fn actual_device_init() -> Result<(), SystemError> {
|
||||
tty_init()?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn subsystem_init() -> Result<(), SystemError> {
|
||||
unified_init!(SUBSYSTEM_INITIALIZER_SLICE);
|
||||
// 应当使用unified_init来初始化
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -109,11 +109,10 @@ impl Deref for LockedKObjectState {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait KObjectAttribute: Attribute {
|
||||
fn support(&self) -> SysFSOpsSupport;
|
||||
|
||||
fn show(&self, kobj: &dyn KObject, buf: &mut [u8]) -> Result<usize, SystemError>;
|
||||
fn store(&self, kobj: &dyn KObject, buf: &[u8]) -> Result<usize, SystemError>;
|
||||
impl Default for LockedKObjectState {
|
||||
fn default() -> Self {
|
||||
LockedKObjectState::new(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -1,22 +1,21 @@
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
use super::{
|
||||
device::{mkdev, DeviceNumber},
|
||||
device::device_number::{DeviceNumber, Major},
|
||||
kobject::KObject,
|
||||
};
|
||||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||
use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
|
||||
|
||||
const KOBJMAP_HASH_SIZE: usize = 255;
|
||||
pub(crate) const DEV_MAJOR_HASH_SIZE: usize = 255;
|
||||
pub(crate) const DEV_MAJOR_MAX: usize = 512;
|
||||
pub(crate) const MINOR_BITS: usize = 20;
|
||||
pub(crate) const MINOR_MASK: usize = 1 << MINOR_BITS - 1;
|
||||
pub(crate) const DEV_MAJOR_HASH_SIZE: u32 = 255;
|
||||
pub(crate) const DEV_MAJOR_MAX: Major = Major::new(512);
|
||||
|
||||
/* Marks the bottom of the first segment of free char majors */
|
||||
pub(crate) const DEV_MAJOR_DYN_END: usize = 234;
|
||||
pub(crate) const DEV_MAJOR_DYN_END: Major = Major::new(234);
|
||||
/* Marks the top and bottom of the second segment of free char majors */
|
||||
pub(crate) const DEV_MAJOR_DYN_EXT_START: usize = 511;
|
||||
pub(crate) const DEV_MAJOR_DYN_EXT_END: usize = 384;
|
||||
pub(crate) const DEV_MAJOR_DYN_EXT_START: Major = Major::new(511);
|
||||
pub(crate) const DEV_MAJOR_DYN_EXT_END: Major = Major::new(384);
|
||||
|
||||
/// @brief: 字符设备与块设备管理结构体
|
||||
#[derive(Debug, Clone)]
|
||||
@ -63,10 +62,15 @@ pub fn kobj_map(
|
||||
range: usize,
|
||||
data: Arc<dyn KObject>,
|
||||
) {
|
||||
if let Some(map) = domain.0.lock().0.get_mut(dev_t.major() % 255) {
|
||||
if let Some(map) = domain
|
||||
.0
|
||||
.lock()
|
||||
.0
|
||||
.get_mut((dev_t.major().data() % 255) as usize)
|
||||
{
|
||||
for i in 0..range {
|
||||
map.insert(
|
||||
mkdev(dev_t.major(), dev_t.minor() + i),
|
||||
DeviceNumber::new(dev_t.major(), dev_t.minor() + i as u32),
|
||||
Probe::new(data.clone()),
|
||||
);
|
||||
}
|
||||
@ -79,9 +83,14 @@ pub fn kobj_map(
|
||||
/// range: 次设备号范围
|
||||
/// @return: none
|
||||
pub fn kobj_unmap(domain: Arc<LockedKObjMap>, dev_t: DeviceNumber, range: usize) {
|
||||
if let Some(map) = domain.0.lock().0.get_mut(dev_t.major() % 255) {
|
||||
if let Some(map) = domain
|
||||
.0
|
||||
.lock()
|
||||
.0
|
||||
.get_mut((dev_t.major().data() % 255) as usize)
|
||||
{
|
||||
for i in 0..range {
|
||||
let rm_dev_t = &DeviceNumber::new(Into::<usize>::into(dev_t) + i);
|
||||
let rm_dev_t = &DeviceNumber::new(dev_t.major(), dev_t.minor() + i as u32);
|
||||
match map.get(rm_dev_t) {
|
||||
Some(_) => {
|
||||
map.remove(rm_dev_t);
|
||||
@ -98,7 +107,7 @@ pub fn kobj_unmap(domain: Arc<LockedKObjMap>, dev_t: DeviceNumber, range: usize)
|
||||
/// @return: 查找成功,返回设备实例,否则返回None
|
||||
#[allow(dead_code)]
|
||||
pub fn kobj_lookup(domain: Arc<LockedKObjMap>, dev_t: DeviceNumber) -> Option<Arc<dyn KObject>> {
|
||||
if let Some(map) = domain.0.lock().0.get(dev_t.major() % 255) {
|
||||
if let Some(map) = domain.0.lock().0.get((dev_t.major().data() % 255) as usize) {
|
||||
match map.get(&dev_t) {
|
||||
Some(value) => {
|
||||
return Some(value.0.clone());
|
||||
@ -133,7 +142,7 @@ pub struct DevsMap(Vec<Vec<DeviceStruct>>);
|
||||
|
||||
impl Default for DevsMap {
|
||||
fn default() -> Self {
|
||||
DevsMap(vec![Vec::new(); DEV_MAJOR_HASH_SIZE])
|
||||
DevsMap(vec![Vec::new(); DEV_MAJOR_HASH_SIZE as usize])
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +165,7 @@ impl DerefMut for DevsMap {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DeviceStruct {
|
||||
dev_t: DeviceNumber, //起始设备号
|
||||
minorct: usize, // 次设备号数量
|
||||
minorct: u32, // 次设备号数量
|
||||
name: &'static str, //字符设备名
|
||||
}
|
||||
|
||||
@ -169,7 +178,7 @@ impl DeviceStruct {
|
||||
/// @return: 实例
|
||||
///
|
||||
#[allow(dead_code)]
|
||||
pub fn new(dev_t: DeviceNumber, minorct: usize, name: &'static str) -> Self {
|
||||
pub fn new(dev_t: DeviceNumber, minorct: u32, name: &'static str) -> Self {
|
||||
Self {
|
||||
dev_t,
|
||||
minorct,
|
||||
@ -191,7 +200,7 @@ impl DeviceStruct {
|
||||
/// @return: 起始设备号
|
||||
///
|
||||
#[allow(dead_code)]
|
||||
pub fn base_minor(&self) -> usize {
|
||||
pub fn base_minor(&self) -> u32 {
|
||||
self.dev_t.minor()
|
||||
}
|
||||
|
||||
@ -199,7 +208,7 @@ impl DeviceStruct {
|
||||
/// @parameter: None
|
||||
/// @return: 次设备号数量
|
||||
#[allow(dead_code)]
|
||||
pub fn minorct(&self) -> usize {
|
||||
pub fn minorct(&self) -> u32 {
|
||||
self.minorct
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use self::{platform_device::PlatformBusDevice, subsys::PlatformBus};
|
||||
use super::{
|
||||
device::{
|
||||
bus::{bus_register, Bus, BusState},
|
||||
device_unregister, sys_devices_kset, DeviceNumber, DevicePrivateData, IdTable,
|
||||
device_unregister, sys_devices_kset, DevicePrivateData, IdTable,
|
||||
},
|
||||
kobject::KObject,
|
||||
};
|
||||
@ -77,7 +77,7 @@ impl CompatibleTable {
|
||||
pub fn platform_bus_init() -> Result<(), SystemError> {
|
||||
let platform_device: Arc<PlatformBusDevice> = PlatformBusDevice::new(
|
||||
DevicePrivateData::new(
|
||||
IdTable::new("platform".to_string(), Some(DeviceNumber::new(0))),
|
||||
IdTable::new("platform".to_string(), None),
|
||||
BusState::NotInitialized.into(),
|
||||
),
|
||||
Some(Arc::downgrade(&(sys_devices_kset() as Arc<dyn KObject>))),
|
||||
|
@ -11,7 +11,7 @@ use crate::{
|
||||
bus::{Bus, BusState},
|
||||
device_manager,
|
||||
driver::Driver,
|
||||
Device, DeviceNumber, DevicePrivateData, DeviceType, IdTable,
|
||||
Device, DevicePrivateData, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
@ -44,8 +44,8 @@ pub const PLATFORM_DEVID_AUTO: i32 = -2;
|
||||
///
|
||||
/// ## 注意
|
||||
///
|
||||
/// 应当在所有实现这个trait的结构体上方,添加 `#[cast_to([sync] PlatformDriver)]`,
|
||||
/// 否则运行时将报错“该对象不是PlatformDriver”
|
||||
/// 应当在所有实现这个trait的结构体上方,添加 `#[cast_to([sync] PlatformDevice)]`,
|
||||
/// 否则运行时将报错“该对象不是PlatformDevice”
|
||||
pub trait PlatformDevice: Device {
|
||||
fn pdev_name(&self) -> &str;
|
||||
/// 返回平台设备id,以及这个id是否是自动生成的
|
||||
@ -85,7 +85,7 @@ impl PlatformDeviceManager {
|
||||
)));
|
||||
}
|
||||
|
||||
pdev.set_bus(Some(platform_bus() as Arc<dyn Bus>));
|
||||
pdev.set_bus(Some(Arc::downgrade(&(platform_bus() as Arc<dyn Bus>))));
|
||||
|
||||
let id = pdev.pdev_id().0;
|
||||
match id {
|
||||
@ -195,7 +195,7 @@ pub struct InnerPlatformBusDevice {
|
||||
|
||||
kernfs_inode: Option<Arc<KernFSInode>>,
|
||||
/// 当前设备挂载到的总线
|
||||
bus: Option<Arc<dyn Bus>>,
|
||||
bus: Option<Weak<dyn Bus>>,
|
||||
/// 当前设备已经匹配的驱动
|
||||
driver: Option<Weak<dyn Driver>>,
|
||||
|
||||
@ -286,16 +286,15 @@ impl Device for PlatformBusDevice {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
fn id_table(&self) -> IdTable {
|
||||
IdTable::new("platform".to_string(), Some(DeviceNumber::new(0)))
|
||||
IdTable::new("platform".to_string(), None)
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
self.inner.lock().bus.clone()
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>) {
|
||||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
|
||||
self.inner.lock().bus = bus;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ use super::{platform_bus, platform_device::PlatformDevice};
|
||||
pub trait PlatformDriver: Driver {
|
||||
/// 检测设备是否能绑定到这个驱动
|
||||
///
|
||||
/// 如果能,则把设备的driver指向这个驱动。
|
||||
/// 如果能,则把设备的driver字段指向这个驱动。
|
||||
/// 请注意,这个函数不应该把driver加入驱动的devices列表,相关工作会在外部的函数里面处理。
|
||||
fn probe(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
fn remove(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError>;
|
||||
@ -41,7 +41,7 @@ impl PlatformDriverManager {
|
||||
///
|
||||
/// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/drivers/base/platform.c?fi=__platform_driver_register#861
|
||||
pub fn register(&self, driver: Arc<dyn PlatformDriver>) -> Result<(), SystemError> {
|
||||
driver.set_bus(Some(platform_bus() as Arc<dyn Bus>));
|
||||
driver.set_bus(Some(Arc::downgrade(&(platform_bus() as Arc<dyn Bus>))));
|
||||
return driver_manager().register(driver as Arc<dyn Driver>);
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,9 @@ pub struct SubSysPrivate {
|
||||
class: SpinLock<Option<Weak<dyn Class>>>,
|
||||
drivers_autoprobe: AtomicBool,
|
||||
/// 当前总线上的所有设备
|
||||
devices: RwLock<Vec<Weak<dyn Device>>>,
|
||||
devices: RwLock<Vec<Arc<dyn Device>>>,
|
||||
/// 当前总线上的所有驱动
|
||||
drivers: RwLock<Vec<Weak<dyn Driver>>>,
|
||||
drivers: RwLock<Vec<Arc<dyn Driver>>>,
|
||||
interfaces: &'static [&'static dyn SubSysInterface],
|
||||
bus_notifier: AtomicNotifierChain<BusNotifyEvent, Arc<dyn Device>>,
|
||||
}
|
||||
@ -106,11 +106,11 @@ impl SubSysPrivate {
|
||||
*self.class.lock() = class;
|
||||
}
|
||||
|
||||
pub fn devices(&self) -> RwLockReadGuard<Vec<Weak<dyn Device>>> {
|
||||
pub fn devices(&self) -> RwLockReadGuard<Vec<Arc<dyn Device>>> {
|
||||
return self.devices.read();
|
||||
}
|
||||
|
||||
pub fn drivers(&self) -> RwLockReadGuard<Vec<Weak<dyn Driver>>> {
|
||||
pub fn drivers(&self) -> RwLockReadGuard<Vec<Arc<dyn Driver>>> {
|
||||
return self.drivers.read();
|
||||
}
|
||||
|
||||
@ -155,18 +155,16 @@ impl SubSysPrivate {
|
||||
|
||||
pub fn add_driver_to_vec(&self, driver: &Arc<dyn Driver>) -> Result<(), SystemError> {
|
||||
let mut drivers = self.drivers.write();
|
||||
let driver_weak = Arc::downgrade(driver);
|
||||
if drivers.iter().any(|d| d.ptr_eq(&driver_weak)) {
|
||||
if drivers.iter().any(|d| Arc::ptr_eq(d, driver)) {
|
||||
return Err(SystemError::EEXIST);
|
||||
}
|
||||
drivers.push(driver_weak);
|
||||
drivers.push(driver.clone());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn remove_driver_from_vec(&self, driver: &Arc<dyn Driver>) {
|
||||
let mut drivers = self.drivers.write();
|
||||
let driver_weak = Arc::downgrade(driver);
|
||||
let index = drivers.iter().position(|d| d.ptr_eq(&driver_weak));
|
||||
let index = drivers.iter().position(|d| Arc::ptr_eq(d, driver));
|
||||
if let Some(index) = index {
|
||||
drivers.remove(index);
|
||||
}
|
||||
@ -174,19 +172,17 @@ impl SubSysPrivate {
|
||||
|
||||
pub fn add_device_to_vec(&self, device: &Arc<dyn Device>) -> Result<(), SystemError> {
|
||||
let mut devices = self.devices.write();
|
||||
let device_weak = Arc::downgrade(device);
|
||||
if devices.iter().any(|d| d.ptr_eq(&device_weak)) {
|
||||
if devices.iter().any(|d| Arc::ptr_eq(d, device)) {
|
||||
return Err(SystemError::EEXIST);
|
||||
}
|
||||
devices.push(device_weak);
|
||||
devices.push(device.clone());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn remove_device_from_vec(&self, device: &Arc<dyn Device>) {
|
||||
let mut devices = self.devices.write();
|
||||
let device_weak = Arc::downgrade(device);
|
||||
let index = devices.iter().position(|d| d.ptr_eq(&device_weak));
|
||||
let index = devices.iter().position(|d| Arc::ptr_eq(d, device));
|
||||
if let Some(index) = index {
|
||||
devices.remove(index);
|
||||
}
|
||||
|
@ -499,11 +499,11 @@ impl Device for LockedAhciDisk {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
todo!("LockedAhciDisk::bus()")
|
||||
}
|
||||
|
||||
fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) {
|
||||
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
|
||||
todo!("LockedAhciDisk::set_bus()")
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,10 @@ use crate::{
|
||||
net::{generate_iface_id, NET_DRIVERS},
|
||||
time::Instant,
|
||||
};
|
||||
use alloc::{string::String, sync::Arc};
|
||||
use alloc::{
|
||||
string::String,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use core::{
|
||||
cell::UnsafeCell,
|
||||
fmt::Debug,
|
||||
@ -218,11 +221,11 @@ impl Driver for E1000EInterface {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) {
|
||||
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,10 @@ use core::{
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use alloc::{string::String, sync::Arc};
|
||||
use alloc::{
|
||||
string::String,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use smoltcp::{phy, wire};
|
||||
use virtio_drivers::{device::net::VirtIONet, transport::Transport};
|
||||
|
||||
@ -261,11 +264,11 @@ impl<T: Transport + 'static> Driver for VirtioInterface<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_bus(&self, _bus: Option<Arc<dyn Bus>>) {
|
||||
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use core::{fmt::Debug, sync::atomic::AtomicU32};
|
||||
use alloc::sync::Arc;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{driver::base::device::DeviceNumber, mm::VirtAddr};
|
||||
use crate::{driver::base::device::device_number::DeviceNumber, mm::VirtAddr};
|
||||
|
||||
use self::serial8250::serial8250_manager;
|
||||
|
||||
|
@ -15,8 +15,8 @@ use crate::{
|
||||
base::{
|
||||
class::Class,
|
||||
device::{
|
||||
bus::Bus, device_manager, driver::Driver, Device, DeviceKObjType, DeviceNumber,
|
||||
DeviceState, DeviceType, IdTable,
|
||||
bus::Bus, device_manager, device_number::DeviceNumber, driver::Driver, Device,
|
||||
DeviceKObjType, DeviceState, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
@ -94,6 +94,9 @@ impl Serial8250Manager {
|
||||
// todo: 把端口绑定到isa_dev、 isa_driver上
|
||||
self.register_ports(&serial8250_isa_driver, &serial8250_isa_dev);
|
||||
|
||||
serial8250_isa_dev.set_driver(Some(Arc::downgrade(
|
||||
&(serial8250_isa_driver.clone() as Arc<dyn Driver>),
|
||||
)));
|
||||
// todo: 把驱动注册到uart层、tty层
|
||||
uart_manager().register_driver(&(serial8250_isa_driver.clone() as Arc<dyn UartDriver>))?;
|
||||
|
||||
@ -216,11 +219,11 @@ impl Device for Serial8250ISADevices {
|
||||
fn is_dead(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
self.inner.read().bus.clone()
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>) {
|
||||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
|
||||
self.inner.write().bus = bus;
|
||||
}
|
||||
|
||||
@ -229,7 +232,7 @@ impl Device for Serial8250ISADevices {
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
return IdTable::new(self.name.to_string(), Some(DeviceNumber::new(0)));
|
||||
return IdTable::new(self.name.to_string(), None);
|
||||
}
|
||||
|
||||
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||
@ -291,7 +294,7 @@ impl KObject for Serial8250ISADevices {
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
|
||||
todo!()
|
||||
// 不允许修改
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
@ -319,7 +322,7 @@ struct InnerSerial8250ISADevices {
|
||||
kset: Option<Arc<KSet>>,
|
||||
parent_kobj: Option<Weak<dyn KObject>>,
|
||||
/// 当前设备所述的总线
|
||||
bus: Option<Arc<dyn Bus>>,
|
||||
bus: Option<Weak<dyn Bus>>,
|
||||
inode: Option<Arc<KernFSInode>>,
|
||||
driver: Option<Weak<dyn Driver>>,
|
||||
device_state: DeviceState,
|
||||
@ -351,7 +354,7 @@ enum Serial8250PlatformDeviceID {
|
||||
#[derive(Debug)]
|
||||
|
||||
struct InnerSerial8250ISADriver {
|
||||
bus: Option<Arc<dyn Bus>>,
|
||||
bus: Option<Weak<dyn Bus>>,
|
||||
kobj_type: Option<&'static dyn KObjType>,
|
||||
kset: Option<Arc<KSet>>,
|
||||
parent_kobj: Option<Weak<dyn KObject>>,
|
||||
@ -486,11 +489,11 @@ impl Driver for Serial8250ISADriver {
|
||||
inner.devices.retain(|d| !Arc::ptr_eq(d, device));
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Arc<dyn Bus>> {
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
self.inner.read().bus.clone()
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>) {
|
||||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
|
||||
self.inner.write().bus = bus;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use alloc::{
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
use crate::{
|
||||
filesystem::{
|
||||
@ -13,6 +14,7 @@ use crate::{
|
||||
ROOT_INODE,
|
||||
},
|
||||
},
|
||||
init::initcall::INITCALL_DEVICE,
|
||||
kerror,
|
||||
libs::{
|
||||
lib_ui::textui::{textui_putchar, FontColor},
|
||||
@ -280,6 +282,7 @@ impl TtyDevicePrivateData {
|
||||
}
|
||||
|
||||
/// @brief 初始化TTY设备
|
||||
#[unified_init(INITCALL_DEVICE)]
|
||||
pub fn tty_init() -> Result<(), SystemError> {
|
||||
let tty: Arc<TtyDevice> = TtyDevice::new("tty0");
|
||||
let devfs_root_inode = ROOT_INODE().lookup("/dev");
|
||||
|
@ -85,7 +85,7 @@ struct InnerFbConsoleDevice {
|
||||
kernfs_inode: Option<Arc<KernFSInode>>,
|
||||
parent: Option<Weak<dyn KObject>>,
|
||||
kset: Option<Arc<KSet>>,
|
||||
bus: Option<Arc<dyn Bus>>,
|
||||
bus: Option<Weak<dyn Bus>>,
|
||||
driver: Option<Weak<dyn Driver>>,
|
||||
ktype: Option<&'static dyn KObjType>,
|
||||
}
|
||||
@ -183,10 +183,14 @@ impl Device for FbConsoleDevice {
|
||||
IdTable::new(Self::NAME.to_string(), None)
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Arc<dyn Bus>>) {
|
||||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
|
||||
self.inner.lock().bus = bus;
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
self.inner.lock().bus.clone()
|
||||
}
|
||||
|
||||
fn set_class(&self, _class: Option<Arc<dyn Class>>) {
|
||||
// 不允许修改
|
||||
kwarn!("fbcon's class can not be changed");
|
||||
|
@ -1,23 +1,45 @@
|
||||
use core::intrinsics::unlikely;
|
||||
|
||||
use alloc::{
|
||||
string::ToString,
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
use crate::driver::base::{
|
||||
class::{class_manager, Class},
|
||||
device::sys_dev_char_kset,
|
||||
init::SUBSYSTEM_INITIALIZER_SLICE,
|
||||
kobject::KObject,
|
||||
subsys::SubSysPrivate,
|
||||
use crate::{
|
||||
driver::base::{
|
||||
class::{class_manager, Class},
|
||||
device::{
|
||||
bus::Bus,
|
||||
device_manager,
|
||||
device_number::{DeviceNumber, Major},
|
||||
driver::Driver,
|
||||
sys_dev_char_kset, Device, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
subsys::SubSysPrivate,
|
||||
},
|
||||
filesystem::{kernfs::KernFSInode, sysfs::AttributeGroup},
|
||||
init::initcall::INITCALL_SUBSYS,
|
||||
libs::{
|
||||
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||
spinlock::SpinLock,
|
||||
},
|
||||
};
|
||||
|
||||
use super::fbcon::fb_console_init;
|
||||
use super::{fbcon::fb_console_init, fbsysfs::FbDeviceAttrGroup, FbId, FrameBuffer};
|
||||
|
||||
/// `/sys/class/graphics` 的 class 实例
|
||||
static mut CLASS_GRAPHICS_INSTANCE: Option<Arc<GraphicsClass>> = None;
|
||||
|
||||
lazy_static! {
|
||||
/// 帧缓冲区管理器
|
||||
static ref FRAME_BUFFER_MANAGER: FrameBufferManager = FrameBufferManager::new();
|
||||
}
|
||||
|
||||
/// 获取 `/sys/class/graphics` 的 class 实例
|
||||
#[inline(always)]
|
||||
#[allow(dead_code)]
|
||||
@ -25,8 +47,13 @@ pub fn sys_class_graphics_instance() -> Option<&'static Arc<GraphicsClass>> {
|
||||
unsafe { CLASS_GRAPHICS_INSTANCE.as_ref() }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn frame_buffer_manager() -> &'static FrameBufferManager {
|
||||
&FRAME_BUFFER_MANAGER
|
||||
}
|
||||
|
||||
/// 初始化帧缓冲区子系统
|
||||
#[unified_init(SUBSYSTEM_INITIALIZER_SLICE)]
|
||||
#[unified_init(INITCALL_SUBSYS)]
|
||||
pub fn fbmem_init() -> Result<(), SystemError> {
|
||||
let graphics_class = GraphicsClass::new();
|
||||
class_manager().class_register(&(graphics_class.clone() as Arc<dyn Class>))?;
|
||||
@ -76,3 +103,236 @@ impl Class for GraphicsClass {
|
||||
return &self.subsystem;
|
||||
}
|
||||
}
|
||||
|
||||
/// 帧缓冲区管理器
|
||||
#[derive(Debug)]
|
||||
pub struct FrameBufferManager {
|
||||
inner: RwLock<InnerFrameBufferManager>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InnerFrameBufferManager {
|
||||
/// 已经注册的帧缓冲区
|
||||
registered_fbs: [Option<Arc<dyn FrameBuffer>>; FrameBufferManager::FB_MAX],
|
||||
}
|
||||
|
||||
impl FrameBufferManager {
|
||||
pub const FB_MAX: usize = 32;
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: RwLock::new(InnerFrameBufferManager {
|
||||
registered_fbs: Default::default(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// 注册一个帧缓冲区
|
||||
///
|
||||
/// # 参数
|
||||
///
|
||||
/// - fb: 帧缓冲区
|
||||
pub fn register_fb(&self, fb: Arc<dyn FrameBuffer>) -> Result<FbId, SystemError> {
|
||||
let id = self.generate_fb_id().expect("no more fb id");
|
||||
fb.set_fb_id(id);
|
||||
let fb_device = FbDevice::new(Arc::downgrade(&fb) as Weak<dyn FrameBuffer>, id);
|
||||
device_manager().device_default_initialize(&(fb_device.clone() as Arc<dyn Device>));
|
||||
fb_device.set_parent(Some(Arc::downgrade(&(fb.clone() as Arc<dyn KObject>))));
|
||||
|
||||
fb.set_fb_device(Some(fb_device.clone()));
|
||||
|
||||
device_manager().add_device(fb_device.clone() as Arc<dyn Device>)?;
|
||||
|
||||
// todo: 从Modedb中获取信息
|
||||
// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbmem.c#1584
|
||||
|
||||
let mut inner = self.inner.write();
|
||||
inner.registered_fbs[id.data() as usize] = Some(fb.clone() as Arc<dyn FrameBuffer>);
|
||||
|
||||
// todo: 把fb跟fbcon关联起来
|
||||
return Ok(id);
|
||||
}
|
||||
|
||||
/// 注销一个帧缓冲区
|
||||
///
|
||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbmem.c#1726
|
||||
#[allow(dead_code)]
|
||||
pub fn unregister_fb(&self, _fb: Arc<dyn FrameBuffer>) -> Result<(), SystemError> {
|
||||
todo!("unregister_fb")
|
||||
}
|
||||
|
||||
/// 根据id查找帧缓冲区
|
||||
pub fn find_fb_by_id(&self, id: FbId) -> Result<Option<Arc<dyn FrameBuffer>>, SystemError> {
|
||||
if unlikely(!id.is_valid()) {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let inner = self.inner.read();
|
||||
return Ok(inner.registered_fbs[id.data() as usize].clone());
|
||||
}
|
||||
|
||||
fn generate_fb_id(&self) -> Option<FbId> {
|
||||
for i in 0..Self::FB_MAX {
|
||||
if self.inner.read().registered_fbs[i].is_none() {
|
||||
return Some(FbId::new(i as u32));
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
/// 抽象的帧缓冲区设备
|
||||
///
|
||||
/// 对应于`/sys/class/graphics/fb(x)`目录下的设备, 其中`(x)`为帧缓冲区的id
|
||||
///
|
||||
/// 该设备的父设备为真实的帧缓冲区设备
|
||||
#[derive(Debug)]
|
||||
#[cast_to([sync] Device)]
|
||||
pub struct FbDevice {
|
||||
inner: SpinLock<InnerFbDevice>,
|
||||
kobj_state: LockedKObjectState,
|
||||
}
|
||||
|
||||
impl FbDevice {
|
||||
pub const BASENAME: &'static str = "fb";
|
||||
fn new(fb: Weak<dyn FrameBuffer>, id: FbId) -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
inner: SpinLock::new(InnerFbDevice {
|
||||
fb,
|
||||
kern_inode: None,
|
||||
parent: None,
|
||||
kset: None,
|
||||
ktype: None,
|
||||
fb_id: id,
|
||||
}),
|
||||
kobj_state: LockedKObjectState::new(None),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn framebuffer(&self) -> Option<Arc<dyn FrameBuffer>> {
|
||||
self.inner.lock().fb.upgrade()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InnerFbDevice {
|
||||
fb: Weak<dyn FrameBuffer>,
|
||||
kern_inode: Option<Arc<KernFSInode>>,
|
||||
parent: Option<Weak<dyn KObject>>,
|
||||
kset: Option<Arc<KSet>>,
|
||||
ktype: Option<&'static dyn KObjType>,
|
||||
/// 帧缓冲区id
|
||||
fb_id: FbId,
|
||||
}
|
||||
|
||||
impl KObject for FbDevice {
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
|
||||
self.inner.lock().kern_inode = inode;
|
||||
}
|
||||
|
||||
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||
self.inner.lock().kern_inode.clone()
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||
self.inner.lock().parent.clone()
|
||||
}
|
||||
|
||||
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
|
||||
self.inner.lock().parent = parent;
|
||||
}
|
||||
|
||||
fn kset(&self) -> Option<Arc<KSet>> {
|
||||
self.inner.lock().kset.clone()
|
||||
}
|
||||
|
||||
fn set_kset(&self, kset: Option<Arc<KSet>>) {
|
||||
self.inner.lock().kset = kset;
|
||||
}
|
||||
|
||||
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||
self.inner.lock().ktype
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
|
||||
self.inner.lock().ktype = ktype;
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
format!("{}{}", Self::BASENAME, self.inner.lock().fb_id.data())
|
||||
}
|
||||
|
||||
fn set_name(&self, _name: String) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||
self.kobj_state.read()
|
||||
}
|
||||
|
||||
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||
self.kobj_state.write()
|
||||
}
|
||||
|
||||
fn set_kobj_state(&self, state: KObjectState) {
|
||||
*self.kobj_state.write() = state;
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for FbDevice {
|
||||
fn dev_type(&self) -> DeviceType {
|
||||
DeviceType::Char
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
IdTable::new(
|
||||
Self::BASENAME.to_string(),
|
||||
Some(DeviceNumber::new(
|
||||
Major::FB_MAJOR,
|
||||
self.inner.lock().fb_id.data(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn class(&self) -> Option<Arc<dyn Class>> {
|
||||
sys_class_graphics_instance().map(|ins| ins.clone() as Arc<dyn Class>)
|
||||
}
|
||||
fn set_class(&self, _class: Option<Arc<dyn Class>>) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn set_driver(&self, _driver: Option<Weak<dyn Driver>>) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fn is_dead(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn can_match(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn set_can_match(&self, _can_match: bool) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fn state_synced(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
|
||||
Some(&[&FbDeviceAttrGroup])
|
||||
}
|
||||
}
|
||||
|
320
kernel/src/driver/video/fbdev/base/fbsysfs.rs
Normal file
320
kernel/src/driver/video/fbdev/base/fbsysfs.rs
Normal file
@ -0,0 +1,320 @@
|
||||
use alloc::sync::Arc;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::base::kobject::KObject,
|
||||
filesystem::{
|
||||
sysfs::{file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport},
|
||||
vfs::syscall::ModeType,
|
||||
},
|
||||
};
|
||||
|
||||
use super::fbmem::FbDevice;
|
||||
|
||||
/// 为FbDevice实现的sysfs属性组
|
||||
#[derive(Debug)]
|
||||
pub struct FbDeviceAttrGroup;
|
||||
|
||||
impl AttributeGroup for FbDeviceAttrGroup {
|
||||
fn name(&self) -> Option<&str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn attrs(&self) -> &[&'static dyn Attribute] {
|
||||
&[
|
||||
&AttrBitsPerPixel,
|
||||
&AttrBlank,
|
||||
&AttrMode,
|
||||
&AttrModes,
|
||||
&AttrName,
|
||||
&AttrPan,
|
||||
&AttrRotate,
|
||||
&AttrState,
|
||||
&AttrStride,
|
||||
&AttrVirtualSize,
|
||||
]
|
||||
}
|
||||
|
||||
fn is_visible(
|
||||
&self,
|
||||
_kobj: alloc::sync::Arc<dyn KObject>,
|
||||
_attr: &'static dyn Attribute,
|
||||
) -> Option<ModeType> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrName;
|
||||
|
||||
impl Attribute for AttrName {
|
||||
fn name(&self) -> &str {
|
||||
"name"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IRUGO
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let fb_dev = kobj.arc_any().downcast::<FbDevice>().unwrap();
|
||||
let fb = fb_dev.framebuffer().ok_or(SystemError::ENODEV)?;
|
||||
let name = fb.name();
|
||||
return sysfs_emit_str(buf, &format!("{}\n", name));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrBitsPerPixel;
|
||||
|
||||
impl Attribute for AttrBitsPerPixel {
|
||||
fn name(&self) -> &str {
|
||||
"bits_per_pixel"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IRUGO | ModeType::S_IWUSR
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
|
||||
}
|
||||
|
||||
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
||||
kwarn!("attr bits_per_pixel store not implemented");
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let fb_dev = kobj.arc_any().downcast::<FbDevice>().unwrap();
|
||||
let fb = fb_dev.framebuffer().ok_or(SystemError::ENODEV)?;
|
||||
let bits_per_pixel = fb.current_fb_var().bits_per_pixel;
|
||||
return sysfs_emit_str(buf, &format!("{}\n", bits_per_pixel));
|
||||
}
|
||||
}
|
||||
|
||||
/// 用于清空屏幕的属性
|
||||
#[derive(Debug)]
|
||||
struct AttrBlank;
|
||||
|
||||
impl Attribute for AttrBlank {
|
||||
fn name(&self) -> &str {
|
||||
"blank"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IWUSR
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::STORE
|
||||
}
|
||||
|
||||
// todo: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#309
|
||||
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
||||
kwarn!("attr blank store not implemented");
|
||||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrMode;
|
||||
|
||||
impl Attribute for AttrMode {
|
||||
fn name(&self) -> &str {
|
||||
"mode"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IRUGO | ModeType::S_IWUSR
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
|
||||
}
|
||||
|
||||
/// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#166
|
||||
fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
todo!("AttrMode::show")
|
||||
}
|
||||
|
||||
/// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#135
|
||||
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
||||
todo!("AttrMode::store")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrModes;
|
||||
|
||||
impl Attribute for AttrModes {
|
||||
fn name(&self) -> &str {
|
||||
"modes"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IRUGO | ModeType::S_IWUSR
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
|
||||
}
|
||||
|
||||
/// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#206
|
||||
fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
todo!("AttrMode::show")
|
||||
}
|
||||
|
||||
/// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#177
|
||||
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
||||
todo!("AttrMode::store")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrPan;
|
||||
|
||||
impl Attribute for AttrPan {
|
||||
fn name(&self) -> &str {
|
||||
"pan"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IRUGO | ModeType::S_IWUSR
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let fb_dev = kobj.arc_any().downcast::<FbDevice>().unwrap();
|
||||
let fb = fb_dev.framebuffer().ok_or(SystemError::ENODEV)?;
|
||||
let var_info = fb.current_fb_var();
|
||||
return sysfs_emit_str(buf, &format!("{},{}\n", var_info.xoffset, var_info.yoffset));
|
||||
}
|
||||
|
||||
/// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#365
|
||||
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
||||
todo!("AttrPan::store")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrVirtualSize;
|
||||
|
||||
impl Attribute for AttrVirtualSize {
|
||||
fn name(&self) -> &str {
|
||||
"virtual_size"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IRUGO | ModeType::S_IWUSR
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let fb_dev = kobj.arc_any().downcast::<FbDevice>().unwrap();
|
||||
let fb = fb_dev.framebuffer().ok_or(SystemError::ENODEV)?;
|
||||
let var_info = fb.current_fb_var();
|
||||
return sysfs_emit_str(
|
||||
buf,
|
||||
&format!("{},{}\n", var_info.xres_virtual, var_info.yres_virtual),
|
||||
);
|
||||
}
|
||||
|
||||
/// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#273
|
||||
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
||||
todo!("AttrVirtualSize::store")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrStride;
|
||||
|
||||
impl Attribute for AttrStride {
|
||||
fn name(&self) -> &str {
|
||||
"stride"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IRUGO
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let fb_dev = kobj.arc_any().downcast::<FbDevice>().unwrap();
|
||||
let fb = fb_dev.framebuffer().ok_or(SystemError::ENODEV)?;
|
||||
let fix_info = fb.current_fb_fix();
|
||||
return sysfs_emit_str(buf, &format!("{}\n", fix_info.line_length));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrRotate;
|
||||
|
||||
impl Attribute for AttrRotate {
|
||||
fn name(&self) -> &str {
|
||||
"rotate"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IRUGO | ModeType::S_IWUSR
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let fb_dev = kobj.arc_any().downcast::<FbDevice>().unwrap();
|
||||
let fb = fb_dev.framebuffer().ok_or(SystemError::ENODEV)?;
|
||||
let var_info = fb.current_fb_var();
|
||||
|
||||
return sysfs_emit_str(buf, &format!("{}\n", var_info.rotate_angle));
|
||||
}
|
||||
|
||||
/// todo https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#246
|
||||
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
||||
todo!("AttrRotate::store")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AttrState;
|
||||
|
||||
impl Attribute for AttrState {
|
||||
fn name(&self) -> &str {
|
||||
"state"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IRUGO | ModeType::S_IWUSR
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let fb_dev = kobj.arc_any().downcast::<FbDevice>().unwrap();
|
||||
let fb = fb_dev.framebuffer().ok_or(SystemError::ENODEV)?;
|
||||
|
||||
return sysfs_emit_str(buf, &format!("{}\n", fb.state() as u8));
|
||||
}
|
||||
|
||||
/// todo https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#406
|
||||
fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
|
||||
todo!("AttrState::store")
|
||||
}
|
||||
}
|
@ -3,14 +3,41 @@ use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::base::device::Device,
|
||||
mm::{ucontext::LockedVMA, PhysAddr},
|
||||
mm::{ucontext::LockedVMA, PhysAddr, VirtAddr},
|
||||
};
|
||||
|
||||
use self::fbmem::{FbDevice, FrameBufferManager};
|
||||
|
||||
pub mod fbcon;
|
||||
pub mod fbmem;
|
||||
pub mod fbsysfs;
|
||||
pub mod modedb;
|
||||
|
||||
// 帧缓冲区id
|
||||
int_like!(FbId, u32);
|
||||
|
||||
impl FbId {
|
||||
/// 帧缓冲区id的初始值(无效值)
|
||||
pub const INIT: Self = Self::new(u32::MAX);
|
||||
|
||||
/// 判断是否为无效的帧缓冲区id
|
||||
#[allow(dead_code)]
|
||||
pub const fn is_valid(&self) -> bool {
|
||||
if self.0 == Self::INIT.0 || self.0 >= FrameBufferManager::FB_MAX as u32 {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// 帧缓冲区应该实现的接口
|
||||
pub trait FrameBuffer: FrameBufferInfo + FrameBufferOps + Device {}
|
||||
pub trait FrameBuffer: FrameBufferInfo + FrameBufferOps + Device {
|
||||
/// 获取帧缓冲区的id
|
||||
fn fb_id(&self) -> FbId;
|
||||
|
||||
/// 设置帧缓冲区的id
|
||||
fn set_fb_id(&self, id: FbId);
|
||||
}
|
||||
|
||||
/// 帧缓冲区信息
|
||||
pub trait FrameBufferInfo {
|
||||
@ -18,19 +45,22 @@ pub trait FrameBufferInfo {
|
||||
fn screen_size(&self) -> usize;
|
||||
|
||||
/// 获取当前的可变帧缓冲信息
|
||||
fn current_fb_var(&self) -> &FbVarScreenInfo;
|
||||
|
||||
/// 获取当前的可变帧缓冲信息(可变引用)
|
||||
fn current_fb_var_mut(&mut self) -> &mut FbVarScreenInfo;
|
||||
fn current_fb_var(&self) -> FbVarScreenInfo;
|
||||
|
||||
/// 获取当前的固定帧缓冲信息
|
||||
fn current_fb_fix(&self) -> &FixedScreenInfo;
|
||||
|
||||
/// 获取当前的固定帧缓冲信息(可变引用)
|
||||
fn current_fb_fix_mut(&mut self) -> &mut FixedScreenInfo;
|
||||
fn current_fb_fix(&self) -> FixedScreenInfo;
|
||||
|
||||
/// 获取当前的视频模式
|
||||
fn video_mode(&self) -> Option<&FbVideoMode>;
|
||||
|
||||
/// 获取当前帧缓冲区对应的`/sys/class/graphics/fb0`或者`/sys/class/graphics/fb1`等的设备结构体
|
||||
fn fb_device(&self) -> Option<Arc<FbDevice>>;
|
||||
|
||||
/// 设置当前帧缓冲区对应的`/sys/class/graphics/fb0`或者`/sys/class/graphics/fb1`等的设备结构体
|
||||
fn set_fb_device(&self, device: Option<Arc<FbDevice>>);
|
||||
|
||||
/// 获取帧缓冲区的状态
|
||||
fn state(&self) -> FbState;
|
||||
}
|
||||
|
||||
/// 帧缓冲区操作
|
||||
@ -94,6 +124,13 @@ pub trait FrameBufferOps {
|
||||
fn fb_destroy(&self);
|
||||
}
|
||||
|
||||
/// 帧缓冲区的状态
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum FbState {
|
||||
Running = 0,
|
||||
Suspended = 1,
|
||||
}
|
||||
|
||||
/// 屏幕黑屏模式。
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
@ -221,10 +258,10 @@ pub struct FbVarScreenInfo {
|
||||
pub pixel_format: FbPixelFormat,
|
||||
/// 激活标志(参见FB_ACTIVATE_*)
|
||||
pub activate: FbActivateFlags,
|
||||
/// 帧缓冲区的高度(像素)
|
||||
pub height: u32,
|
||||
/// 帧缓冲区的宽度(像素)
|
||||
pub width: u32,
|
||||
/// 帧缓冲区的高度(像素) None表示未知
|
||||
pub height: Option<u32>,
|
||||
/// 帧缓冲区的宽度(像素) None表示未知
|
||||
pub width: Option<u32>,
|
||||
/// 像素时钟(皮秒)
|
||||
pub pixclock: u32,
|
||||
/// 左边距
|
||||
@ -249,6 +286,43 @@ pub struct FbVarScreenInfo {
|
||||
pub colorspace: V4l2Colorspace,
|
||||
}
|
||||
|
||||
impl Default for FbVarScreenInfo {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
xres: Default::default(),
|
||||
yres: Default::default(),
|
||||
xres_virtual: Default::default(),
|
||||
yres_virtual: Default::default(),
|
||||
xoffset: Default::default(),
|
||||
yoffset: Default::default(),
|
||||
bits_per_pixel: Default::default(),
|
||||
color_mode: Default::default(),
|
||||
red: Default::default(),
|
||||
green: Default::default(),
|
||||
blue: Default::default(),
|
||||
transp: Default::default(),
|
||||
pixel_format: Default::default(),
|
||||
activate: Default::default(),
|
||||
height: None,
|
||||
width: None,
|
||||
pixclock: Default::default(),
|
||||
left_margin: Default::default(),
|
||||
right_margin: Default::default(),
|
||||
upper_margin: Default::default(),
|
||||
lower_margin: Default::default(),
|
||||
hsync_len: Default::default(),
|
||||
vsync_len: Default::default(),
|
||||
sync: FbSyncFlags::empty(),
|
||||
vmode: FbVModeFlags::empty(),
|
||||
rotate_angle: Default::default(),
|
||||
colorspace: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 帧缓冲区的颜色模式
|
||||
///
|
||||
/// 默认为彩色
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum FbColorMode {
|
||||
@ -260,6 +334,12 @@ pub enum FbColorMode {
|
||||
FourCC,
|
||||
}
|
||||
|
||||
impl Default for FbColorMode {
|
||||
fn default() -> Self {
|
||||
FbColorMode::Color
|
||||
}
|
||||
}
|
||||
|
||||
/// `FbBitfield` 结构体用于描述颜色字段的位域。
|
||||
///
|
||||
/// 所有的偏移量都是从右边开始,位于一个精确为'bits_per_pixel'宽度的"像素"值内。
|
||||
@ -289,6 +369,16 @@ impl FbBitfield {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FbBitfield {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
offset: Default::default(),
|
||||
length: Default::default(),
|
||||
msb_right: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `FbActivateFlags` 用于描述帧缓冲区的激活标志。
|
||||
///
|
||||
@ -317,6 +407,12 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FbActivateFlags {
|
||||
fn default() -> Self {
|
||||
FbActivateFlags::FB_ACTIVATE_NOW
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum FbPixelFormat {
|
||||
@ -327,6 +423,12 @@ pub enum FbPixelFormat {
|
||||
Reserved,
|
||||
}
|
||||
|
||||
impl Default for FbPixelFormat {
|
||||
fn default() -> Self {
|
||||
FbPixelFormat::Standard
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct FbSyncFlags: u32 {
|
||||
/// 水平同步高电平有效
|
||||
@ -415,9 +517,9 @@ pub struct FixedScreenInfo {
|
||||
// 字符串,用于标识屏幕,例如 "TT Builtin"
|
||||
pub id: [char; 16],
|
||||
// 帧缓冲区的起始物理地址
|
||||
pub smem_start: PhysAddr,
|
||||
pub smem_start: Option<PhysAddr>,
|
||||
// 帧缓冲区的长度
|
||||
pub smem_len: u32,
|
||||
pub smem_len: usize,
|
||||
// 屏幕类型,参考 FB_TYPE_
|
||||
pub fb_type: FbType,
|
||||
// 用于表示交错平面的小端辅助类型
|
||||
@ -432,16 +534,61 @@ pub struct FixedScreenInfo {
|
||||
pub ywrapstep: u16,
|
||||
// 一行的大小(以字节为单位)
|
||||
pub line_length: u32,
|
||||
// 内存映射I/O的起始物理地址
|
||||
pub mmio_start: PhysAddr,
|
||||
// 内存映射I/O端口的起始物理地址
|
||||
pub mmio_start: Option<PhysAddr>,
|
||||
// 内存映射I/O的长度
|
||||
pub mmio_len: u32,
|
||||
pub mmio_len: usize,
|
||||
// 表示驱动器拥有的特定芯片/卡片类型
|
||||
pub accel: u32,
|
||||
pub accel: FbAccel,
|
||||
// 表示支持的特性,参考 FB_CAP_
|
||||
pub capabilities: FbCapability,
|
||||
}
|
||||
|
||||
impl FixedScreenInfo {
|
||||
/// 将字符串转换为长度为16的字符数组(包含结尾的`\0`)
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `name`: 字符串,长度不超过15,超过的部分将被截断
|
||||
///
|
||||
/// ## 返回
|
||||
///
|
||||
/// 长度为16的字符数组
|
||||
pub const fn name2id(name: &str) -> [char; 16] {
|
||||
let mut id = [0 as char; 16];
|
||||
let mut i = 0;
|
||||
|
||||
while i < 15 && i < name.len() {
|
||||
id[i] = name.as_bytes()[i] as char;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
id[i] = '\0';
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FixedScreenInfo {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: Default::default(),
|
||||
smem_start: None,
|
||||
smem_len: Default::default(),
|
||||
fb_type: FbType::PackedPixels,
|
||||
type_aux: Default::default(),
|
||||
visual: FbVisual::Mono10,
|
||||
xpanstep: Default::default(),
|
||||
ypanstep: Default::default(),
|
||||
ywrapstep: Default::default(),
|
||||
line_length: Default::default(),
|
||||
mmio_start: None,
|
||||
mmio_len: Default::default(),
|
||||
accel: Default::default(),
|
||||
capabilities: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 帧缓冲类型
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
@ -488,6 +635,12 @@ pub enum FbCapability {
|
||||
FourCC,
|
||||
}
|
||||
|
||||
impl Default for FbCapability {
|
||||
fn default() -> Self {
|
||||
FbCapability::Default
|
||||
}
|
||||
}
|
||||
|
||||
/// 视频模式
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
@ -521,3 +674,179 @@ pub struct FbVideoMode {
|
||||
/// 标志
|
||||
pub flag: u32,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum FbAccel {
|
||||
/// 没有硬件加速器
|
||||
None,
|
||||
|
||||
AtariBlitter = 1,
|
||||
AmigaBlitter = 2,
|
||||
S3Trio64 = 3,
|
||||
NCR77C32BLT = 4,
|
||||
S3Virge = 5,
|
||||
AtiMach64GX = 6,
|
||||
DECTGA = 7,
|
||||
AtiMach64CT = 8,
|
||||
AtiMach64VT = 9,
|
||||
AtiMach64GT = 10,
|
||||
SunCreator = 11,
|
||||
SunCGSix = 12,
|
||||
SunLeo = 13,
|
||||
IMSTwinTurbo = 14,
|
||||
Acc3DLabsPermedia2 = 15,
|
||||
MatroxMGA2064W = 16,
|
||||
MatroxMGA1064SG = 17,
|
||||
MatroxMGA2164W = 18,
|
||||
MatroxMGA2164WAGP = 19,
|
||||
MatroxMGAG400 = 20,
|
||||
NV3 = 21,
|
||||
NV4 = 22,
|
||||
NV5 = 23,
|
||||
NV6 = 24,
|
||||
XGIVolariV = 25,
|
||||
XGIVolariZ = 26,
|
||||
Omap1610 = 27,
|
||||
TridentTGUI = 28,
|
||||
Trident3DImage = 29,
|
||||
TridentBlade3D = 30,
|
||||
TridentBladeXP = 31,
|
||||
CirrusAlpine = 32,
|
||||
NeoMagicNM2070 = 90,
|
||||
NeoMagicNM2090 = 91,
|
||||
NeoMagicNM2093 = 92,
|
||||
NeoMagicNM2097 = 93,
|
||||
NeoMagicNM2160 = 94,
|
||||
NeoMagicNM2200 = 95,
|
||||
NeoMagicNM2230 = 96,
|
||||
NeoMagicNM2360 = 97,
|
||||
NeoMagicNM2380 = 98,
|
||||
PXA3XX = 99,
|
||||
|
||||
Savage4 = 0x80,
|
||||
Savage3D = 0x81,
|
||||
Savage3DMV = 0x82,
|
||||
Savage2000 = 0x83,
|
||||
SavageMXMV = 0x84,
|
||||
SavageMX = 0x85,
|
||||
SavageIXMV = 0x86,
|
||||
SavageIX = 0x87,
|
||||
ProSavagePM = 0x88,
|
||||
ProSavageKM = 0x89,
|
||||
S3Twister = 0x8a,
|
||||
S3TwisterK = 0x8b,
|
||||
SuperSavage = 0x8c,
|
||||
ProSavageDDR = 0x8d,
|
||||
ProSavageDDRK = 0x8e,
|
||||
// Add other accelerators here
|
||||
}
|
||||
|
||||
impl Default for FbAccel {
|
||||
fn default() -> Self {
|
||||
FbAccel::None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct BootTimeScreenInfo {
|
||||
pub origin_x: u8,
|
||||
pub origin_y: u8,
|
||||
/// text mode时,每行的字符数
|
||||
pub origin_video_cols: u8,
|
||||
/// text mode时,行数
|
||||
pub origin_video_lines: u8,
|
||||
/// 标记屏幕是否为VGA类型
|
||||
pub is_vga: bool,
|
||||
/// video mode type
|
||||
pub video_type: BootTimeVideoType,
|
||||
|
||||
// 以下字段用于线性帧缓冲区
|
||||
/// 线性帧缓冲区的起始物理地址
|
||||
pub lfb_base: PhysAddr,
|
||||
/// 线性帧缓冲区在初始化阶段被映射到的起始虚拟地址
|
||||
///
|
||||
/// 这个值可能会被设置2次:
|
||||
///
|
||||
/// - 内存管理初始化之前,early init阶段,临时映射
|
||||
/// - 内存管理初始化完毕,重新映射时被设置
|
||||
pub lfb_virt_base: Option<VirtAddr>,
|
||||
/// 线性帧缓冲区的长度
|
||||
pub lfb_size: usize,
|
||||
/// 线性帧缓冲区的宽度(像素)
|
||||
pub lfb_width: u32,
|
||||
/// 线性帧缓冲区的高度(像素)
|
||||
pub lfb_height: u32,
|
||||
/// 线性帧缓冲区的深度(位数)
|
||||
pub lfb_depth: u8,
|
||||
/// 红色位域的大小
|
||||
pub red_size: u8,
|
||||
/// 红色位域的偏移量(左移位数)
|
||||
pub red_pos: u8,
|
||||
/// 绿色位域的大小
|
||||
pub green_size: u8,
|
||||
/// 绿色位域的偏移量(左移位数)
|
||||
pub green_pos: u8,
|
||||
/// 蓝色位域的大小
|
||||
pub blue_size: u8,
|
||||
/// 蓝色位域的偏移量(左移位数)
|
||||
pub blue_pos: u8,
|
||||
}
|
||||
|
||||
impl BootTimeScreenInfo {
|
||||
pub const DEFAULT: Self = Self {
|
||||
origin_x: 0,
|
||||
origin_y: 0,
|
||||
is_vga: false,
|
||||
lfb_base: PhysAddr::new(0),
|
||||
lfb_size: 0,
|
||||
lfb_width: 0,
|
||||
lfb_height: 0,
|
||||
red_size: 0,
|
||||
red_pos: 0,
|
||||
green_size: 0,
|
||||
green_pos: 0,
|
||||
blue_size: 0,
|
||||
blue_pos: 0,
|
||||
video_type: BootTimeVideoType::UnDefined,
|
||||
origin_video_cols: 0,
|
||||
origin_video_lines: 0,
|
||||
lfb_virt_base: None,
|
||||
lfb_depth: 0,
|
||||
};
|
||||
}
|
||||
|
||||
/// Video types for different display hardware
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum BootTimeVideoType {
|
||||
UnDefined,
|
||||
/// Monochrome Text Display
|
||||
Mda,
|
||||
/// CGA Display
|
||||
Cga,
|
||||
/// EGA/VGA in Monochrome Mode
|
||||
EgaM,
|
||||
/// EGA in Color Mode
|
||||
EgaC,
|
||||
/// VGA+ in Color Mode
|
||||
VgaC,
|
||||
/// VESA VGA in graphic mode
|
||||
Vlfb,
|
||||
/// ACER PICA-61 local S3 video
|
||||
PicaS3,
|
||||
/// MIPS Magnum 4000 G364 video
|
||||
MipsG364,
|
||||
/// Various SGI graphics hardware
|
||||
Sgi,
|
||||
/// DEC TGA
|
||||
TgaC,
|
||||
/// Sun frame buffer
|
||||
Sun,
|
||||
/// Sun PCI based frame buffer
|
||||
SunPci,
|
||||
/// PowerMacintosh frame buffer
|
||||
Pmac,
|
||||
/// EFI graphic mode
|
||||
Efi,
|
||||
}
|
||||
|
3
kernel/src/driver/video/fbdev/base/modedb.rs
Normal file
3
kernel/src/driver/video/fbdev/base/modedb.rs
Normal file
@ -0,0 +1,3 @@
|
||||
//! todo: 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/modedb.c
|
||||
//!
|
||||
//! 实现modedb
|
@ -1 +1,2 @@
|
||||
pub mod base;
|
||||
pub mod vesafb;
|
||||
|
680
kernel/src/driver/video/fbdev/vesafb.rs
Normal file
680
kernel/src/driver/video/fbdev/vesafb.rs
Normal file
@ -0,0 +1,680 @@
|
||||
use core::{
|
||||
ffi::{c_uint, c_void},
|
||||
mem::MaybeUninit,
|
||||
sync::atomic::AtomicBool,
|
||||
};
|
||||
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
use crate::{
|
||||
arch::MMArch,
|
||||
driver::{
|
||||
base::{
|
||||
class::Class,
|
||||
device::{
|
||||
bus::Bus, device_manager, driver::Driver, Device, DeviceState, DeviceType, IdTable,
|
||||
},
|
||||
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
|
||||
kset::KSet,
|
||||
platform::{
|
||||
platform_device::{platform_device_manager, PlatformDevice},
|
||||
platform_driver::{platform_driver_manager, PlatformDriver},
|
||||
CompatibleTable,
|
||||
},
|
||||
},
|
||||
tty::serial::serial8250::send_to_default_serial8250_port,
|
||||
video::fbdev::base::{fbmem::frame_buffer_manager, FbVisual},
|
||||
},
|
||||
filesystem::{
|
||||
kernfs::KernFSInode,
|
||||
sysfs::{file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport},
|
||||
vfs::syscall::ModeType,
|
||||
},
|
||||
include::bindings::bindings::{
|
||||
multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t,
|
||||
},
|
||||
init::{boot_params, initcall::INITCALL_DEVICE},
|
||||
libs::{
|
||||
align::page_align_up,
|
||||
once::Once,
|
||||
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||
spinlock::SpinLock,
|
||||
},
|
||||
mm::{
|
||||
allocator::page_frame::PageFrameCount, no_init::pseudo_map_phys, MemoryManagementArch,
|
||||
PhysAddr, VirtAddr,
|
||||
},
|
||||
};
|
||||
|
||||
use super::base::{
|
||||
fbmem::FbDevice, BlankMode, BootTimeVideoType, FbAccel, FbActivateFlags, FbId, FbState, FbType,
|
||||
FbVModeFlags, FbVarScreenInfo, FbVideoMode, FixedScreenInfo, FrameBuffer, FrameBufferInfo,
|
||||
FrameBufferOps,
|
||||
};
|
||||
|
||||
/// 当前机器上面是否有vesa帧缓冲区
|
||||
static HAS_VESA_FB: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
lazy_static! {
|
||||
static ref VESAFB_FIX_INFO: RwLock<FixedScreenInfo> = RwLock::new(FixedScreenInfo {
|
||||
id: FixedScreenInfo::name2id("VESA VGA"),
|
||||
fb_type: FbType::PackedPixels,
|
||||
accel: FbAccel::None,
|
||||
..Default::default()
|
||||
});
|
||||
static ref VESAFB_DEFINED: RwLock<FbVarScreenInfo> = RwLock::new(FbVarScreenInfo {
|
||||
activate: FbActivateFlags::FB_ACTIVATE_NOW,
|
||||
height: None,
|
||||
width: None,
|
||||
right_margin: 32,
|
||||
upper_margin: 16,
|
||||
lower_margin: 4,
|
||||
vsync_len: 4,
|
||||
vmode: FbVModeFlags::FB_VMODE_NONINTERLACED,
|
||||
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cast_to([sync] Device)]
|
||||
#[cast_to([sync] PlatformDevice)]
|
||||
pub struct VesaFb {
|
||||
inner: SpinLock<InnerVesaFb>,
|
||||
kobj_state: LockedKObjectState,
|
||||
}
|
||||
|
||||
impl VesaFb {
|
||||
pub const NAME: &'static str = "vesa_vga";
|
||||
pub fn new() -> Self {
|
||||
return Self {
|
||||
inner: SpinLock::new(InnerVesaFb {
|
||||
bus: None,
|
||||
class: None,
|
||||
driver: None,
|
||||
kern_inode: None,
|
||||
parent: None,
|
||||
kset: None,
|
||||
kobj_type: None,
|
||||
device_state: DeviceState::NotInitialized,
|
||||
pdev_id: 0,
|
||||
pdev_id_auto: false,
|
||||
fb_id: FbId::INIT,
|
||||
fb_device: None,
|
||||
fb_state: FbState::Suspended,
|
||||
}),
|
||||
kobj_state: LockedKObjectState::new(None),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InnerVesaFb {
|
||||
bus: Option<Weak<dyn Bus>>,
|
||||
class: Option<Arc<dyn Class>>,
|
||||
driver: Option<Weak<dyn Driver>>,
|
||||
kern_inode: Option<Arc<KernFSInode>>,
|
||||
parent: Option<Weak<dyn KObject>>,
|
||||
kset: Option<Arc<KSet>>,
|
||||
kobj_type: Option<&'static dyn KObjType>,
|
||||
device_state: DeviceState,
|
||||
pdev_id: i32,
|
||||
pdev_id_auto: bool,
|
||||
fb_id: FbId,
|
||||
fb_device: Option<Arc<FbDevice>>,
|
||||
fb_state: FbState,
|
||||
}
|
||||
|
||||
impl FrameBuffer for VesaFb {
|
||||
fn fb_id(&self) -> FbId {
|
||||
self.inner.lock().fb_id
|
||||
}
|
||||
|
||||
fn set_fb_id(&self, id: FbId) {
|
||||
self.inner.lock().fb_id = id;
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformDevice for VesaFb {
|
||||
fn pdev_name(&self) -> &str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn set_pdev_id(&self, id: i32) {
|
||||
self.inner.lock().pdev_id = id;
|
||||
}
|
||||
|
||||
fn set_pdev_id_auto(&self, id_auto: bool) {
|
||||
self.inner.lock().pdev_id_auto = id_auto;
|
||||
}
|
||||
|
||||
fn compatible_table(&self) -> CompatibleTable {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn is_initialized(&self) -> bool {
|
||||
self.inner.lock().device_state == DeviceState::Initialized
|
||||
}
|
||||
|
||||
fn set_state(&self, set_state: DeviceState) {
|
||||
self.inner.lock().device_state = set_state;
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for VesaFb {
|
||||
fn dev_type(&self) -> DeviceType {
|
||||
DeviceType::Char
|
||||
}
|
||||
|
||||
fn id_table(&self) -> IdTable {
|
||||
IdTable::new(self.name(), None)
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
self.inner.lock().bus.clone()
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
|
||||
self.inner.lock().bus = bus;
|
||||
}
|
||||
|
||||
fn set_class(&self, class: Option<Arc<dyn Class>>) {
|
||||
self.inner.lock().class = class;
|
||||
}
|
||||
|
||||
fn driver(&self) -> Option<Arc<dyn Driver>> {
|
||||
self.inner.lock().driver.clone()?.upgrade()
|
||||
}
|
||||
|
||||
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
|
||||
self.inner.lock().driver = driver;
|
||||
}
|
||||
|
||||
fn is_dead(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn can_match(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn set_can_match(&self, _can_match: bool) {}
|
||||
|
||||
fn state_synced(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl KObject for VesaFb {
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
|
||||
self.inner.lock().kern_inode = inode;
|
||||
}
|
||||
|
||||
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||
self.inner.lock().kern_inode.clone()
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||
self.inner.lock().parent.clone()
|
||||
}
|
||||
|
||||
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
|
||||
self.inner.lock().parent = parent;
|
||||
}
|
||||
|
||||
fn kset(&self) -> Option<Arc<KSet>> {
|
||||
self.inner.lock().kset.clone()
|
||||
}
|
||||
|
||||
fn set_kset(&self, kset: Option<Arc<KSet>>) {
|
||||
self.inner.lock().kset = kset;
|
||||
}
|
||||
|
||||
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||
self.inner.lock().kobj_type
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
|
||||
self.inner.lock().kobj_type = ktype;
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
Self::NAME.to_string()
|
||||
}
|
||||
|
||||
fn set_name(&self, _name: String) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||
self.kobj_state.read()
|
||||
}
|
||||
|
||||
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||
self.kobj_state.write()
|
||||
}
|
||||
|
||||
fn set_kobj_state(&self, state: KObjectState) {
|
||||
*self.kobj_state.write() = state;
|
||||
}
|
||||
}
|
||||
|
||||
impl FrameBufferOps for VesaFb {
|
||||
fn fb_open(&self, _user: bool) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn fb_release(&self, _user: bool) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn fb_set_color_register(
|
||||
&self,
|
||||
_regno: u16,
|
||||
_red: u16,
|
||||
_green: u16,
|
||||
_blue: u16,
|
||||
) -> Result<(), SystemError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn fb_blank(&self, _blank_mode: BlankMode) -> Result<(), SystemError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn fb_destroy(&self) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl FrameBufferInfo for VesaFb {
|
||||
fn fb_device(&self) -> Option<Arc<FbDevice>> {
|
||||
self.inner.lock().fb_device.clone()
|
||||
}
|
||||
|
||||
fn set_fb_device(&self, device: Option<Arc<FbDevice>>) {
|
||||
self.inner.lock().fb_device = device;
|
||||
}
|
||||
|
||||
fn screen_size(&self) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn current_fb_var(&self) -> FbVarScreenInfo {
|
||||
VESAFB_DEFINED.read().clone()
|
||||
}
|
||||
|
||||
fn current_fb_fix(&self) -> FixedScreenInfo {
|
||||
VESAFB_FIX_INFO.read().clone()
|
||||
}
|
||||
|
||||
fn video_mode(&self) -> Option<&FbVideoMode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn state(&self) -> FbState {
|
||||
self.inner.lock().fb_state
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cast_to([sync] PlatformDriver)]
|
||||
struct VesaFbDriver {
|
||||
inner: SpinLock<InnerVesaFbDriver>,
|
||||
kobj_state: LockedKObjectState,
|
||||
}
|
||||
|
||||
impl VesaFbDriver {
|
||||
pub fn new() -> Arc<Self> {
|
||||
let r = Arc::new(Self {
|
||||
inner: SpinLock::new(InnerVesaFbDriver {
|
||||
ktype: None,
|
||||
kset: None,
|
||||
parent: None,
|
||||
kernfs_inode: None,
|
||||
devices: Vec::new(),
|
||||
bus: None,
|
||||
self_ref: Weak::new(),
|
||||
}),
|
||||
kobj_state: LockedKObjectState::new(None),
|
||||
});
|
||||
|
||||
r.inner.lock().self_ref = Arc::downgrade(&r);
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InnerVesaFbDriver {
|
||||
ktype: Option<&'static dyn KObjType>,
|
||||
kset: Option<Arc<KSet>>,
|
||||
parent: Option<Weak<dyn KObject>>,
|
||||
kernfs_inode: Option<Arc<KernFSInode>>,
|
||||
devices: Vec<Arc<dyn Device>>,
|
||||
bus: Option<Weak<dyn Bus>>,
|
||||
|
||||
self_ref: Weak<VesaFbDriver>,
|
||||
}
|
||||
|
||||
impl VesaFbDriver {
|
||||
const NAME: &'static str = "vesa-framebuffer";
|
||||
}
|
||||
|
||||
impl PlatformDriver for VesaFbDriver {
|
||||
fn probe(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
|
||||
let device = device
|
||||
.clone()
|
||||
.arc_any()
|
||||
.downcast::<VesaFb>()
|
||||
.map_err(|_| SystemError::EINVAL)?;
|
||||
|
||||
device.set_driver(Some(self.inner.lock_irqsave().self_ref.clone()));
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn remove(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn shutdown(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
|
||||
// do nothing
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn suspend(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
|
||||
// do nothing
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn resume(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Driver for VesaFbDriver {
|
||||
fn id_table(&self) -> Option<IdTable> {
|
||||
Some(IdTable::new(VesaFb::NAME.to_string(), None))
|
||||
}
|
||||
|
||||
fn devices(&self) -> Vec<Arc<dyn Device>> {
|
||||
self.inner.lock().devices.clone()
|
||||
}
|
||||
|
||||
fn add_device(&self, device: Arc<dyn Device>) {
|
||||
let mut guard = self.inner.lock();
|
||||
// check if the device is already in the list
|
||||
if guard.devices.iter().any(|dev| Arc::ptr_eq(dev, &device)) {
|
||||
return;
|
||||
}
|
||||
|
||||
guard.devices.push(device);
|
||||
}
|
||||
|
||||
fn delete_device(&self, device: &Arc<dyn Device>) {
|
||||
let mut guard = self.inner.lock();
|
||||
guard.devices.retain(|dev| !Arc::ptr_eq(dev, device));
|
||||
}
|
||||
|
||||
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
|
||||
self.inner.lock().bus = bus;
|
||||
}
|
||||
|
||||
fn bus(&self) -> Option<Weak<dyn Bus>> {
|
||||
self.inner.lock().bus.clone()
|
||||
}
|
||||
|
||||
fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
|
||||
return &[&VesaFbAnonAttributeGroup];
|
||||
}
|
||||
}
|
||||
|
||||
impl KObject for VesaFbDriver {
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
|
||||
self.inner.lock().kernfs_inode = inode;
|
||||
}
|
||||
|
||||
fn inode(&self) -> Option<Arc<KernFSInode>> {
|
||||
self.inner.lock().kernfs_inode.clone()
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<Weak<dyn KObject>> {
|
||||
self.inner.lock().parent.clone()
|
||||
}
|
||||
|
||||
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
|
||||
self.inner.lock().parent = parent;
|
||||
}
|
||||
|
||||
fn kset(&self) -> Option<Arc<KSet>> {
|
||||
self.inner.lock().kset.clone()
|
||||
}
|
||||
|
||||
fn set_kset(&self, kset: Option<Arc<KSet>>) {
|
||||
self.inner.lock().kset = kset;
|
||||
}
|
||||
|
||||
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
|
||||
self.inner.lock().ktype
|
||||
}
|
||||
|
||||
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
|
||||
self.inner.lock().ktype = ktype;
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
Self::NAME.to_string()
|
||||
}
|
||||
|
||||
fn set_name(&self, _name: String) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
|
||||
self.kobj_state.read()
|
||||
}
|
||||
|
||||
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
|
||||
self.kobj_state.write()
|
||||
}
|
||||
|
||||
fn set_kobj_state(&self, state: KObjectState) {
|
||||
*self.kobj_state.write() = state;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct VesaFbAnonAttributeGroup;
|
||||
|
||||
impl AttributeGroup for VesaFbAnonAttributeGroup {
|
||||
fn name(&self) -> Option<&str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn attrs(&self) -> &[&'static dyn Attribute] {
|
||||
&[&AnonAttrPhysAddr as &'static dyn Attribute]
|
||||
}
|
||||
|
||||
fn is_visible(
|
||||
&self,
|
||||
_kobj: Arc<dyn KObject>,
|
||||
attr: &'static dyn Attribute,
|
||||
) -> Option<ModeType> {
|
||||
Some(attr.mode())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AnonAttrPhysAddr;
|
||||
|
||||
impl Attribute for AnonAttrPhysAddr {
|
||||
fn name(&self) -> &str {
|
||||
"smem_start"
|
||||
}
|
||||
|
||||
fn mode(&self) -> ModeType {
|
||||
ModeType::S_IRUGO
|
||||
}
|
||||
|
||||
fn support(&self) -> SysFSOpsSupport {
|
||||
SysFSOpsSupport::SHOW
|
||||
}
|
||||
|
||||
fn show(&self, _kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
sysfs_emit_str(
|
||||
buf,
|
||||
format!(
|
||||
"0x{:x}\n",
|
||||
VESAFB_FIX_INFO
|
||||
.read()
|
||||
.smem_start
|
||||
.unwrap_or(PhysAddr::new(0))
|
||||
.data()
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[unified_init(INITCALL_DEVICE)]
|
||||
pub fn vesa_fb_driver_init() -> Result<(), SystemError> {
|
||||
let driver = VesaFbDriver::new();
|
||||
|
||||
platform_driver_manager().register(driver)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 在内存管理初始化之前,初始化vesafb
|
||||
pub fn vesafb_early_init() -> Result<VirtAddr, SystemError> {
|
||||
let mut _reserved: u32 = 0;
|
||||
|
||||
let mut fb_info: MaybeUninit<multiboot_tag_framebuffer_info_t> = MaybeUninit::uninit();
|
||||
//从multiboot2中读取帧缓冲区信息至fb_info
|
||||
|
||||
// todo: 换成rust的,并且检测是否成功获取
|
||||
unsafe {
|
||||
multiboot2_iter(
|
||||
Some(multiboot2_get_Framebuffer_info),
|
||||
fb_info.as_mut_ptr() as usize as *mut c_void,
|
||||
&mut _reserved as *mut c_uint,
|
||||
)
|
||||
};
|
||||
unsafe { fb_info.assume_init() };
|
||||
let fb_info: multiboot_tag_framebuffer_info_t = unsafe { core::mem::transmute(fb_info) };
|
||||
|
||||
// todo: 判断是否有vesa帧缓冲区,这里暂时直接设置true
|
||||
HAS_VESA_FB.store(true, core::sync::atomic::Ordering::SeqCst);
|
||||
|
||||
let width = fb_info.framebuffer_width;
|
||||
let height = fb_info.framebuffer_height;
|
||||
|
||||
let mut boot_params_guard = boot_params().write();
|
||||
let boottime_screen_info = &mut boot_params_guard.screen_info;
|
||||
|
||||
boottime_screen_info.is_vga = true;
|
||||
|
||||
boottime_screen_info.lfb_base = PhysAddr::new(fb_info.framebuffer_addr as usize);
|
||||
|
||||
if fb_info.framebuffer_type == 2 {
|
||||
//当type=2时,width与height用字符数表示,故depth=8
|
||||
boottime_screen_info.origin_video_cols = width as u8;
|
||||
boottime_screen_info.origin_video_lines = height as u8;
|
||||
boottime_screen_info.video_type = BootTimeVideoType::Mda;
|
||||
boottime_screen_info.lfb_depth = 8;
|
||||
} else {
|
||||
//否则为图像模式,depth应参照帧缓冲区信息里面的每个像素的位数
|
||||
boottime_screen_info.lfb_width = width;
|
||||
boottime_screen_info.lfb_height = height;
|
||||
boottime_screen_info.video_type = BootTimeVideoType::Vlfb;
|
||||
boottime_screen_info.lfb_depth = fb_info.framebuffer_bpp as u8;
|
||||
}
|
||||
|
||||
boottime_screen_info.lfb_size =
|
||||
(width * height * ((fb_info.framebuffer_bpp as u32 + 7) / 8)) as usize;
|
||||
|
||||
let buf_vaddr = VirtAddr::new(0xffff800003200000);
|
||||
boottime_screen_info.lfb_virt_base = Some(buf_vaddr);
|
||||
|
||||
let init_text = "Video driver to map.\n\0";
|
||||
send_to_default_serial8250_port(init_text.as_bytes());
|
||||
|
||||
// 地址映射
|
||||
let paddr = PhysAddr::new(fb_info.framebuffer_addr as usize);
|
||||
let count =
|
||||
PageFrameCount::new(page_align_up(boottime_screen_info.lfb_size) / MMArch::PAGE_SIZE);
|
||||
unsafe { pseudo_map_phys(buf_vaddr, paddr, count) };
|
||||
return Ok(buf_vaddr);
|
||||
}
|
||||
|
||||
#[unified_init(INITCALL_DEVICE)]
|
||||
fn vesa_fb_device_init() -> Result<(), SystemError> {
|
||||
// 如果没有vesa帧缓冲区,直接返回
|
||||
if !HAS_VESA_FB.load(core::sync::atomic::Ordering::SeqCst) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
static INIT: Once = Once::new();
|
||||
INIT.call_once(|| {
|
||||
kinfo!("vesa fb device init");
|
||||
|
||||
let mut fix_info_guard = VESAFB_FIX_INFO.write_irqsave();
|
||||
let mut var_info_guard = VESAFB_DEFINED.write_irqsave();
|
||||
|
||||
let boot_params_guard = boot_params().read();
|
||||
let boottime_screen_info = &boot_params_guard.screen_info;
|
||||
|
||||
fix_info_guard.smem_start = Some(boottime_screen_info.lfb_base);
|
||||
fix_info_guard.smem_len = boottime_screen_info.lfb_size;
|
||||
|
||||
if boottime_screen_info.video_type == BootTimeVideoType::Mda {
|
||||
fix_info_guard.visual = FbVisual::Mono10;
|
||||
var_info_guard.bits_per_pixel = 8;
|
||||
fix_info_guard.line_length = (boottime_screen_info.origin_video_cols as u32)
|
||||
* (var_info_guard.bits_per_pixel / 8);
|
||||
var_info_guard.xres_virtual = boottime_screen_info.origin_video_cols as u32;
|
||||
var_info_guard.yres_virtual = boottime_screen_info.origin_video_lines as u32;
|
||||
} else {
|
||||
fix_info_guard.visual = FbVisual::TrueColor;
|
||||
var_info_guard.bits_per_pixel = boottime_screen_info.lfb_depth as u32;
|
||||
fix_info_guard.line_length =
|
||||
(boottime_screen_info.lfb_width as u32) * (var_info_guard.bits_per_pixel / 8);
|
||||
var_info_guard.xres_virtual = boottime_screen_info.lfb_width as u32;
|
||||
var_info_guard.yres_virtual = boottime_screen_info.lfb_height as u32;
|
||||
}
|
||||
|
||||
drop(var_info_guard);
|
||||
drop(fix_info_guard);
|
||||
|
||||
let device = Arc::new(VesaFb::new());
|
||||
device_manager().device_default_initialize(&(device.clone() as Arc<dyn Device>));
|
||||
|
||||
platform_device_manager()
|
||||
.device_add(device.clone() as Arc<dyn PlatformDevice>)
|
||||
.expect("vesa_fb_device_init: platform_device_manager().device_add failed");
|
||||
|
||||
frame_buffer_manager()
|
||||
.register_fb(device.clone() as Arc<dyn FrameBuffer>)
|
||||
.expect("vesa_fb_device_init: frame_buffer_manager().register_fb failed");
|
||||
|
||||
// 设置vesa fb的状态为运行中
|
||||
device.inner.lock().fb_state = FbState::Running;
|
||||
});
|
||||
|
||||
return Ok(());
|
||||
}
|
@ -1,16 +1,12 @@
|
||||
use core::{
|
||||
ffi::{c_uint, c_void},
|
||||
mem::MaybeUninit,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use crate::{
|
||||
arch::MMArch,
|
||||
driver::tty::serial::serial8250::send_to_default_serial8250_port,
|
||||
include::bindings::bindings::{
|
||||
multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t,
|
||||
FRAME_BUFFER_MAPPING_OFFSET, SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE,
|
||||
},
|
||||
init::boot_params,
|
||||
kinfo,
|
||||
libs::{
|
||||
align::page_align_up,
|
||||
@ -19,8 +15,8 @@ use crate::{
|
||||
spinlock::SpinLock,
|
||||
},
|
||||
mm::{
|
||||
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper,
|
||||
no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
|
||||
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, page::PageFlags,
|
||||
MemoryManagementArch, VirtAddr,
|
||||
},
|
||||
time::timer::{Timer, TimerFunction},
|
||||
};
|
||||
@ -42,7 +38,6 @@ pub fn video_refresh_manager() -> &'static VideoRefreshManager {
|
||||
///管理显示刷新变量的结构体
|
||||
pub struct VideoRefreshManager {
|
||||
device_buffer: RwLock<ScmBufferInfo>,
|
||||
fb_info: multiboot_tag_framebuffer_info_t,
|
||||
refresh_target: RwLock<Option<Arc<SpinLock<Box<[u32]>>>>>,
|
||||
running: AtomicBool,
|
||||
}
|
||||
@ -94,6 +89,7 @@ impl VideoRefreshManager {
|
||||
let buf_vaddr = VirtAddr::new(
|
||||
SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE as usize + FRAME_BUFFER_MAPPING_OFFSET as usize,
|
||||
);
|
||||
boot_params().write_irqsave().screen_info.lfb_virt_base = Some(buf_vaddr);
|
||||
|
||||
let mut frame_buffer_info_graud = self.device_buffer.write();
|
||||
if let ScmBuffer::DeviceBuffer(vaddr) = &mut (frame_buffer_info_graud).buf {
|
||||
@ -101,7 +97,7 @@ impl VideoRefreshManager {
|
||||
}
|
||||
|
||||
// 地址映射
|
||||
let mut paddr = PhysAddr::new(self.fb_info.framebuffer_addr as usize);
|
||||
let mut paddr = boot_params().read().screen_info.lfb_base;
|
||||
let count = PageFrameCount::new(
|
||||
page_align_up(frame_buffer_info_graud.buf_size()) / MMArch::PAGE_SIZE,
|
||||
);
|
||||
@ -178,68 +174,48 @@ impl VideoRefreshManager {
|
||||
}
|
||||
|
||||
/// 此函数用于初始化显示驱动,为后续的图形输出做好准备。
|
||||
#[cfg(not(target_arch = "riscv64"))]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub unsafe fn video_init() -> Result<(), SystemError> {
|
||||
static INIT: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
if INIT
|
||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
||||
.is_err()
|
||||
{
|
||||
panic!("Try to init video twice!");
|
||||
}
|
||||
|
||||
let mut _reserved: u32 = 0;
|
||||
|
||||
let mut fb_info: MaybeUninit<multiboot_tag_framebuffer_info_t> = MaybeUninit::uninit();
|
||||
//从multiboot2中读取帧缓冲区信息至fb_info
|
||||
multiboot2_iter(
|
||||
Some(multiboot2_get_Framebuffer_info),
|
||||
fb_info.as_mut_ptr() as usize as *mut c_void,
|
||||
&mut _reserved as *mut c_uint,
|
||||
);
|
||||
fb_info.assume_init();
|
||||
let fb_info: multiboot_tag_framebuffer_info_t = core::mem::transmute(fb_info);
|
||||
|
||||
let width = fb_info.framebuffer_width;
|
||||
let height = fb_info.framebuffer_height;
|
||||
|
||||
//初始化帧缓冲区信息结构体
|
||||
let (bit_depth, flags) = if fb_info.framebuffer_type == 2 {
|
||||
//当type=2时,width与height用字符数表示,故depth=8
|
||||
|
||||
(8u32, ScmBufferFlag::SCM_BF_TEXT | ScmBufferFlag::SCM_BF_FB)
|
||||
} else {
|
||||
//否则为图像模式,depth应参照帧缓冲区信息里面的每个像素的位数
|
||||
(
|
||||
fb_info.framebuffer_bpp as u32,
|
||||
ScmBufferFlag::SCM_BF_PIXEL | ScmBufferFlag::SCM_BF_FB,
|
||||
)
|
||||
use crate::{
|
||||
arch::driver::video::arch_video_early_init,
|
||||
driver::video::fbdev::base::BootTimeVideoType,
|
||||
};
|
||||
|
||||
let buf_vaddr = VirtAddr::new(0xffff800003200000);
|
||||
let device_buffer = ScmBufferInfo::new_device_buffer(
|
||||
width,
|
||||
height,
|
||||
width * height * ((bit_depth + 7) / 8),
|
||||
bit_depth,
|
||||
flags,
|
||||
buf_vaddr,
|
||||
)
|
||||
.unwrap();
|
||||
arch_video_early_init()?;
|
||||
|
||||
let init_text = "Video driver to map.\n\0";
|
||||
send_to_default_serial8250_port(init_text.as_bytes());
|
||||
let boot_params_guard = boot_params().read();
|
||||
let screen_info = &boot_params_guard.screen_info;
|
||||
let buf_vaddr = screen_info.lfb_virt_base.unwrap();
|
||||
|
||||
//地址映射
|
||||
let paddr = PhysAddr::new(fb_info.framebuffer_addr as usize);
|
||||
let count = PageFrameCount::new(
|
||||
page_align_up(device_buffer.buf_size() as usize) / MMArch::PAGE_SIZE,
|
||||
);
|
||||
pseudo_map_phys(buf_vaddr, paddr, count);
|
||||
let buf_flag: ScmBufferFlag;
|
||||
let device_buffer: ScmBufferInfo;
|
||||
|
||||
if screen_info.video_type == BootTimeVideoType::Mda {
|
||||
buf_flag = ScmBufferFlag::SCM_BF_TEXT | ScmBufferFlag::SCM_BF_FB;
|
||||
device_buffer = ScmBufferInfo::new_device_buffer(
|
||||
screen_info.origin_video_cols.into(),
|
||||
screen_info.origin_video_lines.into(),
|
||||
screen_info.lfb_size as u32,
|
||||
screen_info.lfb_depth.into(),
|
||||
buf_flag,
|
||||
buf_vaddr,
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
// 图形模式
|
||||
buf_flag = ScmBufferFlag::SCM_BF_PIXEL | ScmBufferFlag::SCM_BF_FB;
|
||||
device_buffer = ScmBufferInfo::new_device_buffer(
|
||||
screen_info.lfb_width,
|
||||
screen_info.lfb_height,
|
||||
screen_info.lfb_size as u32,
|
||||
screen_info.lfb_depth.into(),
|
||||
buf_flag,
|
||||
buf_vaddr,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let result = Self {
|
||||
fb_info,
|
||||
device_buffer: RwLock::new(device_buffer),
|
||||
refresh_target: RwLock::new(None),
|
||||
running: AtomicBool::new(false),
|
||||
|
@ -9,6 +9,7 @@ use alloc::{
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use crate::driver::base::device::device_number::DeviceNumber;
|
||||
use crate::filesystem::vfs::SpecialNodeData;
|
||||
use crate::ipc::pipe::LockedPipeInode;
|
||||
use crate::{
|
||||
@ -1685,7 +1686,7 @@ impl IndexNode for LockedFATInode {
|
||||
&self,
|
||||
filename: &str,
|
||||
mode: ModeType,
|
||||
_dev_t: crate::driver::base::device::DeviceNumber,
|
||||
_dev_t: DeviceNumber,
|
||||
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
||||
let mut inode = self.0.lock();
|
||||
if inode.metadata.file_type != FileType::Dir {
|
||||
|
@ -10,6 +10,7 @@ use alloc::{
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::base::device::device_number::DeviceNumber,
|
||||
filesystem::vfs::{core::generate_inode_id, FileType},
|
||||
ipc::pipe::LockedPipeInode,
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
@ -475,7 +476,7 @@ impl IndexNode for LockedRamFSInode {
|
||||
&self,
|
||||
filename: &str,
|
||||
mode: ModeType,
|
||||
_dev_t: crate::driver::base::device::DeviceNumber,
|
||||
_dev_t: DeviceNumber,
|
||||
) -> Result<Arc<dyn IndexNode>, SystemError> {
|
||||
let mut inode = self.0.lock();
|
||||
if inode.metadata.file_type != FileType::Dir {
|
||||
|
@ -12,7 +12,9 @@ use alloc::{string::String, sync::Arc, vec::Vec};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::base::{block::block_device::BlockDevice, char::CharDevice, device::DeviceNumber},
|
||||
driver::base::{
|
||||
block::block_device::BlockDevice, char::CharDevice, device::device_number::DeviceNumber,
|
||||
},
|
||||
ipc::pipe::LockedPipeInode,
|
||||
libs::casting::DowncastArc,
|
||||
time::TimeSpec,
|
||||
|
@ -9,7 +9,7 @@ use alloc::{
|
||||
};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{driver::base::device::DeviceNumber, libs::spinlock::SpinLock};
|
||||
use crate::{driver::base::device::device_number::DeviceNumber, libs::spinlock::SpinLock};
|
||||
|
||||
use super::{
|
||||
file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode, InodeId,
|
||||
|
@ -8,7 +8,7 @@ use alloc::{
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::base::{block::SeekFrom, device::DeviceNumber},
|
||||
driver::base::{block::SeekFrom, device::device_number::DeviceNumber},
|
||||
filesystem::vfs::file::FileDescriptorVec,
|
||||
kerror,
|
||||
libs::rwlock::RwLockWriteGuard,
|
||||
|
25
kernel/src/init/initcall.rs
Normal file
25
kernel/src/init/initcall.rs
Normal file
@ -0,0 +1,25 @@
|
||||
use system_error::SystemError;
|
||||
use unified_init::{define_public_unified_initializer_slice, unified_init};
|
||||
|
||||
define_public_unified_initializer_slice!(INITCALL_PURE);
|
||||
define_public_unified_initializer_slice!(INITCALL_CORE);
|
||||
define_public_unified_initializer_slice!(INITCALL_POSTCORE);
|
||||
define_public_unified_initializer_slice!(INITCALL_ARCH);
|
||||
define_public_unified_initializer_slice!(INITCALL_SUBSYS);
|
||||
define_public_unified_initializer_slice!(INITCALL_FS);
|
||||
define_public_unified_initializer_slice!(INITCALL_ROOTFS);
|
||||
define_public_unified_initializer_slice!(INITCALL_DEVICE);
|
||||
define_public_unified_initializer_slice!(INITCALL_LATE);
|
||||
|
||||
pub fn do_initcalls() -> Result<(), SystemError> {
|
||||
unified_init!(INITCALL_PURE);
|
||||
unified_init!(INITCALL_CORE);
|
||||
unified_init!(INITCALL_POSTCORE);
|
||||
unified_init!(INITCALL_ARCH);
|
||||
unified_init!(INITCALL_SUBSYS);
|
||||
unified_init!(INITCALL_FS);
|
||||
unified_init!(INITCALL_ROOTFS);
|
||||
unified_init!(INITCALL_DEVICE);
|
||||
unified_init!(INITCALL_LATE);
|
||||
return Ok(());
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
//! 这个文件内放置初始内核线程的代码。
|
||||
|
||||
use alloc::string::String;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::process::arch_switch_to_user,
|
||||
@ -13,8 +14,23 @@ use crate::{
|
||||
process::{kthread::KernelThreadMechanism, process::stdio_init},
|
||||
};
|
||||
|
||||
use super::initcall::do_initcalls;
|
||||
|
||||
pub fn initial_kernel_thread() -> i32 {
|
||||
kernel_init().unwrap_or_else(|err| {
|
||||
panic!("Failed to initialize kernel: {:?}", err);
|
||||
});
|
||||
|
||||
switch_to_user();
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn kernel_init() -> Result<(), SystemError> {
|
||||
kenrel_init_freeable()?;
|
||||
|
||||
KernelThreadMechanism::init_stage2();
|
||||
|
||||
// 由于目前加锁,速度过慢,所以先不开启双缓冲
|
||||
// scm_enable_double_buffer().expect("Failed to enable double buffer");
|
||||
stdio_init().expect("Failed to initialize stdio");
|
||||
@ -31,9 +47,16 @@ pub fn initial_kernel_thread() -> i32 {
|
||||
|
||||
kdebug!("initial kernel thread done.");
|
||||
|
||||
switch_to_user();
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
loop {}
|
||||
#[inline(never)]
|
||||
fn kenrel_init_freeable() -> Result<(), SystemError> {
|
||||
do_initcalls().unwrap_or_else(|err| {
|
||||
panic!("Failed to initialize subsystems: {:?}", err);
|
||||
});
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// 切换到用户态
|
@ -1,9 +1,23 @@
|
||||
use crate::{
|
||||
driver::{tty::init::tty_early_init, video::VideoRefreshManager},
|
||||
libs::lib_ui::screen_manager::scm_init,
|
||||
driver::{
|
||||
tty::init::tty_early_init,
|
||||
video::{fbdev::base::BootTimeScreenInfo, VideoRefreshManager},
|
||||
},
|
||||
libs::{lib_ui::screen_manager::scm_init, rwlock::RwLock},
|
||||
};
|
||||
|
||||
pub mod c_adapter;
|
||||
mod c_adapter;
|
||||
|
||||
pub mod initcall;
|
||||
pub mod initial_kthread;
|
||||
|
||||
/// 启动参数
|
||||
static BOOT_PARAMS: RwLock<BootParams> = RwLock::new(BootParams::new());
|
||||
|
||||
#[inline(always)]
|
||||
pub fn boot_params() -> &'static RwLock<BootParams> {
|
||||
&BOOT_PARAMS
|
||||
}
|
||||
|
||||
fn init_intertrait() {
|
||||
intertrait::init_caster_map();
|
||||
@ -15,3 +29,18 @@ pub fn init_before_mem_init() {
|
||||
let video_ok = unsafe { VideoRefreshManager::video_init().is_ok() };
|
||||
scm_init(video_ok);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BootParams {
|
||||
pub screen_info: BootTimeScreenInfo,
|
||||
}
|
||||
|
||||
impl BootParams {
|
||||
const DEFAULT: Self = BootParams {
|
||||
screen_info: BootTimeScreenInfo::DEFAULT,
|
||||
};
|
||||
|
||||
const fn new() -> Self {
|
||||
Self::DEFAULT
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#![feature(allocator_api)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(asm_const)]
|
||||
#![feature(const_for)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_refs_to_cell)]
|
||||
|
@ -15,14 +15,13 @@ use system_error::SystemError;
|
||||
use crate::{
|
||||
arch::{sched::sched, CurrentIrqArch},
|
||||
exception::InterruptArch,
|
||||
init::initial_kthread::initial_kernel_thread,
|
||||
kdebug, kinfo,
|
||||
libs::{once::Once, spinlock::SpinLock},
|
||||
process::{ProcessManager, ProcessState},
|
||||
};
|
||||
|
||||
use super::{
|
||||
fork::CloneFlags, init::initial_kernel_thread, Pid, ProcessControlBlock, ProcessFlags,
|
||||
};
|
||||
use super::{fork::CloneFlags, Pid, ProcessControlBlock, ProcessFlags};
|
||||
|
||||
/// 内核线程的创建任务列表
|
||||
static KTHREAD_CREATE_LIST: SpinLock<LinkedList<Arc<KernelThreadCreateInfo>>> =
|
||||
|
@ -59,7 +59,6 @@ pub mod exec;
|
||||
pub mod exit;
|
||||
pub mod fork;
|
||||
pub mod idle;
|
||||
pub mod init;
|
||||
pub mod kthread;
|
||||
pub mod pid;
|
||||
pub mod process;
|
||||
|
@ -5,6 +5,7 @@ use core::{
|
||||
|
||||
use crate::{
|
||||
arch::{ipc::signal::SigSet, syscall::nr::*},
|
||||
driver::base::device::device_number::DeviceNumber,
|
||||
libs::{futex::constant::FutexFlag, rand::GRandFlags},
|
||||
process::{
|
||||
fork::KernelCloneArgs,
|
||||
@ -681,11 +682,7 @@ impl Syscall {
|
||||
let flags = args[1];
|
||||
let dev_t = args[2];
|
||||
let flags: ModeType = ModeType::from_bits_truncate(flags as u32);
|
||||
Self::mknod(
|
||||
path as *const i8,
|
||||
flags,
|
||||
crate::driver::base::device::DeviceNumber::from(dev_t),
|
||||
)
|
||||
Self::mknod(path as *const i8, flags, DeviceNumber::from(dev_t as u32))
|
||||
}
|
||||
|
||||
SYS_CLONE => {
|
||||
|
@ -31,8 +31,8 @@ sqlite3.o: $(SQLITE3_DIR)/sqlite3.c
|
||||
$(CC) $(CFLAGS) -c $(SQLITE3_DIR)/sqlite3.c -o sqlite3.o
|
||||
|
||||
__download_sqlite3:
|
||||
@echo "Download sqlite3 from https://mirrors.ringotek.cn/pub/third_party/sqlite/$(SQLITE_FILENAME).zip"
|
||||
@wget https://mirrors.ringotek.cn/pub/third_party/sqlite/$(SQLITE_FILENAME).zip || (@echo "Download sqlite3 failed" && rm $(SQLITE_FILENAME).zip && exit 1)
|
||||
@echo "Download sqlite3 from https://mirrors.dragonos.org.cn/pub/third_party/sqlite/$(SQLITE_FILENAME).zip"
|
||||
@wget https://mirrors.dragonos.org.cn/pub/third_party/sqlite/$(SQLITE_FILENAME).zip || (@echo "Download sqlite3 failed" && rm $(SQLITE_FILENAME).zip && exit 1)
|
||||
@unzip -o $(SQLITE_FILENAME).zip || (@echo "Unzip sqlite3 failed" && exit 1)
|
||||
@rm $(SQLITE_FILENAME).zip || (@echo "Remove $(SQLITE_FILENAME).zip failed" && exit 1)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user