添加帧缓冲区抽象并实现vesafb的驱动 (#483)

- 添加bootparams对象
- 修正由于bus的driver、device强弱引用关系 不正确从而导致对象被释放的bug
- 添加vesafb的驱动
- 实现framebuffer抽象层
- 为通用帧缓冲区抽象实现sysfs的属性
- 修改设备号DeviceNumber的定义
- 仿照linux,添加initcall,并在第一个内核线程中,调用他们。
This commit is contained in:
LoGin
2024-01-01 11:46:51 +08:00
committed by GitHub
parent e3eb08d4d7
commit c566df451c
45 changed files with 2179 additions and 391 deletions

View File

@ -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");

View File

@ -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])
}
}

View 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")
}
}

View File

@ -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,
}

View File

@ -0,0 +1,3 @@
//! todo: 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/modedb.c
//!
//! 实现modedb

View File

@ -1 +1,2 @@
pub mod base;
pub mod vesafb;

View 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(());
}

View File

@ -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),