@@ -156,8 +156,8 @@ static API_CALLS: common::Api = common::Api {
156156 serial_get_info,
157157 serial_write,
158158 serial_read,
159- time_get ,
160- time_set ,
159+ time_clock_get ,
160+ time_clock_set ,
161161 configuration_get,
162162 configuration_set,
163163 video_is_valid_mode,
@@ -174,6 +174,30 @@ static API_CALLS: common::Api = common::Api {
174174 block_write,
175175 block_read,
176176 block_verify,
177+ time_ticks_get,
178+ time_ticks_per_second,
179+ video_get_palette,
180+ video_set_palette,
181+ video_set_whole_palette,
182+ i2c_bus_get_info,
183+ i2c_write_read,
184+ audio_mixer_channel_get_info,
185+ audio_mixer_channel_set_level,
186+ audio_output_set_config,
187+ audio_output_get_config,
188+ audio_output_data,
189+ audio_output_get_space,
190+ audio_input_set_config,
191+ audio_input_get_config,
192+ audio_input_data,
193+ audio_input_get_count,
194+ bus_select,
195+ bus_get_info,
196+ bus_write_read,
197+ bus_exchange,
198+ bus_interrupt_status,
199+ block_dev_eject,
200+ power_idle,
177201} ;
178202
179203extern "C" {
@@ -297,13 +321,8 @@ fn main() -> ! {
297321 sign_on ( ) ;
298322
299323 // Now jump to the OS
300- // let code: &common::OsStartFn = unsafe { ::core::mem::transmute(&_flash_os_start) };
301- // code(&API_CALLS);
302-
303- // OS has returned?! Just hang.
304- loop {
305- cortex_m:: asm:: wfi ( ) ;
306- }
324+ let code: & common:: OsStartFn = unsafe { :: core:: mem:: transmute ( & _flash_os_start) } ;
325+ code ( & API_CALLS ) ;
307326}
308327
309328impl Hardware {
@@ -642,20 +661,20 @@ impl Hardware {
642661 // Dump registers
643662 for reg in 0x00 ..=0x15 {
644663 let data = self . io_chip_read ( reg) ;
645- defmt:: debug!( "Reg 0x{:02x} => 0x{:02x}" , reg, data) ;
646664 }
647665 }
648666
649667 /// Read the BMC firmware version string.
650668 ///
651669 /// You get 32 bytes of probably UTF-8 data.
652670 fn bmc_read_firmware_version ( & mut self ) -> Result < [ u8 ; 32 ] , ( ) > {
653- let req = neotron_bmc_protocol:: Request :: new_read ( false , 0 , 32 ) ;
671+ let req = neotron_bmc_protocol:: Request :: new_read ( false , 0x01 , 32 ) ;
654672 let mut buffer = [ 0xFF ; 64 ] ;
655673 buffer[ 0 ..=3 ] . copy_from_slice ( & req. as_bytes ( ) ) ;
656674 self . with_bus_cs ( 0 , |spi| {
657675 spi. transfer ( & mut buffer) . unwrap ( ) ;
658676 } ) ;
677+ defmt:: info!( "buffer: {=[u8]:x}" , buffer) ;
659678 let mut result = & buffer[ ..] ;
660679 let mut latency = 0 ;
661680 while result. len ( ) > 0 && result[ 0 ] == 0xFF {
@@ -694,6 +713,53 @@ impl Hardware {
694713
695714 Err ( ( ) )
696715 }
716+
717+ /// Read the BMC PS/2 keyboard FIFO.
718+ ///
719+ /// We ask for 8 bytes of data. We get `1` byte of 'length', then `N` bytes of valid data, and `32 - (N + 1)` bytes of padding.
720+ fn bmc_read_ps2_keyboard_fifo ( & mut self , buffer : & mut [ u8 ] ) -> Result < usize , ( ) > {
721+ let req = neotron_bmc_protocol:: Request :: new_read ( false , 0x40 , 8 ) ;
722+ let mut buffer = [ 0xFF ; 42 ] ;
723+ buffer[ 0 ..=3 ] . copy_from_slice ( & req. as_bytes ( ) ) ;
724+ self . with_bus_cs ( 0 , |spi| {
725+ spi. transfer ( & mut buffer) . unwrap ( ) ;
726+ } ) ;
727+ defmt:: info!( "buffer: {=[u8]:x}" , buffer) ;
728+ let mut result = & buffer[ ..] ;
729+ let mut latency = 0 ;
730+ while result. len ( ) > 0 && result[ 0 ] == 0xFF {
731+ latency += 1 ;
732+ result = & result[ 1 ..] ;
733+ }
734+ defmt:: info!( "latency: {}" , latency) ;
735+ // 8 bytes of data requested, plus one bytes of response code and one byte of CRC
736+ if result. len ( ) >= 10 {
737+ match neotron_bmc_protocol:: Response :: from_bytes ( & result[ 0 ..10 ] ) {
738+ Ok ( res) => {
739+ if res. result == neotron_bmc_protocol:: ResponseResult :: Ok && res. data . len ( ) == 8
740+ {
741+ defmt:: info!( "Got PS/2 bytes {=[u8]:x}" , res. data) ;
742+ return Ok ( 0 ) ;
743+ } else {
744+ defmt:: warn!(
745+ "Error getting keyboard bytes: Error from BMC {:?} {=[u8]:x}" ,
746+ res. result,
747+ res. data
748+ ) ;
749+ }
750+ }
751+ Err ( e) => {
752+ defmt:: warn!(
753+ "Error getting BMC keyboard bytes: Decoding Error {:?} {=[u8]:x}" ,
754+ e,
755+ result
756+ ) ;
757+ }
758+ }
759+ }
760+
761+ Err ( ( ) )
762+ }
697763}
698764
699765fn sign_on ( ) {
@@ -735,6 +801,12 @@ fn sign_on() {
735801 writeln ! ( & tc, "BMC Version: Error reading" ) . unwrap ( ) ;
736802 }
737803 }
804+
805+ critical_section:: with ( |cs| {
806+ let mut lock = HARDWARE . borrow_ref_mut ( cs) ;
807+ let hw = lock. as_mut ( ) . unwrap ( ) ;
808+ hw. delay . delay_ms ( 5000 ) ;
809+ } ) ;
738810}
739811
740812/// Reset the DMA Peripheral.
@@ -825,7 +897,7 @@ pub extern "C" fn serial_read(
825897///
826898/// If the BIOS does not have a battery-backed clock, or if that battery has
827899/// failed to keep time, the system starts up assuming it is the epoch.
828- pub extern "C" fn time_get ( ) -> common:: Time {
900+ pub extern "C" fn time_clock_get ( ) -> common:: Time {
829901 // TODO: Read from the MCP7940N
830902 common:: Time { secs : 0 , nsecs : 0 }
831903}
@@ -839,7 +911,7 @@ pub extern "C" fn time_get() -> common::Time {
839911/// time (e.g. the user has updated the current time, or if you get a GPS
840912/// fix). The BIOS should push the time out to the battery-backed Real
841913/// Time Clock, if it has one.
842- pub extern "C" fn time_set ( _time : common:: Time ) {
914+ pub extern "C" fn time_clock_set ( _time : common:: Time ) {
843915 // TODO: Update the MCP7940N RTC
844916}
845917
@@ -950,24 +1022,28 @@ pub extern "C" fn video_mode_needs_vram(_mode: common::video::Mode) -> bool {
9501022/// (other than Region 0), so faster memory should be listed first.
9511023///
9521024/// If the region number given is invalid, the function returns `(null, 0)`.
953- pub extern "C" fn memory_get_region ( region : u8 ) -> common:: Result < common:: MemoryRegion > {
1025+ pub extern "C" fn memory_get_region ( region : u8 ) -> common:: Option < common:: MemoryRegion > {
9541026 match region {
9551027 0 => {
9561028 // Application Region
957- common:: Result :: Ok ( MemoryRegion {
1029+ common:: Option :: Some ( MemoryRegion {
9581030 start : unsafe { & mut _ram_os_start as * mut u32 } as * mut u8 ,
9591031 length : unsafe { & mut _ram_os_len as * const u32 } as usize ,
9601032 kind : common:: MemoryKind :: Ram ,
9611033 } )
9621034 }
963- _ => common:: Result :: Err ( common :: Error :: InvalidDevice ) ,
1035+ _ => common:: Option :: None ,
9641036 }
9651037}
9661038
9671039/// Get the next available HID event, if any.
9681040///
9691041/// This function doesn't block. It will return `Ok(None)` if there is no event ready.
9701042pub extern "C" fn hid_get_event ( ) -> common:: Result < common:: Option < common:: hid:: HidEvent > > {
1043+ // todo: call bmc_read_ps2_keyboard_fifo()
1044+ // todo: decode the PS/2 bytes we receive into HidEvents
1045+ // todo: cache all the bytes that don't make up a full HID event
1046+
9711047 // TODO: Support some HID events
9721048 common:: Result :: Ok ( common:: Option :: None )
9731049}
@@ -1013,6 +1089,109 @@ pub extern "C" fn video_wait_for_line(line: u16) {
10131089 }
10141090}
10151091
1092+ /// Read the RGB palette. Currently we only have two colours and you can't
1093+ /// change them.
1094+ extern "C" fn video_get_palette ( index : u8 ) -> common:: Option < common:: video:: RGBColour > {
1095+ match index {
1096+ 0 => common:: Option :: Some ( vga:: colours:: BLUE . into ( ) ) ,
1097+ 1 => common:: Option :: Some ( vga:: colours:: YELLOW . into ( ) ) ,
1098+ _ => common:: Option :: None ,
1099+ }
1100+ }
1101+
1102+ /// Update the RGB palette
1103+ extern "C" fn video_set_palette ( index : u8 , rgb : common:: video:: RGBColour ) {
1104+ // TODO set the palette when we actually have one
1105+ }
1106+
1107+ /// Update all the RGB palette
1108+ unsafe extern "C" fn video_set_whole_palette (
1109+ palette : * const common:: video:: RGBColour ,
1110+ length : usize ,
1111+ ) {
1112+ // TODO set the palette when we actually have one
1113+ }
1114+
1115+ extern "C" fn i2c_bus_get_info ( _i2c_bus : u8 ) -> common:: Option < common:: i2c:: BusInfo > {
1116+ unimplemented ! ( ) ;
1117+ }
1118+
1119+ extern "C" fn i2c_write_read (
1120+ _i2c_bus : u8 ,
1121+ _i2c_device_address : u8 ,
1122+ _tx : common:: ApiByteSlice ,
1123+ _tx2 : common:: ApiByteSlice ,
1124+ _rx : common:: ApiBuffer ,
1125+ ) -> common:: Result < ( ) > {
1126+ unimplemented ! ( ) ;
1127+ }
1128+
1129+ extern "C" fn audio_mixer_channel_get_info (
1130+ _audio_mixer_id : u8 ,
1131+ ) -> common:: Result < common:: audio:: MixerChannelInfo > {
1132+ unimplemented ! ( ) ;
1133+ }
1134+
1135+ extern "C" fn audio_mixer_channel_set_level ( _audio_mixer_id : u8 , _level : u8 ) -> common:: Result < ( ) > {
1136+ unimplemented ! ( ) ;
1137+ }
1138+
1139+ extern "C" fn audio_output_set_config ( _config : common:: audio:: Config ) -> common:: Result < ( ) > {
1140+ unimplemented ! ( ) ;
1141+ }
1142+
1143+ extern "C" fn audio_output_get_config ( ) -> common:: Result < common:: audio:: Config > {
1144+ unimplemented ! ( ) ;
1145+ }
1146+
1147+ unsafe extern "C" fn audio_output_data ( _samples : common:: ApiByteSlice ) -> common:: Result < usize > {
1148+ unimplemented ! ( ) ;
1149+ }
1150+
1151+ extern "C" fn audio_output_get_space ( ) -> common:: Result < usize > {
1152+ unimplemented ! ( ) ;
1153+ }
1154+
1155+ extern "C" fn audio_input_set_config ( _config : common:: audio:: Config ) -> common:: Result < ( ) > {
1156+ unimplemented ! ( ) ;
1157+ }
1158+
1159+ extern "C" fn audio_input_get_config ( ) -> common:: Result < common:: audio:: Config > {
1160+ unimplemented ! ( ) ;
1161+ }
1162+
1163+ extern "C" fn audio_input_data ( _samples : common:: ApiBuffer ) -> common:: Result < usize > {
1164+ unimplemented ! ( ) ;
1165+ }
1166+
1167+ extern "C" fn audio_input_get_count ( ) -> common:: Result < usize > {
1168+ unimplemented ! ( ) ;
1169+ }
1170+
1171+ extern "C" fn bus_select ( _periperal_id : common:: Option < u8 > ) {
1172+ unimplemented ! ( ) ;
1173+ }
1174+
1175+ extern "C" fn bus_get_info ( _periperal_id : u8 ) -> common:: Option < common:: bus:: PeripheralInfo > {
1176+ unimplemented ! ( ) ;
1177+ }
1178+
1179+ extern "C" fn bus_write_read (
1180+ _tx : common:: ApiByteSlice ,
1181+ _tx2 : common:: ApiByteSlice ,
1182+ _rx : common:: ApiBuffer ,
1183+ ) -> common:: Result < ( ) > {
1184+ unimplemented ! ( ) ;
1185+ }
1186+
1187+ extern "C" fn bus_exchange ( _buffer : common:: ApiBuffer ) -> common:: Result < ( ) > {
1188+ unimplemented ! ( ) ;
1189+ }
1190+
1191+ extern "C" fn bus_interrupt_status ( ) -> u32 {
1192+ 0
1193+ }
1194+
10161195/// Get information about the Block Devices in the system.
10171196///
10181197/// Block Devices are also known as *disk drives*. They can be read from
@@ -1062,7 +1241,7 @@ pub extern "C" fn block_dev_get_info(device: u8) -> common::Option<common::block
10621241/// aligned, the BIOS may be able to use a higher-performance code path.
10631242pub extern "C" fn block_write (
10641243 _device : u8 ,
1065- _block : u64 ,
1244+ _block : common :: block_dev :: BlockIdx ,
10661245 _num_blocks : u8 ,
10671246 _data : common:: ApiByteSlice ,
10681247) -> common:: Result < ( ) > {
@@ -1079,7 +1258,7 @@ pub extern "C" fn block_write(
10791258/// aligned, the BIOS may be able to use a higher-performance code path.
10801259pub extern "C" fn block_read (
10811260 _device : u8 ,
1082- _block : u64 ,
1261+ _block : common :: block_dev :: BlockIdx ,
10831262 _num_blocks : u8 ,
10841263 _data : common:: ApiBuffer ,
10851264) -> common:: Result < ( ) > {
@@ -1097,13 +1276,32 @@ pub extern "C" fn block_read(
10971276/// aligned, the BIOS may be able to use a higher-performance code path.
10981277pub extern "C" fn block_verify (
10991278 _device : u8 ,
1100- _block : u64 ,
1279+ _block : common :: block_dev :: BlockIdx ,
11011280 _num_blocks : u8 ,
11021281 _data : common:: ApiByteSlice ,
11031282) -> common:: Result < ( ) > {
11041283 common:: Result :: Err ( common:: Error :: Unimplemented )
11051284}
11061285
1286+ extern "C" fn block_dev_eject ( dev_id : u8 ) -> common:: Result < ( ) > {
1287+ common:: Result :: Ok ( ( ) )
1288+ }
1289+
1290+ /// Sleep the CPU until the next interrupt.
1291+ extern "C" fn power_idle ( ) {
1292+ cortex_m:: asm:: wfe ( ) ;
1293+ }
1294+
1295+ /// TODO: Get the monotonic run-time of the system from SysTick.
1296+ extern "C" fn time_ticks_get ( ) -> common:: Ticks {
1297+ common:: Ticks ( 0 )
1298+ }
1299+
1300+ /// We have a 1 kHz SysTick
1301+ extern "C" fn time_ticks_per_second ( ) -> common:: Ticks {
1302+ common:: Ticks ( 1000 )
1303+ }
1304+
11071305/// Called when DMA raises IRQ0; i.e. when a DMA transfer to the pixel FIFO or
11081306/// the timing FIFO has completed.
11091307#[ interrupt]
0 commit comments