public registers and plane mask

This commit is contained in:
Ryan Kennedy 2020-03-22 18:49:30 -05:00
parent 3eae6fb32d
commit a05f2cc826
9 changed files with 67 additions and 63 deletions

View file

@ -67,7 +67,7 @@ pub struct AttributeControllerRegisters {
}
impl AttributeControllerRegisters {
pub fn new() -> AttributeControllerRegisters {
pub(crate) fn new() -> AttributeControllerRegisters {
AttributeControllerRegisters {
arx_index: Port::new(ARX_INDEX_ADDRESS),
arx_data: Port::new(ARX_DATA_ADDRESS),

View file

@ -12,7 +12,7 @@ pub struct ColorPaletteRegisters {
}
impl ColorPaletteRegisters {
pub fn new() -> ColorPaletteRegisters {
pub(crate) fn new() -> ColorPaletteRegisters {
ColorPaletteRegisters {
data_port: Port::new(COLOR_PALETTE_DATA_ADDRESS),
index_read_port: Port::new(COLOR_PALETTE_INDEX_READ_ADDRESS),

View file

@ -79,7 +79,7 @@ pub struct CrtcControllerRegisters {
}
impl CrtcControllerRegisters {
pub fn new() -> CrtcControllerRegisters {
pub(crate) fn new() -> CrtcControllerRegisters {
CrtcControllerRegisters {
crx_index_cga: Port::new(CRX_INDEX_CGA_ADDRESS),
crx_index_mda: Port::new(CRX_INDEX_MDA_ADDRESS),

View file

@ -17,7 +17,7 @@ pub struct GeneralRegisters {
}
impl GeneralRegisters {
pub fn new() -> GeneralRegisters {
pub(crate) fn new() -> GeneralRegisters {
GeneralRegisters {
st00_read: PortReadOnly::new(ST00_READ_ADDRESS),
st01_read_cga: PortReadOnly::new(ST01_READ_CGA_ADDRESS),

View file

@ -44,7 +44,7 @@ pub struct GraphicsControllerRegisters {
}
impl GraphicsControllerRegisters {
pub fn new() -> GraphicsControllerRegisters {
pub(crate) fn new() -> GraphicsControllerRegisters {
GraphicsControllerRegisters {
grx_index: Port::new(GRX_INDEX_ADDRESS),
grx_data: Port::new(GRX_DATA_ADDRESS),

View file

@ -14,7 +14,7 @@ pub use color_palette::ColorPaletteRegisters;
pub use crtc_controller::{CrtcControllerIndex, CrtcControllerRegisters};
pub use general::GeneralRegisters;
pub use graphics_controller::{GraphicsControllerIndex, GraphicsControllerRegisters};
pub use sequencer::{SequencerIndex, SequencerRegisters};
pub use sequencer::{PlaneMask, SequencerIndex, SequencerRegisters};
const ST00_READ_ADDRESS: u16 = 0x3C2;
const ST01_READ_CGA_ADDRESS: u16 = 0x3DA;

View file

@ -1,6 +1,46 @@
use super::{SRX_DATA_ADDRESS, SRX_INDEX_ADDRESS};
use bitflags::bitflags;
use core::convert::TryFrom;
use x86_64::instructions::port::Port;
bitflags! {
/// Represents the plane masks of the `SequencerIndex::PlaneMask` register.
pub struct PlaneMask: u8 {
/// Represents none of the plane masks of vga memory.
const NONE = 0b0000_0000;
/// Represents `Plane0` of vga memory.
const PLANE0 = 0b0000_0001;
/// Represents `Plane1` of vga memory.
const PLANE1 = 0b0000_0010;
/// Represents `Plane2` of vga memory.
const PLANE2 = 0b0000_0100;
/// Represents `Plane3` of vga memory.
const PLANE3 = 0b0000_1000;
/// Represents all of the plane masks of vga memory.
const ALL_PLANES = Self::PLANE0.bits() | Self::PLANE1.bits() | Self::PLANE2.bits() | Self::PLANE3.bits();
}
}
impl TryFrom<u8> for PlaneMask {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(PlaneMask::PLANE0),
1 => Ok(PlaneMask::PLANE1),
2 => Ok(PlaneMask::PLANE2),
3 => Ok(PlaneMask::PLANE3),
_ => Err("PlaneMask only accepts values between 0-3!"),
}
}
}
impl From<PlaneMask> for u8 {
fn from(value: PlaneMask) -> u8 {
value.bits()
}
}
/// Represents an index for the seqeuncer registers.
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
@ -32,7 +72,7 @@ pub struct SequencerRegisters {
}
impl SequencerRegisters {
pub fn new() -> SequencerRegisters {
pub(crate) fn new() -> SequencerRegisters {
SequencerRegisters {
srx_index: Port::new(SRX_INDEX_ADDRESS),
srx_data: Port::new(SRX_DATA_ADDRESS),
@ -51,6 +91,11 @@ impl SequencerRegisters {
}
}
/// Sets the plane mask of the sequencer controller, as specified by `plane_mask`.
pub fn set_plane_mask(&mut self, plane_mask: PlaneMask) {
self.write(SequencerIndex::PlaneMask, u8::from(plane_mask));
}
fn set_index(&mut self, index: SequencerIndex) {
unsafe {
self.srx_index.write(u8::from(index));

View file

@ -10,10 +10,10 @@ use super::{
registers::{
AttributeControllerIndex, AttributeControllerRegisters, ColorPaletteRegisters,
CrtcControllerIndex, CrtcControllerRegisters, EmulationMode, GeneralRegisters,
GraphicsControllerIndex, GraphicsControllerRegisters, SequencerIndex, SequencerRegisters,
GraphicsControllerIndex, GraphicsControllerRegisters, PlaneMask, SequencerIndex,
SequencerRegisters,
},
};
use bitflags::bitflags;
use conquer_once::spin::Lazy;
use core::convert::TryFrom;
use spinning_top::Spinlock;
@ -86,44 +86,6 @@ impl From<ReadPlane> for u8 {
}
}
bitflags! {
/// Represents the plane masks of the `SequencerIndex::PlaneMask` register.
pub struct PlaneMask: u8 {
/// Represents none of the plane masks of vga memory.
const NONE = 0b0000_0000;
/// Represents `Plane0` of vga memory.
const PLANE0 = 0b0000_0001;
/// Represents `Plane1` of vga memory.
const PLANE1 = 0b0000_0010;
/// Represents `Plane2` of vga memory.
const PLANE2 = 0b0000_0100;
/// Represents `Plane3` of vga memory.
const PLANE3 = 0b0000_1000;
/// Represents all of the plane masks of vga memory.
const ALL_PLANES = Self::PLANE0.bits() | Self::PLANE1.bits() | Self::PLANE2.bits() | Self::PLANE3.bits();
}
}
impl TryFrom<u8> for PlaneMask {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(PlaneMask::PLANE0),
1 => Ok(PlaneMask::PLANE1),
2 => Ok(PlaneMask::PLANE2),
3 => Ok(PlaneMask::PLANE3),
_ => Err("PlaneMask only accepts values between 0-3!"),
}
}
}
impl From<PlaneMask> for u8 {
fn from(value: PlaneMask) -> u8 {
value.bits()
}
}
/// Represents a specified vga video mode.
#[derive(Debug, Clone, Copy)]
pub enum VideoMode {
@ -140,12 +102,12 @@ pub enum VideoMode {
/// Represents a vga graphics card with it's common registers,
/// as well as the most recent video mode.
pub struct Vga {
general_registers: GeneralRegisters,
sequencer_registers: SequencerRegisters,
graphics_controller_registers: GraphicsControllerRegisters,
attribute_controller_registers: AttributeControllerRegisters,
crtc_controller_registers: CrtcControllerRegisters,
color_palette_registers: ColorPaletteRegisters,
pub general_registers: GeneralRegisters,
pub sequencer_registers: SequencerRegisters,
pub graphics_controller_registers: GraphicsControllerRegisters,
pub attribute_controller_registers: AttributeControllerRegisters,
pub crtc_controller_registers: CrtcControllerRegisters,
pub color_palette_registers: ColorPaletteRegisters,
most_recent_video_mode: Option<VideoMode>,
}
@ -280,7 +242,7 @@ impl Vga {
);
// Write font to plane
self.set_plane_mask(PlaneMask::PLANE2);
self.sequencer_registers.set_plane_mask(PlaneMask::PLANE2);
let frame_buffer = u32::from(self.get_frame_buffer()) as *mut u8;
@ -340,12 +302,6 @@ impl Vga {
)
}
/// Sets the plane mask of the sequencer controller, as specified by `plane_mask`.
pub fn set_plane_mask(&mut self, plane_mask: PlaneMask) {
self.sequencer_registers
.write(SequencerIndex::PlaneMask, u8::from(plane_mask));
}
/// Sets the read plane of the graphics controller, as specified by `read_plane`.
pub fn set_read_plane(&mut self, read_plane: ReadPlane) {
let read_plane = u8::from(read_plane) & 0x3;

View file

@ -1,6 +1,7 @@
use crate::{
colors::{Color16Bit, DEFAULT_PALETTE},
vga::{PlaneMask, Vga, VideoMode, VGA},
registers::PlaneMask,
vga::{Vga, VideoMode, VGA},
};
use core::convert::TryInto;
use spinning_top::SpinlockGuard;
@ -35,7 +36,8 @@ impl Graphics640x480x16 {
/// Clears the screen by setting all pixels to `Color16Bit::Black`.
pub fn clear_screen(&self) {
let (mut vga, frame_buffer) = self.get_frame_buffer();
vga.set_plane_mask(PlaneMask::ALL_PLANES);
vga.sequencer_registers
.set_plane_mask(PlaneMask::ALL_PLANES);
vga.set_graphics_enable_set_reset(PlaneMask::NONE);
for offset in 0..ALL_PLANES_SCREEN_SIZE {
unsafe {
@ -58,7 +60,8 @@ impl Graphics640x480x16 {
for plane in 0u8..4u8 {
vga.set_read_plane(plane.try_into().unwrap());
vga.set_plane_mask(plane.try_into().unwrap());
vga.sequencer_registers
.set_plane_mask(plane.try_into().unwrap());
let current_value = unsafe { frame_buffer.add(offset).read_volatile() };
let new_value = if plane_mask & color as u8 != 0 {
current_value | mask