1 use core::sync::atomic::{AtomicBool, Ordering}; 2 3 use crate::{ 4 arch::MMArch, 5 init::boot_params, 6 libs::{ 7 align::page_align_up, 8 lib_ui::screen_manager::{ScmBuffer, ScmBufferFlag, ScmBufferInfo}, 9 rwlock::{RwLock, RwLockReadGuard}, 10 spinlock::SpinLock, 11 }, 12 mm::{mmio_buddy::mmio_pool, page::EntryFlags}, 13 time::timer::{Timer, TimerFunction}, 14 }; 15 use alloc::{boxed::Box, sync::Arc}; 16 use log::info; 17 use system_error::SystemError; 18 19 pub mod console; 20 pub mod fbdev; 21 22 static mut __MAMAGER: Option<VideoRefreshManager> = None; 23 24 pub fn video_refresh_manager() -> &'static VideoRefreshManager { 25 return unsafe { 26 __MAMAGER 27 .as_ref() 28 .expect("Video refresh manager has not been initialized yet!") 29 }; 30 } 31 #[allow(clippy::type_complexity)] 32 ///管理显示刷新变量的结构体 33 pub struct VideoRefreshManager { 34 device_buffer: RwLock<ScmBufferInfo>, 35 refresh_target: RwLock<Option<Arc<SpinLock<Box<[u8]>>>>>, 36 running: AtomicBool, 37 } 38 39 const REFRESH_INTERVAL: u64 = 30; 40 41 impl VideoRefreshManager { 42 /** 43 * @brief 启动定时刷新 44 * @return 启动成功: true, 失败: false 45 */ 46 pub fn run_video_refresh(&self) -> bool { 47 //设置Manager运行标志 48 let res = self.set_run(); 49 50 //设置成功则开始任务,否则直接返回false 51 if res { 52 //第一次将expire_jiffies设置小一点,使得这次刷新尽快开始,后续的刷新将按照REFRESH_INTERVAL间隔进行 53 let timer = Timer::new(VideoRefreshExecutor::new(), 1); 54 //将新一次定时任务加入队列 55 timer.activate(); 56 } 57 return res; 58 } 59 60 /// 停止定时刷新 61 #[allow(dead_code)] 62 pub fn stop_video_refresh(&self) { 63 self.running.store(false, Ordering::SeqCst); 64 } 65 66 fn set_run(&self) -> bool { 67 let res = self 68 .running 69 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst); 70 return res.is_ok(); 71 } 72 73 /** 74 * VBE帧缓存区的地址重新映射 75 */ 76 fn init_frame_buffer(&self) { 77 info!("Re-mapping VBE frame buffer..."); 78 let mut bp = boot_params().write_irqsave(); 79 let buf_size = bp.screen_info.lfb_size; 80 81 let mmio_guard = mmio_pool().create_mmio(page_align_up(buf_size)).unwrap(); 82 let mmio_guard = Arc::new(mmio_guard); 83 let buf_vaddr = mmio_guard.vaddr(); 84 bp.screen_info.lfb_virt_base = Some(buf_vaddr); 85 86 let mut frame_buffer_info_guard: crate::libs::rwlock::RwLockWriteGuard<ScmBufferInfo> = 87 self.device_buffer.write(); 88 unsafe { frame_buffer_info_guard.set_device_buffer_mmio_guard(mmio_guard.clone()) }; 89 if let ScmBuffer::DeviceBuffer(vaddr) = &mut (frame_buffer_info_guard).buf { 90 *vaddr = buf_vaddr; 91 } 92 // 地址映射 93 let paddr = bp.screen_info.lfb_base; 94 let page_flags: EntryFlags<MMArch> = EntryFlags::new().set_execute(true).set_write(true); 95 96 unsafe { 97 mmio_guard 98 .map_phys_with_flags(paddr, page_align_up(buf_size), page_flags) 99 .expect("Failed to map VBE frame buffer!") 100 }; 101 102 info!("VBE frame buffer successfully Re-mapped!"); 103 } 104 105 /** 106 * @brief 初始化显示模块,需先低级初始化才能高级初始化 107 * @param level 初始化等级 108 * false -> 低级初始化:不使用double buffer 109 * true ->高级初始化:增加double buffer的支持 110 * @return int 111 */ 112 pub fn video_reinitialize(&self, level: bool) -> Result<(), SystemError> { 113 if !level { 114 self.init_frame_buffer(); 115 } else { 116 // 开启屏幕计时刷新 117 assert!(self.run_video_refresh()); 118 } 119 return Ok(()); 120 } 121 122 /** 123 * @brief 设置帧缓冲区刷新目标 124 * 125 * @param buf 126 * @return int 127 */ 128 pub fn set_refresh_target(&self, buf_info: &ScmBufferInfo) -> Result<(), SystemError> { 129 let mut refresh_target = self.refresh_target.write_irqsave(); 130 if let ScmBuffer::DoubleBuffer(double_buffer) = &buf_info.buf { 131 *refresh_target = Some(double_buffer.clone()); 132 return Ok(()); 133 } 134 return Err(SystemError::EINVAL); 135 } 136 #[allow(clippy::type_complexity)] 137 #[allow(dead_code)] 138 pub fn refresh_target(&self) -> RwLockReadGuard<'_, Option<Arc<SpinLock<Box<[u8]>>>>> { 139 let x = self.refresh_target.read(); 140 141 return x; 142 } 143 144 pub fn device_buffer(&self) -> RwLockReadGuard<'_, ScmBufferInfo> { 145 return self.device_buffer.read(); 146 } 147 148 /// 在riscv64平台下暂时不支持 149 #[cfg(target_arch = "riscv64")] 150 pub unsafe fn video_init() -> Result<(), SystemError> { 151 return Err(SystemError::ENOSYS); 152 } 153 154 /// 此函数用于初始化显示驱动,为后续的图形输出做好准备。 155 #[cfg(target_arch = "x86_64")] 156 pub unsafe fn video_init() -> Result<(), SystemError> { 157 use crate::{ 158 arch::driver::video::arch_video_early_init, 159 driver::{ 160 serial::serial8250::send_to_default_serial8250_port, 161 video::fbdev::base::BootTimeVideoType, 162 }, 163 }; 164 165 arch_video_early_init()?; 166 167 let boot_params_guard = boot_params().read(); 168 let screen_info = &boot_params_guard.screen_info; 169 let buf_vaddr = screen_info.lfb_virt_base.unwrap(); 170 171 let buf_flag: ScmBufferFlag; 172 let device_buffer: ScmBufferInfo; 173 174 if screen_info.video_type == BootTimeVideoType::Mda { 175 buf_flag = ScmBufferFlag::SCM_BF_TEXT | ScmBufferFlag::SCM_BF_FB; 176 device_buffer = ScmBufferInfo::new_device_buffer( 177 screen_info.origin_video_cols.into(), 178 screen_info.origin_video_lines.into(), 179 screen_info.lfb_size as u32, 180 screen_info.lfb_depth.into(), 181 buf_flag, 182 buf_vaddr, 183 None, 184 ) 185 .unwrap(); 186 } else { 187 // 图形模式 188 buf_flag = ScmBufferFlag::SCM_BF_PIXEL | ScmBufferFlag::SCM_BF_FB; 189 device_buffer = ScmBufferInfo::new_device_buffer( 190 screen_info.lfb_width, 191 screen_info.lfb_height, 192 screen_info.lfb_size as u32, 193 screen_info.lfb_depth.into(), 194 buf_flag, 195 buf_vaddr, 196 None, 197 ) 198 .unwrap(); 199 } 200 201 let result = Self { 202 device_buffer: RwLock::new(device_buffer), 203 refresh_target: RwLock::new(None), 204 running: AtomicBool::new(false), 205 }; 206 207 __MAMAGER = Some(result); 208 209 let init_text = "Video driver initialized.\n\0"; 210 send_to_default_serial8250_port(init_text.as_bytes()); 211 return Ok(()); 212 } 213 } 214 215 //刷新任务执行器 216 #[derive(Debug)] 217 struct VideoRefreshExecutor; 218 219 impl VideoRefreshExecutor { 220 fn new() -> Box<VideoRefreshExecutor> { 221 return Box::new(VideoRefreshExecutor); 222 } 223 } 224 225 impl TimerFunction for VideoRefreshExecutor { 226 /** 227 * @brief 交给定时器执行的任务,此方法不应手动调用 228 * @return Ok(()) 229 */ 230 #[allow(clippy::type_complexity)] 231 fn run(&mut self) -> Result<(), SystemError> { 232 // 获得Manager 233 let manager = video_refresh_manager(); 234 235 let start_next_refresh = || { 236 //判断是否还需要刷新,若需要则继续分配下一次计时任务,否则不分配 237 if manager.running.load(Ordering::SeqCst) { 238 let timer = Timer::new(VideoRefreshExecutor::new(), REFRESH_INTERVAL); 239 //将新一次定时任务加入队列 240 timer.activate(); 241 } 242 }; 243 244 let mut refresh_target: Option<RwLockReadGuard<'_, Option<Arc<SpinLock<Box<[u8]>>>>>> = 245 None; 246 const TRY_TIMES: i32 = 2; 247 for i in 0..TRY_TIMES { 248 let g = manager.refresh_target.try_read(); 249 if g.is_none() { 250 if i == TRY_TIMES - 1 { 251 start_next_refresh(); 252 return Ok(()); 253 } 254 continue; 255 } 256 refresh_target = Some(g.unwrap()); 257 break; 258 } 259 260 let refresh_target = refresh_target.unwrap(); 261 262 if let ScmBuffer::DeviceBuffer(vaddr) = manager.device_buffer().buf { 263 let p: *mut u8 = vaddr.as_ptr(); 264 let mut target_guard = None; 265 for _ in 0..2 { 266 if let Ok(guard) = refresh_target.as_ref().unwrap().try_lock_irqsave() { 267 target_guard = Some(guard); 268 break; 269 } 270 } 271 if target_guard.is_none() { 272 start_next_refresh(); 273 return Ok(()); 274 } 275 let mut target_guard = target_guard.unwrap(); 276 unsafe { 277 p.copy_from_nonoverlapping( 278 target_guard.as_mut_ptr(), 279 manager.device_buffer().buf_size() as usize, 280 ) 281 } 282 } 283 284 start_next_refresh(); 285 286 return Ok(()); 287 } 288 } 289 290 #[no_mangle] 291 pub unsafe extern "C" fn rs_video_init() -> i32 { 292 return VideoRefreshManager::video_init() 293 .map(|_| 0) 294 .unwrap_or_else(|e| e.to_posix_errno()); 295 } 296