services: start implementing services
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
		| @@ -1,5 +1,14 @@ | ||||
| #![allow(dead_code)] | ||||
|  | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub enum Message { | ||||
|     MutableBorrow = 0, | ||||
|     Borrow = 1, | ||||
|     Move = 2, | ||||
|     Scalar = 3, | ||||
|     BlockingScalar = 4, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Copy, Clone)] | ||||
| pub enum SyscallResultNumber { | ||||
|     Ok = 0, | ||||
| @@ -18,6 +27,7 @@ pub enum SyscallResultNumber { | ||||
| #[derive(Debug)] | ||||
| pub enum Syscall { | ||||
|     Unknown([i64; 8]), | ||||
|     Yield, | ||||
|     IncreaseHeap( | ||||
|         i64, /* number of bytes to add */ | ||||
|         i64, /* memory flags */ | ||||
| @@ -28,6 +38,27 @@ pub enum Syscall { | ||||
|         i64, /* flags */ | ||||
|         i64, /* name */ | ||||
|     ), | ||||
|     Connect([u32; 4] /* Server ID */), | ||||
|     SendMessage( | ||||
|         u32,      /* Connection ID */ | ||||
|         u32,      /* message kind */ | ||||
|         u32,      /* opcode */ | ||||
|         [u32; 4], /* descriptor */ | ||||
|     ), | ||||
|     UpdateMemoryFlags( | ||||
|         i64, /* address */ | ||||
|         i64, /* range */ | ||||
|         i64, /* flags */ | ||||
|     ), | ||||
|     CreateThread( | ||||
|         i64, /* entry point */ | ||||
|         i64, /* stack pointer */ | ||||
|         i64, /* stack length */ | ||||
|         i64, /* argument 1 */ | ||||
|         i64, /* argument 2 */ | ||||
|         i64, /* argument 3 */ | ||||
|         i64, /* argument 4 */ | ||||
|     ), | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| @@ -57,6 +88,30 @@ impl From<[i64; 8]> for Syscall { | ||||
|         match value[0].into() { | ||||
|             SyscallNumber::IncreaseHeap => Syscall::IncreaseHeap(value[1], value[2]), | ||||
|             SyscallNumber::MapMemory => Syscall::MapMemory(value[1], value[2], value[3], value[4]), | ||||
|             SyscallNumber::Connect => Syscall::Connect([ | ||||
|                 value[1] as u32, | ||||
|                 value[2] as u32, | ||||
|                 value[3] as u32, | ||||
|                 value[4] as u32, | ||||
|             ]), | ||||
|             SyscallNumber::SendMessage => Syscall::SendMessage( | ||||
|                 value[1] as u32, | ||||
|                 value[2] as u32, | ||||
|                 value[3] as u32, | ||||
|                 [ | ||||
|                     value[4] as u32, | ||||
|                     value[5] as u32, | ||||
|                     value[6] as u32, | ||||
|                     value[7] as u32, | ||||
|                 ], | ||||
|             ), | ||||
|             SyscallNumber::UpdateMemoryFlags => { | ||||
|                 Syscall::UpdateMemoryFlags(value[1], value[2], value[3]) | ||||
|             } | ||||
|             SyscallNumber::CreateThread => Syscall::CreateThread( | ||||
|                 value[1], value[2], value[3], value[4], value[5], value[6], value[7], | ||||
|             ), | ||||
|             SyscallNumber::Yield => Syscall::Yield, | ||||
|             _ => Syscall::Unknown(value), | ||||
|         } | ||||
|     } | ||||
|   | ||||
							
								
								
									
										36
									
								
								src/xous/services.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/xous/services.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| pub mod log; | ||||
| pub mod ticktimer; | ||||
|  | ||||
| pub enum ScalarResult { | ||||
|     Scalar1(u32), | ||||
|     Scalar2([u32; 2]), | ||||
|     Scalar5([u32; 5]), | ||||
| } | ||||
|  | ||||
| pub trait Service { | ||||
|     fn scalar(&mut self, sender: u32, opcode: u32, _args: [u32; 4]) { | ||||
|         panic!("Unknown scalar to service {}: {}", sender, opcode); | ||||
|     } | ||||
|     fn blocking_scalar(&mut self, sender: u32, opcode: u32, _args: [u32; 4]) -> ScalarResult { | ||||
|         panic!("Unknown scalar to service {}: {}", sender, opcode); | ||||
|     } | ||||
|     fn lend(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) -> [u32; 2] { | ||||
|         panic!("Unknown lend to service {}: {} ({:?})", sender, opcode, extra); | ||||
|     } | ||||
|     fn lend_mut(&mut self, sender: u32, opcode: u32, _buf: &mut [u8], extra: [u32; 2]) -> [u32; 2] { | ||||
|         panic!("Unknown lend_mut to service {}: {} ({:?})", sender, opcode, extra); | ||||
|     } | ||||
|     fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) { | ||||
|         panic!("Unknown send to service {}: {} ({:?})", sender, opcode, extra); | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub fn get_service(name: &[u32; 4]) -> Option<Box<dyn Service + Sync + Send>> { | ||||
|     match name { | ||||
|         [0x6b636974, 0x656d6974, 0x65732d72, 0x72657672] => { | ||||
|             Some(Box::new(ticktimer::Ticktimer::new())) | ||||
|         } | ||||
|         [0x73756f78, 0x676f6c2d, 0x7265732d, 0x20726576] => Some(Box::new(log::Log::new())), | ||||
|         _ => None, | ||||
|     } | ||||
| } | ||||
							
								
								
									
										56
									
								
								src/xous/services/log.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/xous/services/log.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| use super::{ScalarResult, Service}; | ||||
| use std::io::Write; | ||||
|  | ||||
| enum LogLendOpcode { | ||||
|     /// A `&[u8]` destined for stdout | ||||
|     StandardOutput = 1, | ||||
|  | ||||
|     /// A `&[u8]` destined for stderr | ||||
|     StandardError = 2, | ||||
| } | ||||
|  | ||||
| pub struct Log {} | ||||
|  | ||||
| impl Log { | ||||
|     pub fn new() -> Self { | ||||
|         // println!("Constructing a log server"); | ||||
|         Log {} | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Default for Log { | ||||
|     fn default() -> Self { | ||||
|         Self::new() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Service for Log { | ||||
|     fn scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) { | ||||
|         println!("Log scalar {}: {} {:x?}", sender, opcode, args); | ||||
|     } | ||||
|     fn blocking_scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) -> ScalarResult { | ||||
|         println!("Log blocking_scalar {}: {} {:x?}", sender, opcode, args); | ||||
|         ScalarResult::Scalar1(0) | ||||
|     } | ||||
|     fn lend(&mut self, sender: u32, opcode: u32, buf: &[u8], extra: [u32; 2]) -> [u32; 2] { | ||||
|         if opcode == LogLendOpcode::StandardOutput as u32 { | ||||
|             let print_buffer = &buf[0..extra[1] as usize]; | ||||
|             // println!("Log stdout:"); | ||||
|             std::io::stdout().write_all(print_buffer).unwrap(); | ||||
|         } else if opcode == LogLendOpcode::StandardError as u32 { | ||||
|             let print_buffer = &buf[0..extra[1] as usize]; | ||||
|             // println!("Log stderr:"); | ||||
|             std::io::stderr().write_all(print_buffer).unwrap(); | ||||
|         } else { | ||||
|             panic!("Log lend {}: {} {:x?}", sender, opcode, buf); | ||||
|         } | ||||
|         [0, 0] | ||||
|     } | ||||
|     fn lend_mut(&mut self, sender: u32, opcode: u32, _buf: &mut [u8], extra: [u32; 2]) -> [u32; 2] { | ||||
|         println!("Log lend_mut {}: {} {:x?}", sender, opcode, extra); | ||||
|         [0, 0] | ||||
|     } | ||||
|     fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) { | ||||
|         println!("Log send {}: {} {:x?}", sender, opcode, extra); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										70
									
								
								src/xous/services/ticktimer.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/xous/services/ticktimer.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| pub struct Ticktimer { | ||||
|     start: std::time::SystemTime, | ||||
| } | ||||
|  | ||||
| enum ScalarOpcode { | ||||
|     ElapsedMs = 0, | ||||
|     WaitForCondition = 8 | ||||
| } | ||||
|  | ||||
| impl Ticktimer { | ||||
|     pub fn new() -> Self { | ||||
|         // println!("Constructing a ticktimer"); | ||||
|         Ticktimer { | ||||
|             start: std::time::SystemTime::now(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Default for Ticktimer { | ||||
|     fn default() -> Self { | ||||
|         Self::new() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl super::Service for Ticktimer { | ||||
|     fn scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) { | ||||
|         println!("Ticktimer scalar {}: {} {:x?}", sender, opcode, args); | ||||
|     } | ||||
|     fn blocking_scalar(&mut self, sender: u32, opcode: u32, args: [u32; 4]) -> super::ScalarResult { | ||||
|         if opcode == ScalarOpcode::ElapsedMs as u32 { | ||||
|             let elapsed_ms = std::time::SystemTime::now() | ||||
|                 .duration_since(self.start) | ||||
|                 .unwrap() | ||||
|                 .as_millis() as u64; | ||||
|             super::ScalarResult::Scalar2([elapsed_ms as u32, (elapsed_ms >> 32) as u32]) | ||||
|         } else if opcode == ScalarOpcode::WaitForCondition as u32 { | ||||
|             let start = std::time::SystemTime::now(); | ||||
|             let mut elapsed_ms = start | ||||
|                 .duration_since(self.start) | ||||
|                 .unwrap() | ||||
|                 .as_millis() as u64; | ||||
|             let mut condition = args[0]; | ||||
|             while condition != 0 { | ||||
|                 std::thread::sleep(std::time::Duration::from_millis(1)); | ||||
|                 elapsed_ms = start | ||||
|                     .duration_since(self.start) | ||||
|                     .unwrap() | ||||
|                     .as_millis() as u64; | ||||
|                 condition = args[0]; | ||||
|             } | ||||
|             super::ScalarResult::Scalar2([elapsed_ms as u32, (elapsed_ms >> 32) as u32]) | ||||
|         } else { | ||||
|             panic!( | ||||
|                 "Ticktimer blocking_scalar {}: {} {:x?}", | ||||
|                 sender, opcode, args | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|     fn lend(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) -> [u32; 2] { | ||||
|         println!("Ticktimer lend {}: {} {:x?}", sender, opcode, extra); | ||||
|         [0, 0] | ||||
|     } | ||||
|     fn lend_mut(&mut self, sender: u32, opcode: u32, _buf: &mut [u8], extra: [u32; 2]) -> [u32; 2] { | ||||
|         println!("Ticktimer lend_mut {}: {} {:x?}", sender, opcode, extra); | ||||
|         [0, 0] | ||||
|     } | ||||
|     fn send(&mut self, sender: u32, opcode: u32, _buf: &[u8], extra: [u32; 2]) { | ||||
|         println!("Ticktimer send {}: {} {:x?}", sender, opcode, extra); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user