@@ -20,10 +20,15 @@ use core::fmt::Write;
2020
2121use spin:: Once ;
2222
23+ use crate :: arch:: interrupts:: { self , InterruptStack } ;
2324use crate :: arch:: io;
25+ use crate :: userland:: task:: Task ;
2426use crate :: utils:: sync:: Mutex ;
2527
26- static COM_1 : Once < Mutex < SerialPort > > = Once :: new ( ) ;
28+ use alloc:: sync:: Arc ;
29+ use alloc:: vec:: Vec ;
30+
31+ pub static COM_1 : Once < Mutex < SerialPort > > = Once :: new ( ) ;
2732
2833bitflags:: bitflags! {
2934 pub struct InterruptEnable : u8 {
@@ -95,25 +100,35 @@ impl SerialPort {
95100 }
96101
97102 pub fn send_byte ( & mut self , byte : u8 ) {
98- unsafe {
99- match byte {
100- 8 | 0x7F => {
101- self . wait_for_line_status ( LineStatus :: OUTPUT_EMPTY ) ;
103+ match byte {
104+ 8 | 0x7F => {
105+ self . wait_for_line_status ( LineStatus :: OUTPUT_EMPTY ) ;
106+ unsafe {
102107 io:: outb ( self . 0 , 8 ) ;
108+ }
103109
104- self . wait_for_line_status ( LineStatus :: OUTPUT_EMPTY ) ;
110+ self . wait_for_line_status ( LineStatus :: OUTPUT_EMPTY ) ;
111+ unsafe {
105112 io:: outb ( self . 0 , b' ' ) ;
113+ }
106114
107- self . wait_for_line_status ( LineStatus :: OUTPUT_EMPTY ) ;
115+ self . wait_for_line_status ( LineStatus :: OUTPUT_EMPTY ) ;
116+ unsafe {
108117 io:: outb ( self . 0 , 8 ) ;
109118 }
110- _ => {
111- self . wait_for_line_status ( LineStatus :: OUTPUT_EMPTY ) ;
112- io:: outb ( self . 0 , byte)
119+ }
120+ _ => {
121+ self . wait_for_line_status ( LineStatus :: OUTPUT_EMPTY ) ;
122+ unsafe {
123+ io:: outb ( self . 0 , byte) ;
113124 }
114125 }
115126 }
116127 }
128+
129+ pub fn read_byte ( & mut self ) -> u8 {
130+ unsafe { io:: inb ( self . 0 ) }
131+ }
117132}
118133
119134impl fmt:: Write for SerialPort {
@@ -126,15 +141,44 @@ impl fmt::Write for SerialPort {
126141 }
127142}
128143
144+ fn irq_handler ( _stack : & mut InterruptStack ) {
145+ if !unsafe { COM_1 . get_unchecked ( ) }
146+ . lock_irq ( )
147+ . line_status ( )
148+ . contains ( LineStatus :: INPUT_FULL )
149+ {
150+ return ;
151+ }
152+
153+ ( * LISTENERS )
154+ . lock_irq ( )
155+ . iter ( )
156+ . for_each ( |task| task. wake_up ( ) ) ;
157+ }
158+
159+ lazy_static:: lazy_static! {
160+ static ref LISTENERS : Mutex <Vec <Arc <Task >>> = Mutex :: new( Vec :: new( ) ) ;
161+ }
162+
163+ pub fn register_listener ( task : Arc < Task > ) {
164+ ( * LISTENERS ) . lock_irq ( ) . push ( task) ;
165+ }
166+
129167/// Initialize the serial ports if available.
130168pub fn init ( ) {
131169 unsafe {
132- let com_1 = SerialPort :: new ( 0x3F8 ) . init ( ) ;
133-
170+ let com_1 = SerialPort :: new ( 0x3f8 ) . init ( ) ;
134171 COM_1 . call_once ( move || Mutex :: new ( com_1) ) ;
135172 }
136173}
137174
175+ pub fn setup_interrupts ( ) {
176+ let vector = interrupts:: allocate_vector ( ) ;
177+ interrupts:: register_handler ( vector, irq_handler) ;
178+
179+ crate :: arch:: apic:: io_apic_setup_legacy_irq ( 4 , vector, 1 ) ;
180+ }
181+
138182pub macro serial_print( $( $arg: tt) * ) {
139183 crate :: drivers:: uart_16550:: _serial_print ( format_args ! ( $( $arg) * ) )
140184}
@@ -147,6 +191,8 @@ pub macro serial_println {
147191#[ doc( hidden) ]
148192pub fn _serial_print ( args: fmt:: Arguments ) {
149193 if let Some ( c) = COM_1 . get ( ) {
150- c. lock ( ) . write_fmt ( args) . expect ( "failed to write to COM1" )
194+ c. lock_irq ( )
195+ . write_fmt ( args)
196+ . expect ( "failed to write to COM1" )
151197 }
152198}
0 commit comments