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