serial8250_pio.rs 14 KB

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