|  |  | @ -1,52 +1,46 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | use core::fmt::{Write, Result, Arguments}; |  |  |  | use core::fmt::{Write, Result, Arguments}; | 
			
		
	
		
		
			
				
					
					|  |  |  | use core::ptr::{read_volatile, write_volatile}; |  |  |  | use core::ptr::{read_volatile, write_volatile}; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | struct SerialPort {}; |  |  |  | struct SerialPort { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     base: usize | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | impl SerialPort { |  |  |  | impl SerialPort { | 
			
		
	
		
		
			
				
					
					|  |  |  |     fn new() -> SerialPort { |  |  |  |     fn new() -> SerialPort { | 
			
		
	
		
		
			
				
					
					|  |  |  |         SerialPort { } |  |  |  |         SerialPort { } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | impl Write for SerialPort { |  |  |  |     pub fn init(&mut self, base: usize) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     fn write_str(&mut self, s: &str) -> Result { |  |  |  |         self.base = base; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         for c in s.bytes() { |  |  |  |         // Turn off the FIFO
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             if c == 127 { |  |  |  |         write(self.base + COM_FCR, 0 as u8); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 putchar(8); |  |  |  |         // Set speed; requires DLAB latch
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 putchar(b' '); |  |  |  |         write(self.base + COM_LCR, COM_LCR_DLAB); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 putchar(8); |  |  |  |         write(self.base + COM_DLL, (115200 / 9600) as u8); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             } else { |  |  |  |         write(self.base + COM_DLM, 0 as u8); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 putchar(c); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         Ok(()) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | fn write<T>(addr: usize, content: T) { |  |  |  |         // 8 data bits, 1 stop bit, parity off; turn off DLAB latch
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     let cell = (addr) as *mut T; |  |  |  |         write(self.base + COM_LCR, COM_LCR_WLEN8 & !COM_LCR_DLAB); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     write_volatile(cell, content); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | fn read<T>(addr: usize) -> T { |  |  |  |         // No modem controls
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     let cell = (addr) as *const T; |  |  |  |         write(self.base + COM_MCR, 0 as u8); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     read_volatile(cell); |  |  |  |         // Enable rcv interrupts
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         write(self.base + COM_IER, COM_IER_RDI); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// non-blocking version of putchar()
 |  |  |  |     /// non-blocking version of putchar()
 | 
			
		
	
		
		
			
				
					
					|  |  |  | fn putchar(c: u8) { |  |  |  |     fn putchar(&mut self, c: u8) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     write(COM1 + COM_TX, c); |  |  |  |         write(self.base + COM_TX, c); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// blocking version of getchar()
 |  |  |  |     /// blocking version of getchar()
 | 
			
		
	
		
		
			
				
					
					|  |  |  | pub fn getchar() -> char { |  |  |  |     pub fn getchar(&mut self) -> char { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         loop { |  |  |  |         loop { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (read::<u8>(COM1 + COM_LSR) & COM_LSR_DATA) == 0 { |  |  |  |             if (read::<u8>(self.base + COM_LSR) & COM_LSR_DATA) == 0 { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                 break; |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     let c = read::<u8>(COM1 + COM_RX); |  |  |  |         let c = read::<u8>(self.base + COM_RX); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         match c { |  |  |  |         match c { | 
			
		
	
		
		
			
				
					
					|  |  |  |             255 => '\0',   // null
 |  |  |  |             255 => '\0',   // null
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             c => c as char, |  |  |  |             c => c as char, | 
			
		
	
	
		
		
			
				
					|  |  | @ -54,35 +48,44 @@ pub fn getchar() -> char { | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// non-blocking version of getchar()
 |  |  |  |     /// non-blocking version of getchar()
 | 
			
		
	
		
		
			
				
					
					|  |  |  | pub fn getchar_option() -> Option<char> { |  |  |  |     pub fn getchar_option(&mut self) -> Option<char> { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     match read::<u8>(COM1 + COM_LSR) & COM_LSR_DATA { |  |  |  |         match read::<u8>(self.base + COM_LSR) & COM_LSR_DATA { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             0 => None, |  |  |  |             0 => None, | 
			
		
	
		
		
			
				
					
					|  |  |  |         else => Some(read::<u8>(COM1 + COM_RX) as u8 as char), |  |  |  |             _ => Some(read::<u8>(self.base + COM_RX) as u8 as char), | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | pub fn putfmt(fmt: Arguments) { |  |  |  |     pub fn putfmt(&mut self, fmt: Arguments) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     SerialPort.write_fmt(fmt).unwrap(); |  |  |  |         self.write_fmt(fmt).unwrap(); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | pub fn init() { |  |  |  | } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     // Turn off the FIFO
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     write(COM1 + COM_FCR, 0 as u8); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     // Set speed; requires DLAB latch
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     write(COM1 + COM_LCR, COM_LCR_DLAB); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     write(COM1 + COM_DLL, (115200 / 9600) as u8); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     write(COM1 + COM_DLM, 0 as u8); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // 8 data bits, 1 stop bit, parity off; turn off DLAB latch
 |  |  |  | impl Write for SerialPort { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     write(COM1 + COM_LCR, COM_LCR_WLEN8 & !COM_LCR_DLAB); |  |  |  |     fn write_str(&mut self, s: &str) -> Result { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         for c in s.bytes() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if c == 127 { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 self.putchar(8); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 self.putchar(b' '); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 self.putchar(8); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 self.putchar(c); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         Ok(()) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // No modem controls
 |  |  |  | fn write<T>(addr: usize, content: T) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     write(COM1 + COM_MCR, 0 as u8); |  |  |  |     let cell = (addr) as *mut T; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     // Enable rcv interrupts
 |  |  |  |     write_volatile(cell, content); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     write(COM1 + COM_IER, COM_IER_RDI); |  |  |  | } | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | fn read<T>(addr: usize) -> T { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     let cell = (addr) as *const T; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     read_volatile(cell); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | const COM1          :usize = 0xbf000900; // 16550 Base Address
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | const COM_RX        :usize = 0;   // In:  Receive buffer (DLAB=0)
 |  |  |  | const COM_RX        :usize = 0;   // In:  Receive buffer (DLAB=0)
 | 
			
		
	
		
		
			
				
					
					|  |  |  | const COM_TX        :usize = 0;   // Out: Transmit buffer (DLAB=0)
 |  |  |  | const COM_TX        :usize = 0;   // Out: Transmit buffer (DLAB=0)
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -109,6 +112,6 @@ lazy_static! { | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub static ref SERIAL_PORT: Mutex<SerialPort> = Mutex::new(SerialPort::new()); |  |  |  |     pub static ref SERIAL_PORT: Mutex<SerialPort> = Mutex::new(SerialPort::new()); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | pub fn init() { |  |  |  | pub fn init(base: usize) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     SERIAL_PORT.lock().init(); |  |  |  |     SERIAL_PORT.lock().init(base); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } |