99//!
1010//! The BIOS is started by having standard Cortex-M Interrupt Vector Table at
1111//! address `0x1000_0100`. This IVT is found and jumped to by the RP2040 boot
12- //! block(`0x1000_0000` to `0x1000_00FF`).
12+ //! block (`0x1000_0000` to `0x1000_00FF`).
1313
1414// -----------------------------------------------------------------------------
1515// Licence Statement
@@ -89,6 +89,7 @@ static API_CALLS: common::Api = common::Api {
8989 serial_configure,
9090 serial_get_info,
9191 serial_write,
92+ serial_read,
9293 time_get,
9394 time_set,
9495 configuration_get,
@@ -99,6 +100,14 @@ static API_CALLS: common::Api = common::Api {
99100 video_get_framebuffer,
100101 video_set_framebuffer,
101102 memory_get_region,
103+ video_mode_needs_vram,
104+ hid_get_event,
105+ hid_set_leds,
106+ video_wait_for_line,
107+ block_dev_get_info,
108+ block_write,
109+ block_read,
110+ block_verify,
102111} ;
103112
104113extern "C" {
@@ -336,6 +345,19 @@ pub extern "C" fn serial_write(
336345 common:: Result :: Err ( common:: Error :: Unimplemented )
337346}
338347
348+ /// Read bytes from a serial port. There is no sense of 'opening' or
349+ /// 'closing' the device - serial devices are always open. If the return value
350+ /// is `Ok(n)`, the value `n` may be less than the size of the given buffer.
351+ /// If so, that means not all of the data could be received - only the
352+ /// first `n` bytes were filled in.
353+ pub extern "C" fn serial_read (
354+ _device : u8 ,
355+ _data : common:: ApiBuffer ,
356+ _timeout : common:: Option < common:: Timeout > ,
357+ ) -> common:: Result < usize > {
358+ common:: Result :: Err ( common:: Error :: Unimplemented )
359+ }
360+
339361/// Get the current wall time.
340362///
341363/// The Neotron BIOS does not understand time zones, leap-seconds or the
@@ -448,6 +470,13 @@ pub unsafe extern "C" fn video_set_framebuffer(_buffer: *const u8) -> common::Re
448470 common:: Result :: Err ( common:: Error :: Unimplemented )
449471}
450472
473+ /// Find out whether the given video mode needs more VRAM than we currently have.
474+ ///
475+ /// The answer is no for any currently supported video mode (which is just the four text modes right now).
476+ pub extern "C" fn video_mode_needs_vram ( _mode : common:: video:: Mode ) -> bool {
477+ false
478+ }
479+
451480/// Find out how large a given region of memory is.
452481///
453482/// The first region is the 'main application region' and is defined to always
@@ -480,6 +509,146 @@ pub extern "C" fn memory_get_region(region: u8) -> common::Result<common::Memory
480509 }
481510}
482511
512+ /// Get the next available HID event, if any.
513+ ///
514+ /// This function doesn't block. It will return `Ok(None)` if there is no event ready.
515+ pub extern "C" fn hid_get_event ( ) -> common:: Result < common:: Option < common:: hid:: HidEvent > > {
516+ // TODO: Support some HID events
517+ common:: Result :: Ok ( common:: Option :: None )
518+ }
519+
520+ /// Control the keyboard LEDs.
521+ pub extern "C" fn hid_set_leds ( _leds : common:: hid:: KeyboardLeds ) -> common:: Result < ( ) > {
522+ common:: Result :: Err ( common:: Error :: Unimplemented )
523+ }
524+
525+ /// Wait for the next occurence of the specified video scan-line.
526+ ///
527+ /// In general we must assume that the video memory is read top-to-bottom
528+ /// as the picture is being drawn on the monitor (e.g. via a VGA video
529+ /// signal). If you modify video memory during this *drawing period*
530+ /// there is a risk that the image on the monitor (however briefly) may
531+ /// contain some parts from before the modification and some parts from
532+ /// after. This can given rise to the *tearing effect* where it looks
533+ /// like the screen has been torn (or ripped) across because there is a
534+ /// discontinuity part-way through the image.
535+ ///
536+ /// This function busy-waits until the video drawing has reached a
537+ /// specified scan-line on the video frame.
538+ ///
539+ /// There is no error code here. If the line you ask for is beyond the
540+ /// number of visible scan-lines in the current video mode, it waits util
541+ /// the last visible scan-line is complete.
542+ ///
543+ /// If you wait for the last visible line until drawing, you stand the
544+ /// best chance of your pixels operations on the video RAM being
545+ /// completed before scan-lines start being sent to the monitor for the
546+ /// next frame.
547+ ///
548+ /// You can also use this for a crude `16.7 ms` delay but note that
549+ /// some video modes run at `70 Hz` and so this would then give you a
550+ /// `14.3ms` second delay.
551+ pub extern "C" fn video_wait_for_line ( line : u16 ) {
552+ let desired_line = line. min ( vga:: get_num_scan_lines ( ) ) ;
553+ loop {
554+ let current_line = vga:: get_scan_line ( ) ;
555+ if current_line == desired_line {
556+ break ;
557+ }
558+ }
559+ }
560+
561+ /// Get information about the Block Devices in the system.
562+ ///
563+ /// Block Devices are also known as *disk drives*. They can be read from
564+ /// (and often written to) but only in units called *blocks* or *sectors*.
565+ ///
566+ /// The BIOS should enumerate removable devices first, followed by fixed
567+ /// devices.
568+ ///
569+ /// The set of devices is not expected to change at run-time - removal of
570+ /// media is indicated with a boolean field in the
571+ /// `block_dev::DeviceInfo` structure.
572+ pub extern "C" fn block_dev_get_info ( device : u8 ) -> common:: Option < common:: block_dev:: DeviceInfo > {
573+ match device {
574+ 0 => {
575+ common:: Option :: Some ( common:: block_dev:: DeviceInfo {
576+ // This is the built-in SD card slot
577+ name : common:: types:: ApiString :: new ( "SdCard0" ) ,
578+ device_type : common:: block_dev:: DeviceType :: SecureDigitalCard ,
579+ // This is the standard for SD cards
580+ block_size : 512 ,
581+ // TODO: scan the card here
582+ num_blocks : 0 ,
583+ // No motorised eject
584+ ejectable : false ,
585+ // But you can take the card out
586+ removable : true ,
587+ // Pretend the card is out
588+ media_present : true ,
589+ // Don't care about this value when card is out
590+ read_only : false ,
591+ } )
592+ }
593+ _ => {
594+ // Nothing else supported by this BIOS
595+ common:: Option :: None
596+ }
597+ }
598+ }
599+
600+ /// Write one or more sectors to a block device.
601+ ///
602+ /// The function will block until all data is written. The array pointed
603+ /// to by `data` must be `num_blocks * block_size` in length, where
604+ /// `block_size` is given by `block_dev_get_info`.
605+ ///
606+ /// There are no requirements on the alignment of `data` but if it is
607+ /// aligned, the BIOS may be able to use a higher-performance code path.
608+ pub extern "C" fn block_write (
609+ _device : u8 ,
610+ _block : u64 ,
611+ _num_blocks : u8 ,
612+ _data : common:: ApiByteSlice ,
613+ ) -> common:: Result < ( ) > {
614+ common:: Result :: Err ( common:: Error :: Unimplemented )
615+ }
616+
617+ /// Read one or more sectors to a block device.
618+ ///
619+ /// The function will block until all data is read. The array pointed
620+ /// to by `data` must be `num_blocks * block_size` in length, where
621+ /// `block_size` is given by `block_dev_get_info`.
622+ ///
623+ /// There are no requirements on the alignment of `data` but if it is
624+ /// aligned, the BIOS may be able to use a higher-performance code path.
625+ pub extern "C" fn block_read (
626+ _device : u8 ,
627+ _block : u64 ,
628+ _num_blocks : u8 ,
629+ _data : common:: ApiBuffer ,
630+ ) -> common:: Result < ( ) > {
631+ common:: Result :: Err ( common:: Error :: Unimplemented )
632+ }
633+
634+ /// Verify one or more sectors on a block device (that is read them and
635+ /// check they match the given data).
636+ ///
637+ /// The function will block until all data is verified. The array pointed
638+ /// to by `data` must be `num_blocks * block_size` in length, where
639+ /// `block_size` is given by `block_dev_get_info`.
640+ ///
641+ /// There are no requirements on the alignment of `data` but if it is
642+ /// aligned, the BIOS may be able to use a higher-performance code path.
643+ pub extern "C" fn block_verify (
644+ _device : u8 ,
645+ _block : u64 ,
646+ _num_blocks : u8 ,
647+ _data : common:: ApiByteSlice ,
648+ ) -> common:: Result < ( ) > {
649+ common:: Result :: Err ( common:: Error :: Unimplemented )
650+ }
651+
483652/// Called when DMA raises IRQ0; i.e. when a DMA transfer to the pixel FIFO or
484653/// the timing FIFO has completed.
485654#[ interrupt]
0 commit comments