1 //! PIO的串口驱动
2
3 use core::{
4 hint::spin_loop,
5 sync::atomic::{AtomicBool, Ordering},
6 };
7
8 use alloc::{
9 string::ToString,
10 sync::{Arc, Weak},
11 };
12
13 use crate::{
14 arch::{driver::apic::ioapic::IoApic, io::PortIOArch, CurrentPortIOArch},
15 driver::{
16 base::device::{
17 device_number::{DeviceNumber, Major},
18 DeviceId,
19 },
20 serial::{AtomicBaudRate, BaudRate, DivisorFraction, UartPort},
21 tty::{
22 console::ConsoleSwitch,
23 kthread::send_to_tty_refresh_thread,
24 termios::WindowSize,
25 tty_core::{TtyCore, TtyCoreData},
26 tty_driver::{TtyDriver, TtyDriverManager, TtyOperation},
27 virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData, VirtConsole},
28 },
29 video::console::dummycon::dummy_console,
30 },
31 exception::{
32 irqdata::IrqHandlerData,
33 irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn},
34 manage::irq_manager,
35 IrqNumber,
36 },
37 libs::{rwlock::RwLock, spinlock::SpinLock},
38 };
39 use system_error::SystemError;
40
41 use super::{Serial8250ISADevices, Serial8250ISADriver, Serial8250Manager, Serial8250Port};
42
43 static mut PIO_PORTS: [Option<Serial8250PIOPort>; 8] =
44 [None, None, None, None, None, None, None, None];
45
46 const SERIAL_8250_PIO_IRQ: IrqNumber = IrqNumber::new(IoApic::VECTOR_BASE as u32 + 4);
47
48 impl Serial8250Manager {
49 #[allow(static_mut_refs)]
bind_pio_ports( &self, uart_driver: &Arc<Serial8250ISADriver>, devs: &Arc<Serial8250ISADevices>, )50 pub(super) fn bind_pio_ports(
51 &self,
52 uart_driver: &Arc<Serial8250ISADriver>,
53 devs: &Arc<Serial8250ISADevices>,
54 ) {
55 for port in unsafe { &PIO_PORTS }.iter().flatten() {
56 port.set_device(Some(devs));
57 self.uart_add_one_port(uart_driver, port).ok();
58 }
59 }
60 }
61
62 macro_rules! init_port {
63 ($port_num:expr) => {
64 unsafe {
65 let port = Serial8250PIOPort::new(
66 match $port_num {
67 1 => Serial8250PortBase::COM1,
68 2 => Serial8250PortBase::COM2,
69 3 => Serial8250PortBase::COM3,
70 4 => Serial8250PortBase::COM4,
71 5 => Serial8250PortBase::COM5,
72 6 => Serial8250PortBase::COM6,
73 7 => Serial8250PortBase::COM7,
74 8 => Serial8250PortBase::COM8,
75 _ => panic!("invalid port number"),
76 },
77 crate::driver::serial::SERIAL_BAUDRATE,
78 );
79 if let Ok(port) = port {
80 if port.init().is_ok() {
81 PIO_PORTS[$port_num - 1] = Some(port);
82 true
83 } else {
84 false
85 }
86 } else {
87 false
88 }
89 }
90 };
91 }
92
93 /// 在内存管理初始化之前,初始化串口设备
serial8250_pio_port_early_init() -> Result<(), SystemError>94 pub(super) fn serial8250_pio_port_early_init() -> Result<(), SystemError> {
95 for i in 1..=8 {
96 init_port!(i);
97 }
98
99 return Ok(());
100 }
101
102 #[derive(Debug)]
103 pub struct Serial8250PIOPort {
104 iobase: Serial8250PortBase,
105 baudrate: AtomicBaudRate,
106 initialized: AtomicBool,
107 inner: RwLock<Serial8250PIOPortInner>,
108 }
109
110 impl Serial8250PIOPort {
111 const SERIAL8250PIO_MAX_BAUD_RATE: BaudRate = BaudRate::new(115200);
new(iobase: Serial8250PortBase, baudrate: BaudRate) -> Result<Self, SystemError>112 pub fn new(iobase: Serial8250PortBase, baudrate: BaudRate) -> Result<Self, SystemError> {
113 let r = Self {
114 iobase,
115 baudrate: AtomicBaudRate::new(baudrate),
116 initialized: AtomicBool::new(false),
117 inner: RwLock::new(Serial8250PIOPortInner::new()),
118 };
119
120 r.check_baudrate(&baudrate)?;
121
122 return Ok(r);
123 }
124
init(&self) -> Result<(), SystemError>125 pub fn init(&self) -> Result<(), SystemError> {
126 let r = self
127 .initialized
128 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst);
129 if r.is_err() {
130 // 已经初始化
131 return Ok(());
132 }
133
134 let port = self.iobase as u16;
135 unsafe {
136 CurrentPortIOArch::out8(port + 1, 0x00); // Disable all interrupts
137 self.set_divisor(self.baudrate.load(Ordering::SeqCst))
138 .unwrap(); // Set baud rate
139
140 CurrentPortIOArch::out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
141 CurrentPortIOArch::out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control,因此不需要置位RTS/DSR)
142 CurrentPortIOArch::out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
143 CurrentPortIOArch::out8(port, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
144
145 // Check if serial is faulty (i.e: not same byte as sent)
146 if CurrentPortIOArch::in8(port) != 0xAE {
147 self.initialized.store(false, Ordering::SeqCst);
148 return Err(SystemError::ENODEV);
149 }
150
151 // If serial is not faulty set it in normal operation mode
152 // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
153 CurrentPortIOArch::out8(port + 4, 0x0b);
154
155 CurrentPortIOArch::out8(port + 1, 0x01); // Enable interrupts
156 }
157
158 return Ok(());
159 /*
160 Notice that the initialization code above writes to [PORT + 1]
161 twice with different values. This is once to write to the Divisor
162 register along with [PORT + 0] and once to write to the Interrupt
163 register as detailed in the previous section.
164 The second write to the Line Control register [PORT + 3]
165 clears the DLAB again as well as setting various other bits.
166 */
167 }
168
check_baudrate(&self, baudrate: &BaudRate) -> Result<(), SystemError>169 const fn check_baudrate(&self, baudrate: &BaudRate) -> Result<(), SystemError> {
170 // 错误的比特率
171 if baudrate.data() > Self::SERIAL8250PIO_MAX_BAUD_RATE.data()
172 || Self::SERIAL8250PIO_MAX_BAUD_RATE.data() % baudrate.data() != 0
173 {
174 return Err(SystemError::EINVAL);
175 }
176
177 return Ok(());
178 }
179
180 #[allow(dead_code)]
serial_received(&self) -> bool181 fn serial_received(&self) -> bool {
182 self.serial_in(5) & 1 != 0
183 }
184
is_transmit_empty(&self) -> bool185 fn is_transmit_empty(&self) -> bool {
186 self.serial_in(5) & 0x20 != 0
187 }
188
189 /// 发送字节
190 ///
191 /// ## 参数
192 ///
193 /// - `s`:待发送的字节
send_bytes(&self, s: &[u8])194 fn send_bytes(&self, s: &[u8]) {
195 while !self.is_transmit_empty() {
196 spin_loop();
197 }
198
199 for c in s {
200 self.serial_out(0, (*c).into());
201 }
202 }
203
204 /// 读取一个字节,如果没有数据则返回None
read_one_byte(&self) -> Option<u8>205 fn read_one_byte(&self) -> Option<u8> {
206 if !self.serial_received() {
207 return None;
208 }
209 return Some(self.serial_in(0) as u8);
210 }
211 }
212
213 impl Serial8250Port for Serial8250PIOPort {
device(&self) -> Option<Arc<Serial8250ISADevices>>214 fn device(&self) -> Option<Arc<Serial8250ISADevices>> {
215 self.inner.read().device()
216 }
217
set_device(&self, device: Option<&Arc<Serial8250ISADevices>>)218 fn set_device(&self, device: Option<&Arc<Serial8250ISADevices>>) {
219 self.inner.write().set_device(device);
220 }
221 }
222
223 impl UartPort for Serial8250PIOPort {
serial_in(&self, offset: u32) -> u32224 fn serial_in(&self, offset: u32) -> u32 {
225 unsafe { CurrentPortIOArch::in8(self.iobase as u16 + offset as u16).into() }
226 }
227
serial_out(&self, offset: u32, value: u32)228 fn serial_out(&self, offset: u32, value: u32) {
229 // warning: pio的串口只能写入8位,因此这里丢弃高24位
230 unsafe { CurrentPortIOArch::out8(self.iobase as u16 + offset as u16, value as u8) }
231 }
232
divisor(&self, baud: BaudRate) -> (u32, DivisorFraction)233 fn divisor(&self, baud: BaudRate) -> (u32, DivisorFraction) {
234 let divisor = Self::SERIAL8250PIO_MAX_BAUD_RATE.data() / baud.data();
235 return (divisor, DivisorFraction::new(0));
236 }
237
set_divisor(&self, baud: BaudRate) -> Result<(), SystemError>238 fn set_divisor(&self, baud: BaudRate) -> Result<(), SystemError> {
239 self.check_baudrate(&baud)?;
240
241 let port = self.iobase as u16;
242 unsafe {
243 CurrentPortIOArch::out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
244
245 let divisor = self.divisor(baud).0;
246
247 CurrentPortIOArch::out8(port, (divisor & 0xff) as u8); // Set divisor (lo byte)
248 CurrentPortIOArch::out8(port + 1, ((divisor >> 8) & 0xff) as u8); // (hi byte)
249 CurrentPortIOArch::out8(port + 3, 0x03); // 8 bits, no parity, one stop bit
250 }
251
252 self.baudrate.store(baud, Ordering::SeqCst);
253
254 return Ok(());
255 }
256
startup(&self) -> Result<(), SystemError>257 fn startup(&self) -> Result<(), SystemError> {
258 todo!("serial8250_pio::startup")
259 }
260
shutdown(&self)261 fn shutdown(&self) {
262 todo!("serial8250_pio::shutdown")
263 }
264
baud_rate(&self) -> Option<BaudRate>265 fn baud_rate(&self) -> Option<BaudRate> {
266 Some(self.baudrate.load(Ordering::SeqCst))
267 }
268
handle_irq(&self) -> Result<(), SystemError>269 fn handle_irq(&self) -> Result<(), SystemError> {
270 let mut buf = [0; 8];
271 let mut index = 0;
272
273 // Read up to the size of the buffer
274 while index < buf.len() {
275 if let Some(c) = self.read_one_byte() {
276 buf[index] = c;
277 index += 1;
278 } else {
279 break; // No more bytes to read
280 }
281 }
282
283 send_to_tty_refresh_thread(&buf[0..index]);
284 Ok(())
285 }
286
iobase(&self) -> Option<usize>287 fn iobase(&self) -> Option<usize> {
288 Some(self.iobase as usize)
289 }
290 }
291
292 #[derive(Debug)]
293 struct Serial8250PIOPortInner {
294 /// 当前端口绑定的设备
295 ///
296 /// ps: 存储weak以避免循环引用
297 device: Option<Weak<Serial8250ISADevices>>,
298 }
299
300 impl Serial8250PIOPortInner {
new() -> Self301 pub const fn new() -> Self {
302 Self { device: None }
303 }
304
305 #[allow(dead_code)]
device(&self) -> Option<Arc<Serial8250ISADevices>>306 pub fn device(&self) -> Option<Arc<Serial8250ISADevices>> {
307 if let Some(device) = self.device.as_ref() {
308 return device.upgrade();
309 }
310 return None;
311 }
312
set_device(&mut self, device: Option<&Arc<Serial8250ISADevices>>)313 fn set_device(&mut self, device: Option<&Arc<Serial8250ISADevices>>) {
314 self.device = device.map(Arc::downgrade);
315 }
316 }
317
318 #[allow(dead_code)]
319 #[repr(u16)]
320 #[derive(Clone, Debug, Copy)]
321 pub enum Serial8250PortBase {
322 COM1 = 0x3f8,
323 COM2 = 0x2f8,
324 COM3 = 0x3e8,
325 COM4 = 0x2e8,
326 COM5 = 0x5f8,
327 COM6 = 0x4f8,
328 COM7 = 0x5e8,
329 COM8 = 0x4e8,
330 }
331
332 /// 临时函数,用于向COM1发送数据
send_to_default_serial8250_pio_port(s: &[u8])333 pub fn send_to_default_serial8250_pio_port(s: &[u8]) {
334 if let Some(port) = unsafe { PIO_PORTS[0].as_ref() } {
335 port.send_bytes(s);
336 }
337 }
338
339 #[derive(Debug)]
340 pub(super) struct Serial8250PIOTtyDriverInner;
341
342 impl Serial8250PIOTtyDriverInner {
new() -> Self343 pub fn new() -> Self {
344 Self
345 }
346
do_install( &self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>, vc: Arc<VirtConsole>, ) -> Result<(), SystemError>347 fn do_install(
348 &self,
349 driver: Arc<TtyDriver>,
350 tty: Arc<TtyCore>,
351 vc: Arc<VirtConsole>,
352 ) -> Result<(), SystemError> {
353 driver.standard_install(tty.clone())?;
354 vc.port().setup_internal_tty(Arc::downgrade(&tty));
355 tty.set_port(vc.port());
356 vc.devfs_setup()?;
357
358 Ok(())
359 }
360 }
361
362 impl TtyOperation for Serial8250PIOTtyDriverInner {
open(&self, _tty: &TtyCoreData) -> Result<(), SystemError>363 fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> {
364 Ok(())
365 }
366
write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError>367 fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result<usize, SystemError> {
368 let index = tty.index();
369 if tty.index() >= unsafe { PIO_PORTS.len() } {
370 return Err(SystemError::ENODEV);
371 }
372 let pio_port = unsafe { PIO_PORTS[index].as_ref() }.ok_or(SystemError::ENODEV)?;
373 pio_port.send_bytes(&buf[..nr]);
374
375 Ok(nr)
376 }
377
flush_chars(&self, _tty: &TtyCoreData)378 fn flush_chars(&self, _tty: &TtyCoreData) {}
379
put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError>380 fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> {
381 self.write(tty, &[ch], 1).map(|_| ())
382 }
383
ioctl(&self, _tty: Arc<TtyCore>, _cmd: u32, _arg: usize) -> Result<(), SystemError>384 fn ioctl(&self, _tty: Arc<TtyCore>, _cmd: u32, _arg: usize) -> Result<(), SystemError> {
385 Err(SystemError::ENOIOCTLCMD)
386 }
387
close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError>388 fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
389 Ok(())
390 }
391
resize(&self, tty: Arc<TtyCore>, winsize: WindowSize) -> Result<(), SystemError>392 fn resize(&self, tty: Arc<TtyCore>, winsize: WindowSize) -> Result<(), SystemError> {
393 *tty.core().window_size_write() = winsize;
394 Ok(())
395 }
396
install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError>397 fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> Result<(), SystemError> {
398 if tty.core().index() >= unsafe { PIO_PORTS.len() } {
399 return Err(SystemError::ENODEV);
400 }
401
402 *tty.core().window_size_write() = WindowSize::DEFAULT;
403 let vc_data = Arc::new(SpinLock::new(VirtualConsoleData::new(usize::MAX)));
404 let mut vc_data_guard = vc_data.lock_irqsave();
405 vc_data_guard.set_driver_funcs(Arc::downgrade(&dummy_console()) as Weak<dyn ConsoleSwitch>);
406 vc_data_guard.init(
407 Some(tty.core().window_size().row.into()),
408 Some(tty.core().window_size().col.into()),
409 true,
410 );
411 drop(vc_data_guard);
412 let vc = VirtConsole::new(Some(vc_data));
413 let vc_index = vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?;
414 self.do_install(driver, tty, vc.clone()).inspect_err(|_| {
415 vc_manager().free(vc_index);
416 })?;
417
418 Ok(())
419 }
420 }
421
serial_8250_pio_register_tty_devices() -> Result<(), SystemError>422 pub(super) fn serial_8250_pio_register_tty_devices() -> Result<(), SystemError> {
423 let (_, driver) = TtyDriverManager::lookup_tty_driver(DeviceNumber::new(
424 Major::TTY_MAJOR,
425 Serial8250Manager::TTY_SERIAL_MINOR_START,
426 ))
427 .ok_or(SystemError::ENODEV)?;
428
429 for (i, port) in unsafe { PIO_PORTS.iter() }.enumerate() {
430 if let Some(port) = port {
431 let core = driver.init_tty_device(Some(i)).inspect_err(|_| {
432 log::error!(
433 "failed to init tty device for serial 8250 pio port {}, port iobase: {:?}",
434 i,
435 port.iobase
436 );
437 })?;
438 core.resize( core.clone(), WindowSize::DEFAULT)
439 .inspect_err(|_| {
440 log::error!(
441 "failed to resize tty device for serial 8250 pio port {}, port iobase: {:?}",
442 i,
443 port.iobase
444 );
445 })?;
446 }
447 }
448
449 irq_manager()
450 .request_irq(
451 SERIAL_8250_PIO_IRQ,
452 "serial8250_pio".to_string(),
453 &Serial8250IrqHandler,
454 IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_TRIGGER_RISING,
455 Some(DeviceId::new(Some("serial8250_pio"), None).unwrap()),
456 )
457 .inspect_err(|e| {
458 log::error!("failed to request irq for serial 8250 pio: {:?}", e);
459 })?;
460
461 Ok(())
462 }
463
464 #[derive(Debug)]
465 struct Serial8250IrqHandler;
466
467 impl IrqHandler for Serial8250IrqHandler {
handle( &self, _irq: IrqNumber, _static_data: Option<&dyn IrqHandlerData>, _dynamic_data: Option<Arc<dyn IrqHandlerData>>, ) -> Result<IrqReturn, SystemError>468 fn handle(
469 &self,
470 _irq: IrqNumber,
471 _static_data: Option<&dyn IrqHandlerData>,
472 _dynamic_data: Option<Arc<dyn IrqHandlerData>>,
473 ) -> Result<IrqReturn, SystemError> {
474 for port in unsafe { PIO_PORTS.iter() }.flatten() {
475 port.handle_irq()?;
476 }
477
478 Ok(IrqReturn::Handled)
479 }
480 }
481