Skip to content

Commit

Permalink
增加/dev/fb0,能够在用户程序读写帧缓冲区 (#485)
Browse files Browse the repository at this point in the history
  • Loading branch information
fslongjin authored Jan 2, 2024
1 parent e7071df commit 02343d0
Show file tree
Hide file tree
Showing 22 changed files with 230 additions and 53 deletions.
5 changes: 5 additions & 0 deletions kernel/src/driver/base/device/device_number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ impl Major {

/// 未命名的主设备
pub const UNNAMED_MAJOR: Self = Self::new(0);

pub const IDE0_MAJOR: Self = Self::new(3);
pub const HD_MAJOR: Self = Self::IDE0_MAJOR;

pub const INPUT_MAJOR: Self = Self::new(13);
/// /dev/fb* framebuffers
pub const FB_MAJOR: Self = Self::new(29);

Expand Down
7 changes: 5 additions & 2 deletions kernel/src/driver/base/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ impl DeviceManager {
/// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/core.c#3398
///
/// todo: 完善错误处理逻辑:如果添加失败,需要将之前添加的内容全部回滚
#[inline]
#[inline(never)]
#[allow(dead_code)]
pub fn add_device(&self, device: Arc<dyn Device>) -> Result<(), SystemError> {
// 在这里处理与parent相关的逻辑
Expand Down Expand Up @@ -547,14 +547,17 @@ impl DeviceManager {
/// @brief: 卸载设备
/// @parameter id_table: 总线标识符,用于唯一标识该设备
/// @return: None
///
/// ## 注意
/// 该函数已废弃,不再使用
#[inline]
#[allow(dead_code)]
pub fn remove_device(&self, _id_table: &IdTable) {
todo!()
}

/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#542
fn remove(&self, _dev: &Arc<dyn Device>) {
pub fn remove(&self, _dev: &Arc<dyn Device>) {
todo!("DeviceManager::remove")
}

Expand Down
6 changes: 3 additions & 3 deletions kernel/src/driver/disk/ahci/ahci_inode.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::driver::base::block::block_device::BlockDevice;
use crate::driver::base::device::device_number::{DeviceNumber, Major};
use crate::filesystem::devfs::{DevFS, DeviceINode};
use crate::filesystem::vfs::file::FileMode;
use crate::filesystem::vfs::syscall::ModeType;
use crate::filesystem::vfs::{
core::generate_inode_id, make_rawdev, FilePrivateData, FileSystem, FileType, IndexNode,
Metadata,
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
};
use crate::{libs::spinlock::SpinLock, time::TimeSpec};
use alloc::{
Expand Down Expand Up @@ -54,7 +54,7 @@ impl LockedAhciInode {
nlinks: 1,
uid: 0,
gid: 0,
raw_dev: make_rawdev(1, 3), // 这里用来作为device number
raw_dev: DeviceNumber::new(Major::HD_MAJOR, 0),
},
};

Expand Down
7 changes: 5 additions & 2 deletions kernel/src/driver/keyboard/ps2_keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use core::{ffi::c_void, sync::atomic::AtomicI32};
use alloc::sync::{Arc, Weak};

use crate::{
driver::tty::tty_device::TTY_DEVICES,
driver::{
base::device::device_number::{DeviceNumber, Major},
tty::tty_device::TTY_DEVICES,
},
filesystem::{
devfs::{devfs_register, DevFS, DeviceINode},
vfs::{
Expand Down Expand Up @@ -65,7 +68,7 @@ impl LockedPS2KeyBoardInode {
nlinks: 1,
uid: 0,
gid: 0,
raw_dev: 0, // 这里用来作为device number
raw_dev: DeviceNumber::new(Major::INPUT_MAJOR, 0), // 这里用来作为device number
},
};

Expand Down
124 changes: 113 additions & 11 deletions kernel/src/driver/video/fbdev/base/fbmem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use core::intrinsics::unlikely;
use alloc::{
string::{String, ToString},
sync::{Arc, Weak},
vec::Vec,
};

use system_error::SystemError;
Expand All @@ -22,11 +23,19 @@ use crate::{
kset::KSet,
subsys::SubSysPrivate,
},
filesystem::{kernfs::KernFSInode, sysfs::AttributeGroup},
filesystem::{
devfs::{devfs_register, DevFS, DeviceINode},
kernfs::KernFSInode,
sysfs::AttributeGroup,
vfs::{
file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode,
Metadata,
},
},
init::initcall::INITCALL_SUBSYS,
libs::{
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
spinlock::SpinLock,
spinlock::{SpinLock, SpinLockGuard},
},
};

Expand Down Expand Up @@ -141,6 +150,16 @@ impl FrameBufferManager {
fb.set_fb_device(Some(fb_device.clone()));

device_manager().add_device(fb_device.clone() as Arc<dyn Device>)?;
// 添加到devfs
devfs_register(&fb_device.name(), fb_device.clone()).map_err(|e| {
kerror!(
"register fb device '{}' to devfs failed: {:?}",
fb_device.name(),
e
);
device_manager().remove(&(fb_device.clone() as Arc<dyn Device>));
e
})?;

// todo: 从Modedb中获取信息
// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbmem.c#1584
Expand Down Expand Up @@ -195,22 +214,44 @@ pub struct FbDevice {
impl FbDevice {
pub const BASENAME: &'static str = "fb";
fn new(fb: Weak<dyn FrameBuffer>, id: FbId) -> Arc<Self> {
Arc::new(Self {
let r = Arc::new(Self {
inner: SpinLock::new(InnerFbDevice {
fb,
kern_inode: None,
parent: None,
kset: None,
ktype: None,
fb_id: id,
device_inode_fs: None,
devfs_metadata: Metadata::new(
FileType::FramebufferDevice,
ModeType::from_bits_truncate(0o666),
),
}),
kobj_state: LockedKObjectState::new(None),
})
});

let mut inner_guard = r.inner.lock();

inner_guard.devfs_metadata.raw_dev = r.do_device_number(&inner_guard);
drop(inner_guard);

return r;
}

pub fn framebuffer(&self) -> Option<Arc<dyn FrameBuffer>> {
self.inner.lock().fb.upgrade()
}

/// 获取设备号
pub fn device_number(&self) -> DeviceNumber {
let inner_guard = self.inner.lock();
self.do_device_number(&inner_guard)
}

fn do_device_number(&self, inner_guard: &SpinLockGuard<'_, InnerFbDevice>) -> DeviceNumber {
DeviceNumber::new(Major::FB_MAJOR, inner_guard.fb_id.data())
}
}

#[derive(Debug)]
Expand All @@ -222,6 +263,10 @@ struct InnerFbDevice {
ktype: Option<&'static dyn KObjType>,
/// 帧缓冲区id
fb_id: FbId,

/// device inode要求的字段
device_inode_fs: Option<Weak<DevFS>>,
devfs_metadata: Metadata,
}

impl KObject for FbDevice {
Expand Down Expand Up @@ -288,13 +333,7 @@ impl Device for FbDevice {
}

fn id_table(&self) -> IdTable {
IdTable::new(
Self::BASENAME.to_string(),
Some(DeviceNumber::new(
Major::FB_MAJOR,
self.inner.lock().fb_id.data(),
)),
)
IdTable::new(Self::BASENAME.to_string(), Some(self.device_number()))
}

fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
Expand Down Expand Up @@ -336,3 +375,66 @@ impl Device for FbDevice {
Some(&[&FbDeviceAttrGroup])
}
}

impl DeviceINode for FbDevice {
fn set_fs(&self, fs: Weak<DevFS>) {
self.inner.lock().device_inode_fs = Some(fs);
}
}

impl IndexNode for FbDevice {
fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> {
Ok(())
}

fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
Ok(())
}
fn read_at(
&self,
offset: usize,
len: usize,
buf: &mut [u8],
_data: &mut FilePrivateData,
) -> Result<usize, SystemError> {
let fb = self.inner.lock().fb.upgrade().unwrap();
return fb.fb_read(&mut buf[0..len], offset);
}

fn write_at(
&self,
offset: usize,
len: usize,
buf: &[u8],
_data: &mut FilePrivateData,
) -> Result<usize, SystemError> {
let fb = self.inner.lock().fb.upgrade().unwrap();
return fb.fb_write(&buf[0..len], offset);
}

fn fs(&self) -> Arc<dyn FileSystem> {
self.inner
.lock()
.device_inode_fs
.as_ref()
.unwrap()
.upgrade()
.unwrap()
}

fn as_any_ref(&self) -> &dyn core::any::Any {
self
}

fn list(&self) -> Result<Vec<String>, SystemError> {
todo!()
}

fn metadata(&self) -> Result<Metadata, SystemError> {
Ok(self.inner.lock().devfs_metadata.clone())
}

fn resize(&self, _len: usize) -> Result<(), SystemError> {
return Ok(());
}
}
42 changes: 42 additions & 0 deletions kernel/src/driver/video/fbdev/vesafb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,48 @@ impl FrameBufferOps for VesaFb {
fn fb_destroy(&self) {
todo!()
}

fn fb_read(&self, buf: &mut [u8], pos: usize) -> Result<usize, SystemError> {
let bp = boot_params().read();

let vaddr = bp.screen_info.lfb_virt_base.ok_or(SystemError::ENODEV)?;
let size = self.current_fb_fix().smem_len;
drop(bp);
if pos >= size {
return Ok(0);
}

let pos = pos as i64;
let size = size as i64;

let len = core::cmp::min(size - pos, buf.len() as i64) as usize;

let slice = unsafe { core::slice::from_raw_parts(vaddr.as_ptr::<u8>(), size as usize) };
buf[..len].copy_from_slice(&slice[pos as usize..(pos as usize + len)]);

return Ok(len);
}

fn fb_write(&self, buf: &[u8], pos: usize) -> Result<usize, SystemError> {
let bp = boot_params().read();

let vaddr = bp.screen_info.lfb_virt_base.ok_or(SystemError::ENODEV)?;
let size = self.current_fb_fix().smem_len;

if pos >= size {
return Ok(0);
}

let pos = pos as i64;
let size = size as i64;

let len = core::cmp::min(size - pos, buf.len() as i64) as usize;

let slice = unsafe { core::slice::from_raw_parts_mut(vaddr.as_ptr::<u8>(), size as usize) };
slice[pos as usize..(pos as usize + len)].copy_from_slice(&buf[..len]);

return Ok(len);
}
}

impl FrameBufferInfo for VesaFb {
Expand Down
6 changes: 3 additions & 3 deletions kernel/src/driver/video/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ impl VideoRefreshManager {
);
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 {
let mut frame_buffer_info_guard = self.device_buffer.write();
if let ScmBuffer::DeviceBuffer(vaddr) = &mut (frame_buffer_info_guard).buf {
*vaddr = buf_vaddr;
}

// 地址映射
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,
page_align_up(frame_buffer_info_guard.buf_size()) / MMArch::PAGE_SIZE,
);
let page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true);

Expand Down
10 changes: 8 additions & 2 deletions kernel/src/filesystem/devfs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use super::vfs::{
FileSystem, FileType, FsInfo, IndexNode, Metadata,
};
use crate::{
driver::base::device::device_number::DeviceNumber,
kerror, kinfo,
libs::{
once::Once,
Expand Down Expand Up @@ -154,6 +155,11 @@ impl DevFS {
.add_dev(name, device.clone())
.expect("DevFS: Failed to register /dev/kvm");
}
FileType::FramebufferDevice => {
dev_root_inode
.add_dev(name, device.clone())
.expect("DevFS: Failed to register /dev/fb");
}
_ => {
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
Expand Down Expand Up @@ -254,7 +260,7 @@ impl DevFSInode {
nlinks: 1,
uid: 0,
gid: 0,
raw_dev: data_,
raw_dev: DeviceNumber::from(data_ as u32),
},
fs: Weak::default(),
};
Expand Down Expand Up @@ -344,7 +350,7 @@ impl LockedDevFSInode {
nlinks: 1,
uid: 0,
gid: 0,
raw_dev: data,
raw_dev: DeviceNumber::from(data as u32),
},
fs: guard.fs.clone(),
})));
Expand Down
4 changes: 2 additions & 2 deletions kernel/src/filesystem/devfs/null_dev.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::driver::base::device::device_number::DeviceNumber;
use crate::filesystem::vfs::file::FileMode;
use crate::filesystem::vfs::make_rawdev;
use crate::filesystem::vfs::syscall::ModeType;
use crate::filesystem::vfs::{
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
Expand Down Expand Up @@ -49,7 +49,7 @@ impl LockedNullInode {
nlinks: 1,
uid: 0,
gid: 0,
raw_dev: make_rawdev(1, 3), // 这里用来作为device number
raw_dev: DeviceNumber::default(), // 这里用来作为device number
},
};

Expand Down
Loading

0 comments on commit 02343d0

Please sign in to comment.