@@ -83,6 +83,7 @@ use rp_pico::{
8383
8484// Other Neotron Crates
8585use common:: MemoryRegion ;
86+ use neotron_bmc_commands:: Command ;
8687use neotron_bmc_protocol:: Receivable ;
8788use neotron_common_bios as common;
8889
@@ -714,7 +715,7 @@ impl Hardware {
714715 /// These are connected to the bit 4 of GPIOA on the MCP23S17.
715716 fn set_hdd_led ( & mut self , enabled : bool ) {
716717 // LEDs are active-low.
717- self . led_state = ( self . led_state & 0x1e ) | if enabled { 0 } else { 1 } ;
718+ self . led_state = ( self . led_state & 0x1e ) | u8 :: from ( ! enabled) ;
718719 self . io_chip_write ( 0x12 , self . led_state << 3 | self . last_cs ) ;
719720 }
720721
@@ -825,33 +826,39 @@ impl Hardware {
825826 self . io_chip_read ( Self :: MCP23S17_GPIOB )
826827 }
827828
828- /// Read from a BMC register.
829+ /// Send a request to the BMC (a register read or a register write) and get
830+ /// the response.
829831 ///
830- /// It will perform a couple of retries, and then panic if the BMC did not respond correctly. It
831- /// sets the Chip Select line and controls the IO chip automatically.
832+ /// It will perform a couple of retries, and then panic if the BMC did not
833+ /// respond correctly. It sets the Chip Select line and controls the IO chip
834+ /// automatically.
832835 ///
833- /// The number of bytes you want is set by the length of the `buffer` argument.
834- ///
835- fn bmc_read_register ( & mut self , register : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , ( ) > {
836+ /// The `buffer` argument may contain a mutable buffer for received data.
837+ fn bmc_do_request (
838+ & mut self ,
839+ req : neotron_bmc_protocol:: Request ,
840+ buffer : Option < & mut [ u8 ] > ,
841+ ) -> Result < ( ) , ( ) > {
836842 const MAX_LATENCY : usize = 128 ;
837843
838- if buffer. len ( ) > self . bmc_buffer . len ( ) {
839- defmt:: error!( "Asked for too much data ({})" , buffer. len( ) ) ;
840- return Err ( ( ) ) ;
841- }
842- if buffer. len ( ) > usize:: from ( u8:: MAX ) {
843- defmt:: error!( "Asked for too much data ({})" , buffer. len( ) ) ;
844- return Err ( ( ) ) ;
844+ if let Some ( buffer) = buffer. as_ref ( ) {
845+ if buffer. len ( ) > self . bmc_buffer . len ( ) {
846+ defmt:: error!( "Asked for too much data ({})" , buffer. len( ) ) ;
847+ return Err ( ( ) ) ;
848+ }
849+ if buffer. len ( ) > usize:: from ( u8:: MAX ) {
850+ defmt:: error!( "Asked for too much data ({})" , buffer. len( ) ) ;
851+ return Err ( ( ) ) ;
852+ }
845853 }
846- let req =
847- neotron_bmc_protocol:: Request :: new_read ( USE_ALT . get ( ) , register, buffer. len ( ) as u8 ) ;
854+
848855 let req_bytes = req. as_bytes ( ) ;
849856 for _retries in 0 ..4 {
850857 // Clear the input buffer
851858 for byte in self . bmc_buffer . iter_mut ( ) {
852859 * byte = 0xFF ;
853860 }
854- let expected_response_len = buffer. len ( ) + 2 ;
861+ let expected_response_len = buffer. as_ref ( ) . map ( |b| b . len ( ) ) . unwrap_or ( 0 ) + 2 ;
855862 defmt:: debug!( "req: {=[u8; 4]:02x}" , req_bytes) ;
856863 let mut latency = 0 ;
857864 self . with_bus_cs ( 0 , |spi, borrowed_buffer| {
@@ -878,16 +885,25 @@ impl Hardware {
878885 let response_portion = & self . bmc_buffer [ 0 ..expected_response_len] ;
879886 match neotron_bmc_protocol:: Response :: from_bytes ( response_portion) {
880887 Ok ( res) => {
881- if res. result == neotron_bmc_protocol:: ResponseResult :: Ok
882- && res. data . len ( ) == buffer. len ( )
883- {
884- buffer. copy_from_slice ( res. data ) ;
888+ if res. result == neotron_bmc_protocol:: ResponseResult :: Ok {
889+ if let Some ( buffer) = buffer {
890+ if res. data . len ( ) == buffer. len ( ) {
891+ buffer. copy_from_slice ( res. data ) ;
892+ } else {
893+ defmt:: warn!(
894+ "Mismatch between received and expected data: expected {}, got {} bytes - {=[u8]:X}" ,
895+ buffer. len( ) ,
896+ res. data. len( ) ,
897+ res. data
898+ ) ;
899+ return Err ( ( ) ) ;
900+ }
901+ }
885902 return Ok ( ( ) ) ;
886903 } else {
887904 defmt:: warn!(
888- "Error reading {} bytes from {}: Error from BMC {:?} {=[u8]:x}" ,
889- buffer. len( ) ,
890- register,
905+ "Error executing {:?}: Error from BMC {:?} {=[u8]:x}" ,
906+ req,
891907 res. result,
892908 response_portion
893909 ) ;
@@ -897,9 +913,8 @@ impl Hardware {
897913 }
898914 Err ( e) => {
899915 defmt:: warn!(
900- "Error reading {} bytes from {}: Decoding Error {:?} {=[u8]:x}" ,
901- buffer. len( ) ,
902- register,
916+ "Error executing {:?}: Decoding Error {:?} {=[u8]:x}" ,
917+ req,
903918 e,
904919 response_portion
905920 ) ;
@@ -911,12 +926,45 @@ impl Hardware {
911926 panic ! ( "Failed to talk to BMC after several retries." ) ;
912927 }
913928
929+ /// Make the BMC produce a sequence of beeps using the Speaker
930+ fn play_startup_tune ( & mut self ) -> Result < ( ) , ( ) > {
931+ // (delay (ms), command, data)
932+ let seq: & [ ( u16 , Command , u8 ) ] = & [
933+ ( 0 , Command :: SpeakerPeriodLow , 137 ) ,
934+ ( 0 , Command :: SpeakerPeriodHigh , 0 ) ,
935+ ( 0 , Command :: SpeakerDutyCycle , 127 ) ,
936+ ( 0 , Command :: SpeakerDuration , 7 ) ,
937+ ( 0 , Command :: SpeakerPeriodLow , 116 ) ,
938+ ( 70 , Command :: SpeakerDuration , 7 ) ,
939+ ( 0 , Command :: SpeakerPeriodLow , 97 ) ,
940+ ( 70 , Command :: SpeakerDuration , 7 ) ,
941+ ] ;
942+
943+ for ( delay, reg, val) in seq {
944+ if * delay > 0 {
945+ self . delay . delay_ms ( * delay as u32 ) ;
946+ }
947+ self . bmc_do_request (
948+ neotron_bmc_protocol:: Request :: new_short_write ( USE_ALT . get ( ) , ( * reg) . into ( ) , * val) ,
949+ None ,
950+ ) ?;
951+ }
952+ Ok ( ( ) )
953+ }
954+
914955 /// Read the BMC firmware version string.
915956 ///
916957 /// You get 32 bytes of probably UTF-8 data.
917958 fn bmc_read_firmware_version ( & mut self ) -> Result < [ u8 ; 32 ] , ( ) > {
918959 let mut firmware_version = [ 0u8 ; 32 ] ;
919- self . bmc_read_register ( 0x01 , & mut firmware_version) ?;
960+ self . bmc_do_request (
961+ neotron_bmc_protocol:: Request :: new_read (
962+ USE_ALT . get ( ) ,
963+ Command :: FirmwareVersion . into ( ) ,
964+ firmware_version. len ( ) as u8 ,
965+ ) ,
966+ Some ( & mut firmware_version) ,
967+ ) ?;
920968 Ok ( firmware_version)
921969 }
922970
@@ -938,7 +986,14 @@ impl Hardware {
938986 }
939987
940988 let mut fifo_data = [ 0u8 ; 9 ] ;
941- self . bmc_read_register ( 0x40 , & mut fifo_data) ?;
989+ self . bmc_do_request (
990+ neotron_bmc_protocol:: Request :: new_read (
991+ USE_ALT . get ( ) ,
992+ Command :: Ps2KbBuffer . into ( ) ,
993+ fifo_data. len ( ) as u8 ,
994+ ) ,
995+ Some ( & mut fifo_data) ,
996+ ) ?;
942997 let bytes_in_fifo = fifo_data[ 0 ] ;
943998 if bytes_in_fifo == 0 {
944999 defmt:: trace!( "Got no PS/2 bytes" ) ;
@@ -948,15 +1003,15 @@ impl Hardware {
9481003 for ( dest, src) in out_buffer. iter_mut ( ) . zip ( fifo_data. iter ( ) . skip ( 1 ) ) {
9491004 * dest = * src;
9501005 }
951- return Ok ( bytes_in_fifo as usize ) ;
1006+ Ok ( bytes_in_fifo as usize )
9521007 }
9531008}
9541009
9551010fn sign_on ( ) {
9561011 static LICENCE_TEXT : & str = "\
957- Copyright © Jonathan 'theJPster' Pallant and the Neotron Developers, 2022\n \
958- \n \
959- This program is free software under GPL v3 (or later)\n ";
1012+ Copyright © Jonathan 'theJPster' Pallant and the Neotron Developers, 2022\n \
1013+ \n \
1014+ This program is free software under GPL v3 (or later)\n ";
9601015
9611016 // Create a new temporary console for some boot-up messages
9621017 let tc = vga:: TextConsole :: new ( ) ;
@@ -975,13 +1030,17 @@ fn sign_on() {
9751030 let bmc_ver = critical_section:: with ( |cs| {
9761031 let mut lock = HARDWARE . borrow_ref_mut ( cs) ;
9771032 let hw = lock. as_mut ( ) . unwrap ( ) ;
978- hw. bmc_read_firmware_version ( )
1033+ let ver = hw. bmc_read_firmware_version ( ) ;
1034+ if let Err ( e) = hw. play_startup_tune ( ) {
1035+ writeln ! ( & tc, "BMC error: {e:?}" ) . unwrap ( ) ;
1036+ }
1037+ ver
9791038 } ) ;
9801039
9811040 match bmc_ver {
9821041 Ok ( string_bytes) => match core:: str:: from_utf8 ( & string_bytes) {
9831042 Ok ( s) => {
984- writeln ! ( & tc, "BMC Version: {}" , s ) . unwrap ( ) ;
1043+ writeln ! ( & tc, "BMC Version: {s}" ) . unwrap ( ) ;
9851044 }
9861045 Err ( _e) => {
9871046 writeln ! ( & tc, "BMC Version: Unknown" ) . unwrap ( ) ;
0 commit comments