1- use crate :: error:: Result ;
1+ #![ deny( missing_docs) ]
2+
3+ //! # Physical PS2 Support
4+ //!
5+ //! This module provides support for interacting with a physical
6+ //! PS2 keyboard controller.
7+
8+ use crate :: error:: { Error , Result } ;
29use bitflags:: bitflags;
310use x86:: io:: { inb, outb} ;
411
@@ -7,7 +14,7 @@ const PS2_STATUS_PORT: u16 = 0x64;
714const PS2_COMMAND_PORT : u16 = 0x64 ;
815
916bitflags ! {
10- pub struct Ps2StatusFlags : u8 {
17+ struct Ps2StatusFlags : u8 {
1118 const OUTPUT_BUFFER_FULL = 1 << 0 ;
1219 const INPUT_BUFFER_FULL = 1 << 1 ;
1320 const SELF_TEST_PASS = 1 << 2 ;
@@ -20,7 +27,7 @@ bitflags! {
2027}
2128
2229bitflags ! {
23- pub struct Ps2ConfigurationFlags : u8 {
30+ struct Ps2ConfigurationFlags : u8 {
2431 const FIRST_PORT_INTERRUPT = 1 << 0 ;
2532 const SECOND_PORT_INTERRUPT = 1 << 1 ;
2633 const SYSTEM_POST = 1 << 2 ;
@@ -48,101 +55,123 @@ enum Command {
4855 WriteSecond = 0xD4 ,
4956}
5057
58+ /// A representation of a physical PS2 keyboard controller
59+ ///
60+ /// Note that currently only one instance of this type should be created.
5161pub struct Ps2Controller ;
62+
5263impl Ps2Controller {
53- pub fn init ( ) -> Result < ( ) > {
64+ /// Create a new `Ps2Controller` and prepare the controller
65+ pub fn init ( ) -> Result < Self > {
5466 // See https://wiki.osdev.org/%228042%22_PS/2_Controller#Initialising_the_PS.2F2_Controller
55- Self :: flush_read ( "init start" ) ;
56- Self :: write_command_port ( Command :: DisableFirst ) ;
57- Self :: write_command_port ( Command :: DisableSecond ) ;
58- Self :: flush_read ( "disable" ) ;
67+ let mut controller = Ps2Controller { } ;
68+ controller. flush_read ( "init start" ) ;
69+ controller. write_command_port ( Command :: DisableFirst ) ;
70+ controller. write_command_port ( Command :: DisableSecond ) ;
71+ controller. flush_read ( "disable" ) ;
5972
6073 {
61- let mut config = Self :: read_configuration ( ) ;
74+ let mut config = controller . read_configuration ( ) ;
6275 config. insert ( Ps2ConfigurationFlags :: FIRST_PORT_CLOCK_DISABLED ) ;
6376 config. insert ( Ps2ConfigurationFlags :: SECOND_PORT_CLOCK_DISABLED ) ;
6477 config. remove ( Ps2ConfigurationFlags :: FIRST_PORT_TRANSLATION ) ;
6578 config. remove ( Ps2ConfigurationFlags :: FIRST_PORT_INTERRUPT ) ;
6679 config. remove ( Ps2ConfigurationFlags :: SECOND_PORT_INTERRUPT ) ;
67- Self :: write_configuration ( config) ;
80+ controller. write_configuration ( config) ;
81+ }
82+
83+ controller. write_command_port ( Command :: TestController ) ;
84+
85+ if controller. read_data_port ( ) != 0x55 {
86+ return Err ( Error :: DeviceError (
87+ "Failed to init Ps2Controller" . into ( ) ,
88+ ) ) ;
6889 }
6990
70- Self :: write_command_port ( Command :: TestController ) ;
71- //TODO: these should return error
72- assert_eq ! ( Self :: read_data_port ( ) , 0x55 ) ;
91+ controller . write_command_port ( Command :: EnableFirst ) ;
92+ controller . write_command_port ( Command :: EnableSecond ) ;
93+ controller . flush_read ( "enable" ) ;
7394
74- Self :: write_command_port ( Command :: EnableFirst ) ;
75- Self :: write_command_port ( Command :: EnableSecond ) ;
76- Self :: flush_read ( "enable" ) ;
95+ controller. write_data_port ( 0xff ) ;
7796
78- Self :: write_data_port ( 0xff ) ;
79- //TODO: these should return error
80- assert_eq ! ( Self :: read_data_port( ) , 0xFA ) ;
81- assert_eq ! ( Self :: read_data_port( ) , 0xAA ) ;
97+ if controller. read_data_port ( ) != 0xFA {
98+ return Err ( Error :: DeviceError (
99+ "Failed to init Ps2Controller" . into ( ) ,
100+ ) ) ;
101+ }
102+ if controller. read_data_port ( ) != 0xAA {
103+ return Err ( Error :: DeviceError (
104+ "Failed to init Ps2Controller" . into ( ) ,
105+ ) ) ;
106+ }
82107
83- Self :: flush_read ( "defaults" ) ;
108+ controller . flush_read ( "defaults" ) ;
84109
85110 {
86- let mut config = Self :: read_configuration ( ) ;
111+ let mut config = controller . read_configuration ( ) ;
87112 config. remove ( Ps2ConfigurationFlags :: FIRST_PORT_CLOCK_DISABLED ) ;
88113 config. remove ( Ps2ConfigurationFlags :: SECOND_PORT_CLOCK_DISABLED ) ;
89114 config. insert ( Ps2ConfigurationFlags :: FIRST_PORT_TRANSLATION ) ;
90115 config. insert ( Ps2ConfigurationFlags :: FIRST_PORT_INTERRUPT ) ;
91116 config. insert ( Ps2ConfigurationFlags :: SECOND_PORT_INTERRUPT ) ;
92- Self :: write_configuration ( config) ;
117+ controller . write_configuration ( config) ;
93118 }
94119
95- Self :: flush_read ( "init finished" ) ;
96- Ok ( ( ) )
120+ controller . flush_read ( "init finished" ) ;
121+ Ok ( controller )
97122 }
98123
99- fn flush_read ( message : & str ) {
100- while Self :: read_status_port ( )
124+ fn flush_read ( & mut self , message : & str ) {
125+ while self
126+ . read_status_port ( )
101127 . contains ( Ps2StatusFlags :: OUTPUT_BUFFER_FULL )
102128 {
103- info ! ( "ps2: flush {}: {:X}" , message, Self :: read_data_port( ) )
129+ info ! ( "ps2: flush {}: {:X}" , message, self . read_data_port( ) )
104130 }
105131 }
106132
107- fn read_data_port ( ) -> u8 {
108- Self :: wait_read ( ) ;
133+ /// Read a pending byte of data from the controller
134+ pub fn read_data_port ( & mut self ) -> u8 {
135+ self . wait_read ( ) ;
109136 unsafe { inb ( PS2_DATA_PORT ) }
110137 }
111138
112- fn write_data_port ( data : u8 ) {
113- Self :: wait_write ( ) ;
139+ fn write_data_port ( & mut self , data : u8 ) {
140+ self . wait_write ( ) ;
114141 unsafe {
115142 outb ( PS2_DATA_PORT , data) ;
116143 }
117144 }
118145
119- fn read_status_port ( ) -> Ps2StatusFlags {
146+ fn read_status_port ( & mut self ) -> Ps2StatusFlags {
120147 Ps2StatusFlags :: from_bits_truncate ( unsafe { inb ( PS2_STATUS_PORT ) } )
121148 }
122149
123- fn read_configuration ( ) -> Ps2ConfigurationFlags {
124- Self :: write_command_port ( Command :: ReadConfig ) ;
125- Ps2ConfigurationFlags :: from_bits_truncate ( Self :: read_data_port ( ) )
150+ fn read_configuration ( & mut self ) -> Ps2ConfigurationFlags {
151+ self . write_command_port ( Command :: ReadConfig ) ;
152+ Ps2ConfigurationFlags :: from_bits_truncate ( self . read_data_port ( ) )
126153 }
127154
128- fn write_configuration ( config : Ps2ConfigurationFlags ) {
129- Self :: write_command_port ( Command :: WriteConfig ) ;
130- Self :: write_data_port ( config. bits ( ) )
155+ fn write_configuration ( & mut self , config : Ps2ConfigurationFlags ) {
156+ self . write_command_port ( Command :: WriteConfig ) ;
157+ self . write_data_port ( config. bits ( ) )
131158 }
132159
133- fn wait_read ( ) {
134- while !Self :: read_status_port ( )
160+ fn wait_read ( & mut self ) {
161+ while !self
162+ . read_status_port ( )
135163 . contains ( Ps2StatusFlags :: OUTPUT_BUFFER_FULL )
136164 { }
137165 }
138166
139- fn wait_write ( ) {
140- while Self :: read_status_port ( )
167+ fn wait_write ( & mut self ) {
168+ while self
169+ . read_status_port ( )
141170 . contains ( Ps2StatusFlags :: INPUT_BUFFER_FULL )
142171 { }
143172 }
144173
145- fn write_command_port ( cmd : Command ) {
174+ fn write_command_port ( & mut self , cmd : Command ) {
146175 unsafe {
147176 outb ( PS2_COMMAND_PORT , cmd as u8 ) ;
148177 }
0 commit comments