@@ -64,6 +64,65 @@ impl SerialPort {
64
64
Self ( base)
65
65
}
66
66
67
+ /// Creates a new serial port interface on the given I/O base port and initializes it.
68
+ ///
69
+ /// This function returns `Err(())` if the serial port fails a simple loopback test.
70
+ ///
71
+ /// This function is unsafe because the caller must ensure that the given base address
72
+ /// really points to a serial port device and that the caller has the necessary rights
73
+ /// to perform the I/O operation.
74
+ pub unsafe fn try_create ( base : u16 ) -> Result < Self , ( ) > {
75
+ let mut port = unsafe { Self :: new ( base) } ;
76
+
77
+ port. init ( ) ;
78
+
79
+ port. loopback_test ( ) ?;
80
+
81
+ Ok ( port)
82
+ }
83
+
84
+ /// Tests that the serial port is working.
85
+ ///
86
+ /// This function temporarily sets the serial port into loopback mode and
87
+ /// performse a simple write and read, checking that the same
88
+ /// value is read. If not this function returns `Err(())`.
89
+ pub fn loopback_test ( & mut self ) -> Result < ( ) , ( ) > {
90
+ self . loopback_test_with ( 0xae )
91
+ }
92
+
93
+ /// Tests that the serial port is working.
94
+ ///
95
+ /// This function temporarily sets the serial port into loopback mode and
96
+ /// performse a simple write of `data` and read, checking that the same
97
+ /// value is read. If not this function returns `Err(())`.
98
+ pub fn loopback_test_with ( & mut self , data : u8 ) -> Result < ( ) , ( ) > {
99
+ unsafe {
100
+ // Disable interrupts
101
+ x86:: io:: outb ( self . port_int_en ( ) , 0x00 ) ;
102
+
103
+ // Set the serial port into loopback mode
104
+ x86:: io:: outb ( self . port_modem_ctrl ( ) , 0x1e ) ;
105
+
106
+ // write `data` to the data port
107
+ x86:: io:: outb ( self . port_data ( ) , data) ;
108
+
109
+ // read back the value we just wrote
110
+ let loopback = x86:: io:: inb ( self . port_data ( ) ) ;
111
+ if loopback != data {
112
+ return Err ( ( ) ) ;
113
+ }
114
+
115
+ // Mark data terminal ready, signal request to send
116
+ // and enable auxilliary output #2 (used as interrupt line for CPU)
117
+ x86:: io:: outb ( self . port_modem_ctrl ( ) , 0x0b ) ;
118
+
119
+ // Enable interrupts
120
+ x86:: io:: outb ( self . port_int_en ( ) , 0x01 ) ;
121
+ }
122
+
123
+ Ok ( ( ) )
124
+ }
125
+
67
126
/// Initializes the serial port.
68
127
///
69
128
/// The default configuration of [38400/8-N-1](https://en.wikipedia.org/wiki/8-N-1) is used.
0 commit comments