xref: /DragonOS/kernel/src/driver/video/mod.rs (revision 08a2ee408498b0db4c76c57b149f1cf047758f3c)
1 use core::{
2     ffi::{c_uint, c_void},
3     mem::MaybeUninit,
4     sync::atomic::{AtomicBool, Ordering},
5 };
6 
7 use alloc::{boxed::Box, sync::Arc};
8 
9 use crate::{
10     arch::MMArch,
11     driver::tty::serial::serial8250::send_to_default_serial8250_port,
12     include::bindings::bindings::{
13         multiboot2_get_Framebuffer_info, multiboot2_iter, multiboot_tag_framebuffer_info_t,
14         FRAME_BUFFER_MAPPING_OFFSET, SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE,
15     },
16     kinfo,
17     libs::{
18         align::page_align_up,
19         lib_ui::screen_manager::{ScmBuffer, ScmBufferFlag, ScmBufferInfo},
20         rwlock::{RwLock, RwLockReadGuard},
21         spinlock::SpinLock,
22     },
23     mm::{
24         allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper,
25         no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
26     },
27     syscall::SystemError,
28     time::timer::{Timer, TimerFunction},
29 };
30 
31 pub mod fbdev;
32 
33 static mut __MAMAGER: Option<VideoRefreshManager> = None;
34 
35 pub fn video_refresh_manager() -> &'static VideoRefreshManager {
36     return unsafe {
37         &__MAMAGER
38             .as_ref()
39             .expect("Video refresh manager has not been initialized yet!")
40     };
41 }
42 
43 ///管理显示刷新变量的结构体
44 pub struct VideoRefreshManager {
45     device_buffer: RwLock<ScmBufferInfo>,
46     fb_info: multiboot_tag_framebuffer_info_t,
47     refresh_target: RwLock<Option<Arc<SpinLock<Box<[u32]>>>>>,
48     running: AtomicBool,
49 }
50 
51 const REFRESH_INTERVAL: u64 = 30;
52 
53 impl VideoRefreshManager {
54     /**
55      * @brief 启动定时刷新
56      * @return 启动成功: true, 失败: false
57      */
58     pub fn run_video_refresh(&self) -> bool {
59         //设置Manager运行标志
60         let res = self.set_run();
61 
62         //设置成功则开始任务,否则直接返回false
63         if res {
64             //第一次将expire_jiffies设置小一点,使得这次刷新尽快开始,后续的刷新将按照REFRESH_INTERVAL间隔进行
65             let timer = Timer::new(VideoRefreshExecutor::new(), 1);
66             //将新一次定时任务加入队列
67             timer.activate();
68         }
69         return res;
70     }
71 
72     /// 停止定时刷新
73     #[allow(dead_code)]
74     pub fn stop_video_refresh(&self) {
75         self.running.store(false, Ordering::SeqCst);
76     }
77 
78     fn set_run(&self) -> bool {
79         let res = self
80             .running
81             .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst);
82         if res.is_ok() {
83             return true;
84         } else {
85             return false;
86         }
87     }
88 
89     /**
90      * @brief VBE帧缓存区的地址重新映射
91      * 将帧缓存区映射到地址SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE处
92      */
93     fn init_frame_buffer(&self) {
94         kinfo!("Re-mapping VBE frame buffer...");
95         let buf_vaddr = VirtAddr::new(
96             SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE as usize + FRAME_BUFFER_MAPPING_OFFSET as usize,
97         );
98 
99         let mut frame_buffer_info_graud = self.device_buffer.write();
100         if let ScmBuffer::DeviceBuffer(vaddr) = &mut (frame_buffer_info_graud).buf {
101             *vaddr = buf_vaddr;
102         }
103 
104         // 地址映射
105         let mut paddr = PhysAddr::new(self.fb_info.framebuffer_addr as usize);
106         let count = PageFrameCount::new(
107             page_align_up(frame_buffer_info_graud.buf_size()) / MMArch::PAGE_SIZE,
108         );
109         let page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true);
110 
111         let mut kernel_mapper = KernelMapper::lock();
112         let mut kernel_mapper = kernel_mapper.as_mut();
113         assert!(kernel_mapper.is_some());
114         let mut vaddr = buf_vaddr;
115         unsafe {
116             for _ in 0..count.data() {
117                 let flusher = kernel_mapper
118                     .as_mut()
119                     .unwrap()
120                     .map_phys(vaddr, paddr, page_flags)
121                     .unwrap();
122 
123                 flusher.flush();
124                 vaddr += MMArch::PAGE_SIZE;
125                 paddr += MMArch::PAGE_SIZE;
126             }
127         }
128 
129         kinfo!("VBE frame buffer successfully Re-mapped!");
130     }
131 
132     /**
133      * @brief 初始化显示模块,需先低级初始化才能高级初始化
134      * @param level 初始化等级
135      * false -> 低级初始化:不使用double buffer
136      * true ->高级初始化:增加double buffer的支持
137      * @return int
138      */
139     pub fn video_reinitialize(&self, level: bool) -> Result<(), SystemError> {
140         if !level {
141             self.init_frame_buffer();
142         } else {
143             // 开启屏幕计时刷新
144             assert!(self.run_video_refresh());
145         }
146         return Ok(());
147     }
148 
149     /**
150      * @brief 设置帧缓冲区刷新目标
151      *
152      * @param buf
153      * @return int
154      */
155     pub fn set_refresh_target(&self, buf_info: &ScmBufferInfo) -> Result<(), SystemError> {
156         let mut refresh_target = self.refresh_target.write_irqsave();
157         if let ScmBuffer::DoubleBuffer(double_buffer) = &buf_info.buf {
158             *refresh_target = Some(double_buffer.clone());
159             return Ok(());
160         }
161         return Err(SystemError::EINVAL);
162     }
163 
164     #[allow(dead_code)]
165     pub fn refresh_target(&self) -> RwLockReadGuard<'_, Option<Arc<SpinLock<Box<[u32]>>>>> {
166         let x = self.refresh_target.read();
167 
168         return x;
169     }
170 
171     pub fn device_buffer(&self) -> RwLockReadGuard<'_, ScmBufferInfo> {
172         return self.device_buffer.read();
173     }
174 
175     /// 在riscv64平台下暂时不支持
176     #[cfg(target_arch = "riscv64")]
177     pub unsafe fn video_init() -> Result<(), SystemError> {
178         return Err(SystemError::ENOSYS);
179     }
180 
181     /// 此函数用于初始化显示驱动,为后续的图形输出做好准备。
182     #[cfg(not(target_arch = "riscv64"))]
183     pub unsafe fn video_init() -> Result<(), SystemError> {
184         static INIT: AtomicBool = AtomicBool::new(false);
185 
186         if INIT
187             .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
188             .is_err()
189         {
190             panic!("Try to init video twice!");
191         }
192 
193         let mut _reserved: u32 = 0;
194 
195         let mut fb_info: MaybeUninit<multiboot_tag_framebuffer_info_t> = MaybeUninit::uninit();
196         //从multiboot2中读取帧缓冲区信息至fb_info
197         multiboot2_iter(
198             Some(multiboot2_get_Framebuffer_info),
199             fb_info.as_mut_ptr() as usize as *mut c_void,
200             &mut _reserved as *mut c_uint,
201         );
202         fb_info.assume_init();
203         let fb_info: multiboot_tag_framebuffer_info_t = core::mem::transmute(fb_info);
204 
205         let width = fb_info.framebuffer_width;
206         let height = fb_info.framebuffer_height;
207 
208         //初始化帧缓冲区信息结构体
209         let (bit_depth, flags) = if fb_info.framebuffer_type == 2 {
210             //当type=2时,width与height用字符数表示,故depth=8
211 
212             (8u32, ScmBufferFlag::SCM_BF_TEXT | ScmBufferFlag::SCM_BF_FB)
213         } else {
214             //否则为图像模式,depth应参照帧缓冲区信息里面的每个像素的位数
215             (
216                 fb_info.framebuffer_bpp as u32,
217                 ScmBufferFlag::SCM_BF_PIXEL | ScmBufferFlag::SCM_BF_FB,
218             )
219         };
220 
221         let buf_vaddr = VirtAddr::new(0xffff800003200000);
222         let device_buffer = ScmBufferInfo::new_device_buffer(
223             width,
224             height,
225             width * height * ((bit_depth + 7) / 8),
226             bit_depth,
227             flags,
228             buf_vaddr,
229         )
230         .unwrap();
231 
232         let init_text = "Video driver to map.\n\0";
233         send_to_default_serial8250_port(init_text.as_bytes());
234 
235         //地址映射
236         let paddr = PhysAddr::new(fb_info.framebuffer_addr as usize);
237         let count = PageFrameCount::new(
238             page_align_up(device_buffer.buf_size() as usize) / MMArch::PAGE_SIZE,
239         );
240         pseudo_map_phys(buf_vaddr, paddr, count);
241 
242         let result = Self {
243             fb_info,
244             device_buffer: RwLock::new(device_buffer),
245             refresh_target: RwLock::new(None),
246             running: AtomicBool::new(false),
247         };
248 
249         __MAMAGER = Some(result);
250 
251         let init_text = "Video driver initialized.\n\0";
252         send_to_default_serial8250_port(init_text.as_bytes());
253         return Ok(());
254     }
255 }
256 
257 //刷新任务执行器
258 #[derive(Debug)]
259 struct VideoRefreshExecutor;
260 
261 impl VideoRefreshExecutor {
262     fn new() -> Box<VideoRefreshExecutor> {
263         return Box::new(VideoRefreshExecutor);
264     }
265 }
266 
267 impl TimerFunction for VideoRefreshExecutor {
268     /**
269      * @brief 交给定时器执行的任务,此方法不应手动调用
270      * @return Ok(())
271      */
272     fn run(&mut self) -> Result<(), SystemError> {
273         // 获得Manager
274         let manager = video_refresh_manager();
275 
276         let start_next_refresh = || {
277             //判断是否还需要刷新,若需要则继续分配下一次计时任务,否则不分配
278             if manager.running.load(Ordering::SeqCst) {
279                 let timer = Timer::new(VideoRefreshExecutor::new(), REFRESH_INTERVAL);
280                 //将新一次定时任务加入队列
281                 timer.activate();
282             }
283         };
284 
285         let mut refresh_target: Option<RwLockReadGuard<'_, Option<Arc<SpinLock<Box<[u32]>>>>>> =
286             None;
287         const TRY_TIMES: i32 = 2;
288         for i in 0..TRY_TIMES {
289             let g = manager.refresh_target.try_read();
290             if g.is_none() {
291                 if i == TRY_TIMES - 1 {
292                     start_next_refresh();
293                     return Ok(());
294                 }
295                 continue;
296             }
297             refresh_target = Some(g.unwrap());
298             break;
299         }
300 
301         let refresh_target = refresh_target.unwrap();
302 
303         if let ScmBuffer::DeviceBuffer(vaddr) = manager.device_buffer().buf {
304             let p = vaddr.as_ptr() as *mut u8;
305             let mut target_guard = None;
306             for _ in 0..2 {
307                 if let Ok(guard) = refresh_target.as_ref().unwrap().try_lock_irqsave() {
308                     target_guard = Some(guard);
309                     break;
310                 }
311             }
312             if target_guard.is_none() {
313                 start_next_refresh();
314                 return Ok(());
315             }
316             let mut target_guard = target_guard.unwrap();
317             unsafe {
318                 p.copy_from_nonoverlapping(
319                     target_guard.as_mut_ptr() as *mut u8,
320                     manager.device_buffer().buf_size() as usize,
321                 )
322             }
323         }
324 
325         start_next_refresh();
326 
327         return Ok(());
328     }
329 }
330 
331 #[no_mangle]
332 pub unsafe extern "C" fn rs_video_init() -> i32 {
333     return VideoRefreshManager::video_init()
334         .map(|_| 0)
335         .unwrap_or_else(|e| e.to_posix_errno());
336 }
337