From 39a4dd2ff08f7f16f57b7dae67e26946f890512c Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 8 Apr 2019 20:53:00 +0800 Subject: [PATCH] Fix VGA driver, now screen lightens on malta! Signed-off-by: Harry Chen --- kernel/src/arch/mipsel/board/malta/mod.rs | 5 +- kernel/src/arch/mipsel/io.rs | 5 -- kernel/src/arch/mipsel/mod.rs | 8 +-- kernel/src/drivers/bus/mod.rs | 2 +- kernel/src/drivers/bus/pci.rs | 35 +++++++++- kernel/src/drivers/gpu/qemu_stdvga.rs | 82 +++++++++++++++++------ kernel/src/drivers/net/e1000.rs | 4 +- 7 files changed, 105 insertions(+), 36 deletions(-) diff --git a/kernel/src/arch/mipsel/board/malta/mod.rs b/kernel/src/arch/mipsel/board/malta/mod.rs index 2681bd3..9917c70 100644 --- a/kernel/src/arch/mipsel/board/malta/mod.rs +++ b/kernel/src/arch/mipsel/board/malta/mod.rs @@ -1,6 +1,7 @@ use once::*; use alloc::string::String; use mips::registers::cp0; +use crate::drivers::bus::pci; #[path = "../../../../drivers/serial/ti_16c550c.rs"] pub mod serial; @@ -31,7 +32,9 @@ pub fn init_serial_early() { /// Initialize other board drivers pub fn init_driver() { // TODO: add possibly more drivers - vga::init(0xb8000000, 0xb2050000, 800, 600); + vga::init(0xbbe00000, 0xb2050000, 800, 600); + // pci::init(); + fb::init(); } pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferResult { diff --git a/kernel/src/arch/mipsel/io.rs b/kernel/src/arch/mipsel/io.rs index 2012a62..e5be3e5 100644 --- a/kernel/src/arch/mipsel/io.rs +++ b/kernel/src/arch/mipsel/io.rs @@ -23,8 +23,3 @@ pub fn putfmt(fmt: Arguments) { console.write_fmt(fmt).unwrap(); } } - -pub fn putchar(c: u8) { - unsafe { SERIAL_PORT.force_unlock() } - SERIAL_PORT.lock().putchar(c); -} diff --git a/kernel/src/arch/mipsel/mod.rs b/kernel/src/arch/mipsel/mod.rs index 9bc4c4e..5976118 100644 --- a/kernel/src/arch/mipsel/mod.rs +++ b/kernel/src/arch/mipsel/mod.rs @@ -51,15 +51,15 @@ pub extern fn rust_main() -> ! { unsafe { memory::clear_bss(); } board::init_serial_early(); - driver::init(); - - println!("Hello MIPS 32 from CPU {}, dtb @ {:#x}", cpu_id, dtb_start); + crate::logging::init(); interrupt::init(); memory::init(); timer::init(); + driver::init(); + + println!("Hello MIPS 32 from CPU {}, dtb @ {:#x}", cpu_id, dtb_start); - crate::logging::init(); crate::drivers::init(dtb_start); crate::process::init(); diff --git a/kernel/src/drivers/bus/mod.rs b/kernel/src/drivers/bus/mod.rs index 673e3ba..cee2283 100644 --- a/kernel/src/drivers/bus/mod.rs +++ b/kernel/src/drivers/bus/mod.rs @@ -1,3 +1,3 @@ -#[cfg(target_arch = "x86_64")] +#[cfg(any(target_arch = "x86_64", target_arch = "mips"))] pub mod pci; pub mod virtio_mmio; diff --git a/kernel/src/drivers/bus/pci.rs b/kernel/src/drivers/bus/pci.rs index 6a143c8..78d0bd6 100644 --- a/kernel/src/drivers/bus/pci.rs +++ b/kernel/src/drivers/bus/pci.rs @@ -10,7 +10,6 @@ use core::cmp::Ordering; use pci::*; use rcore_memory::{paging::PageTable, PAGE_SIZE}; use spin::Mutex; -use x86_64::instructions::port::Port; const PCI_COMMAND: u16 = 0x04; const PCI_CAP_PTR: u16 = 0x34; @@ -26,7 +25,12 @@ const PCI_CAP_ID_MSI: u8 = 0x05; struct PortOpsImpl; +#[cfg(target_arch = "x86_64")] +use x86_64::instructions::port::Port; + +#[cfg(target_arch = "x86_64")] impl PortOps for PortOpsImpl { + unsafe fn read8(&self, port: u16) -> u8 { Port::new(port).read() } @@ -47,6 +51,35 @@ impl PortOps for PortOpsImpl { } } + +#[cfg(target_arch = "mips")] +use crate::util::{read, write}; +#[cfg(feature = "board_malta")] +const PCI_BASE: usize = 0xbbe00000; + +#[cfg(target_arch = "mips")] +impl PortOps for PortOpsImpl { + + unsafe fn read8(&self, port: u16) -> u8 { + read(PCI_BASE + port as usize) + } + unsafe fn read16(&self, port: u16) -> u16 { + read(PCI_BASE + port as usize) + } + unsafe fn read32(&self, port: u16) -> u32 { + read(PCI_BASE + port as usize) + } + unsafe fn write8(&self, port: u16, val: u8) { + write(PCI_BASE + port as usize, val); + } + unsafe fn write16(&self, port: u16, val: u16) { + write(PCI_BASE + port as usize, val); + } + unsafe fn write32(&self, port: u16, val: u32) { + write(PCI_BASE + port as usize, val); + } +} + /// Enable the pci device and its interrupt /// Return assigned MSI interrupt number when applicable unsafe fn enable(loc: Location) -> Option { diff --git a/kernel/src/drivers/gpu/qemu_stdvga.rs b/kernel/src/drivers/gpu/qemu_stdvga.rs index 63a3c21..7467667 100644 --- a/kernel/src/drivers/gpu/qemu_stdvga.rs +++ b/kernel/src/drivers/gpu/qemu_stdvga.rs @@ -2,49 +2,71 @@ use crate::util::{read, write}; -const VGA_MMIO_OFFSET: usize = 0x400 - 0x3c0; +const VGA_MMIO_OFFSET: usize = 0x400 - 0x3C0; const VBE_MMIO_OFFSET: usize = 0x500; -const VGA_AR_ADDR: u16 = 0x3C0; -const VBE_DISPI_INDEX_XRES: u16 = 0x01; -const VBE_DISPI_INDEX_YRES: u16 = 0x02; -const VBE_DISPI_INDEX_BPP: u16 = 0x03; -const VBE_DISPI_INDEX_ENABLE: u16 = 0x04; +const VGA_AR_ADDR : u16 = 0x3C0; +const VBE_DISPI_INDEX_XRES : u16 = 0x1; +const VBE_DISPI_INDEX_YRES : u16 = 0x2; +const VBE_DISPI_INDEX_BPP : u16 = 0x3; +const VBE_DISPI_INDEX_ENABLE : u16 = 0x4; +const VBE_DISPI_INDEX_BANK : u16 = 0x5; +const VBE_DISPI_INDEX_VIRT_WIDTH : u16 = 0x6; +const VBE_DISPI_INDEX_VIRT_HEIGHT : u16 = 0x7; +const VBE_DISPI_INDEX_X_OFFSET : u16 = 0x8; +const VBE_DISPI_INDEX_Y_OFFSET : u16 = 0x9; +const VBE_DISPI_INDEX_VIDEO_MEMORY_64K : u16 = 0xa; -const VGA_AR_PAS: u8 = 0x20; -const VBE_DISPI_ENABLED: u16 = 0x01; +const VGA_AR_PAS : u8 = 0x20; +const VBE_DISPI_ENABLED : u16 = 0x01; +const VBE_DISPI_LFB_ENABLED : u16 = 0x40; + +const PCI_COMMAND: u8 = 0x04; +const PCI_COMMAND_IO: u32 = 0x1; +const PCI_COMMAND_MEMORY: u32 = 0x2; +const PCI_COMMAND_MASTER: u32 = 0x4; +const PCI_COMMAND_SPECIAL: u32 = 0x8; +const PCI_COMMAND_SERR: u32 = 0x100; -const PCIR_COMMAND: u8 = 0x04; -const PCIM_CMD_PORTEN: u32 = 0x0001; -const PCIM_CMD_MEMEN: u32 = 0x0002; fn pci_read_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8) -> u32 { // write config address let address = (1 << 31) | ((bus as u32) << 16) | ((slot as u32) << 11) | ((func as u32) << 8) | (offset as u32); - println!("Address: {:08x}", address); write(pci_base + 0xcf8, address); // do the actual work - read(pci_base + 0xcfc) + let value = read(pci_base + 0xcfc); + debug!("Read {:08x} from PCI address: {:02x}:{:02x}.{:02x} @ 0x{:02x}", value, bus, slot, func, offset); + value } fn pci_write_config(pci_base: usize, bus: u8, slot: u8, func: u8, offset: u8, value: u32) { // write config address let address = (1 << 31) | ((bus as u32) << 16) | ((slot as u32) << 11) | ((func as u32) << 8) | (offset as u32); + debug!("Write {:08x} to PCI address: {:02x}:{:02x}.{:02x} @ 0x{:02x}", value, bus, slot, func, offset); write(pci_base + 0xcf8, address); // do the actual work write(pci_base + 0xcfc, value) } pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { + + debug!("PCI Controller Base: {:08x}", pci_read_config(pci_base, 0x00, 0x00, 0x00, 0x20)); + + let controller = pci_read_config(pci_base, 0x00, 0x00, 0x00, PCI_COMMAND); + pci_write_config(pci_base, 0x00, 0x00, 0x00, PCI_COMMAND, controller | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR); - // enable PCI MMIO let pci_vendor = pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x0); - println!("PCI Device ID: {:08x}", pci_vendor); + debug!("VGA PCI Device ID: {:08x}", pci_vendor); - let pci_state = pci_read_config(pci_base, 0x00, 0x12, 0x00, PCIR_COMMAND); - println!("PCI Config Status: {:08x}", pci_state); - pci_write_config(pci_base, 0x00, 0x12, 0x00, PCIR_COMMAND, pci_state | PCIM_CMD_PORTEN | PCIM_CMD_MEMEN); + // enable port and MMIO for vga card + pci_write_config(pci_base, 0x00, 0x12, 0x00, PCI_COMMAND, pci_read_config(pci_base, 0x00, 0x12, 0x00, PCI_COMMAND) | PCI_COMMAND_MEMORY); + // bar 0 + pci_write_config(pci_base, 0x00, 0x12, 0x00, 0x10, 0x10000000); + debug!("VGA PCI BAR 0: {:08x}", pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x10)); + // bar 2 + pci_write_config(pci_base, 0x00, 0x12, 0x00, 0x18, 0x12050000); + debug!("VGA PCI BAR 2: {:08x}", pci_read_config(pci_base, 0x00, 0x12, 0x00, 0x18)); // vga operations @@ -52,6 +74,10 @@ pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { write(vga_base + VGA_MMIO_OFFSET + (offset as usize), value); }; + let vga_read_io = |offset: u16| -> u8 { + read(vga_base + VGA_MMIO_OFFSET + (offset as usize)) + }; + let vga_write_vbe = |offset: u16, value: u16| { write(vga_base + VBE_MMIO_OFFSET + (offset as usize) * 2, value); }; @@ -60,17 +86,29 @@ pub fn init(pci_base: usize, vga_base: usize, x_res: u16, y_res: u16) { read(vga_base + VBE_MMIO_OFFSET + (offset as usize) * 2) }; - // enable palette access + debug!("VGA Endianess: {:x}", read::(vga_base + 0x604)); + + // unblank vga output + vga_read_io(0x3DA); vga_write_io(VGA_AR_ADDR, VGA_AR_PAS); + debug!("VGA AR: {}", vga_read_io(VGA_AR_ADDR)); + // set resolution and color depth vga_write_vbe(VBE_DISPI_INDEX_XRES, x_res); vga_write_vbe(VBE_DISPI_INDEX_YRES, y_res); + vga_write_vbe(VBE_DISPI_INDEX_VIRT_WIDTH, x_res); + vga_write_vbe(VBE_DISPI_INDEX_VIRT_HEIGHT, y_res); + vga_write_vbe(VBE_DISPI_INDEX_BANK, 0); + vga_write_vbe(VBE_DISPI_INDEX_X_OFFSET, 0); + vga_write_vbe(VBE_DISPI_INDEX_Y_OFFSET, 0); vga_write_vbe(VBE_DISPI_INDEX_BPP, 8); + debug!("VGA Resolution: {}*{}@{}bit", vga_read_vbe(VBE_DISPI_INDEX_XRES), vga_read_vbe(VBE_DISPI_INDEX_YRES), vga_read_vbe(VBE_DISPI_INDEX_BPP)); + // enable vbe let vbe_enable = vga_read_vbe(VBE_DISPI_INDEX_ENABLE); - println!("VBE Status: {:04x}", vbe_enable); - vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable | VBE_DISPI_ENABLED); + vga_write_vbe(VBE_DISPI_INDEX_ENABLE, vbe_enable | VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); + debug!("VBE Status: {:04x}", vga_read_vbe(VBE_DISPI_INDEX_ENABLE)); - println!("QEMU STDVGA driver initialized @ {:x}", vga_base); + info!("QEMU STDVGA driver initialized @ {:x}", vga_base); } diff --git a/kernel/src/drivers/net/e1000.rs b/kernel/src/drivers/net/e1000.rs index fb32d8f..7aa0962 100644 --- a/kernel/src/drivers/net/e1000.rs +++ b/kernel/src/drivers/net/e1000.rs @@ -348,8 +348,8 @@ pub fn e1000_init(name: String, irq: Option, header: usize, size: usize) { let recv_page = unsafe { HEAP_ALLOCATOR.alloc_zeroed(Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()) } as usize; - let send_page_pa = active_table().get_entry(send_page).unwrap().target(); - let recv_page_pa = active_table().get_entry(recv_page).unwrap().target(); + let send_page_pa = active_table().get_entry(send_page).unwrap().target() as u64; + let recv_page_pa = active_table().get_entry(recv_page).unwrap().target() as u64; let send_queue_size = PAGE_SIZE / size_of::(); let recv_queue_size = PAGE_SIZE / size_of::(); let mut send_queue =