Added VGA API allowing userspace to easily access 0xB8000.
This commit is contained in:
parent
1026354e98
commit
15ce53919c
|
@ -44,8 +44,8 @@ c/h/stdio.h
|
||||||
|
|
||||||
COMMONOBJS=c++.o thread.o io.o memory.o string.o error.o format.o
|
COMMONOBJS=c++.o thread.o io.o memory.o string.o error.o format.o
|
||||||
SORTIXOBJS:=$(addprefix sortix/,$(COMMONOBJS))
|
SORTIXOBJS:=$(addprefix sortix/,$(COMMONOBJS))
|
||||||
LIBMAXSIOBJS:=$(COMMONOBJS)
|
LIBMAXSIOBJS:=$(COMMONOBJS) sortix-vga.o
|
||||||
HEADERS=error.h io.h memory.h platform.h string.h syscall.h thread.h types.h format.h
|
HEADERS=error.h io.h memory.h platform.h string.h syscall.h thread.h types.h format.h sortix-vga.h
|
||||||
|
|
||||||
OBJS:=$(LIBMAXSIOBJS)
|
OBJS:=$(LIBMAXSIOBJS)
|
||||||
BINS:=libmaxsi.so
|
BINS:=libmaxsi.so
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
sortix-vga.h
|
||||||
|
Provides access to the VGA framebuffer under Sortix. This is highly
|
||||||
|
unportable and is very likely to be removed or changed radically.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LIBMAXSI_SORTIX_VGA_H
|
||||||
|
#define LIBMAXSI_SORTIX_VGA_H
|
||||||
|
|
||||||
|
namespace System
|
||||||
|
{
|
||||||
|
namespace VGA
|
||||||
|
{
|
||||||
|
// This is the contents of a VGA framebuffer used in text mode. The
|
||||||
|
// lower 8 lower bits correspond to an ASCII character, the next 4 bits
|
||||||
|
// is the text color, and the upper 4 bits are the background color.
|
||||||
|
struct Frame
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// The width of each line in characters.
|
||||||
|
const static size_t width = 80;
|
||||||
|
|
||||||
|
// The number of lines.
|
||||||
|
const static size_t height = 25;
|
||||||
|
|
||||||
|
// The data containing the frame.
|
||||||
|
uint16_t text[width * height];
|
||||||
|
|
||||||
|
// An opaque file descriptor that defines this frame. Used to change
|
||||||
|
// the current frame or deleting frames.
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
// Beware: The kernel may or may keep more hidden data here. You may
|
||||||
|
// not depend on the usage of this area.
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Only the kernel may create an instance of this structure.
|
||||||
|
Frame() { }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Allocates a framebuffer able to store VGA data. This buffer is not
|
||||||
|
// relocatable and must remain at this position.
|
||||||
|
Frame* CreateFrame();
|
||||||
|
|
||||||
|
// Sets the process' current VGA frame. If the process currently have
|
||||||
|
// focus, then this is the frame shown on the screen. Any edits done
|
||||||
|
// on this frame while it is active will be shown instantly on the
|
||||||
|
// screen if the process have focus.
|
||||||
|
int ChangeFrame(int fd);
|
||||||
|
|
||||||
|
// Deletes a frame. This is equivalent to IO::Close(fd).
|
||||||
|
int DeleteFrame(int fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,54 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of LibMaxsi.
|
||||||
|
|
||||||
|
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
sortix-vga.cpp
|
||||||
|
Provides access to the VGA framebuffer under Sortix. This is highly
|
||||||
|
unportable and is very likely to be removed or changed radically.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
#include "sortix-vga.h"
|
||||||
|
|
||||||
|
namespace System
|
||||||
|
{
|
||||||
|
namespace VGA
|
||||||
|
{
|
||||||
|
|
||||||
|
DEFN_SYSCALL0(Frame*, SysCreateFrame, 5);
|
||||||
|
DEFN_SYSCALL1(int, SysChangeFrame, 6, int);
|
||||||
|
DEFN_SYSCALL1(int, SysDeleteFrame, 7, int);
|
||||||
|
|
||||||
|
Frame* CreateFrame()
|
||||||
|
{
|
||||||
|
return SysCreateFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ChangeFrame(int fd)
|
||||||
|
{
|
||||||
|
return SysChangeFrame(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DeleteFrame(int fd)
|
||||||
|
{
|
||||||
|
return SysDeleteFrame(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,7 +43,7 @@ DEFINES:=$(DEFINES) -DINITRD
|
||||||
CPPFLAGSRELEASE=-s -O3
|
CPPFLAGSRELEASE=-s -O3
|
||||||
CPPFLAGSDEBUG=
|
CPPFLAGSDEBUG=
|
||||||
CPPFLAGS=-I.. $(CPUDEFINES) $(CPUFLAGS) -std=gnu++0x -Wall -Wextra -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector $(DEFINES) $(CPPFLAGSRELEASE)
|
CPPFLAGS=-I.. $(CPUDEFINES) $(CPUFLAGS) -std=gnu++0x -Wall -Wextra -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector $(DEFINES) $(CPPFLAGSRELEASE)
|
||||||
OBJS=$(CPUOBJS) kernel.o descriptor_tables.o isr.o time.o log.o iprintable.o panic.o keyboard.o memorymanagement.o scheduler.o syscall.o application.o pong.o sound.o pci.o uart.o conway.o test.o http.o vgaterminal.o serialterminal.o descriptors.o device.o ../libmaxsi/libmaxsi-sortix.a
|
OBJS=$(CPUOBJS) kernel.o descriptor_tables.o isr.o time.o log.o iprintable.o panic.o keyboard.o memorymanagement.o scheduler.o syscall.o application.o pong.o sound.o pci.o uart.o conway.o test.o http.o vgaterminal.o serialterminal.o descriptors.o device.o vga.o ../libmaxsi/libmaxsi-sortix.a
|
||||||
JSOBJS:=$(subst .o,-js.o,$(OBJS))
|
JSOBJS:=$(subst .o,-js.o,$(OBJS))
|
||||||
|
|
||||||
all: sortix.bin
|
all: sortix.bin
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "iprintable.h"
|
#include "iprintable.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
|
#include "vga.h"
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix
|
||||||
{
|
{
|
||||||
|
@ -47,7 +48,7 @@ namespace Sortix
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t NumSyscalls = 5;
|
const size_t NumSyscalls = 8;
|
||||||
const Syscall Syscalls[NumSyscalls] =
|
const Syscall Syscalls[NumSyscalls] =
|
||||||
{
|
{
|
||||||
&Scheduler::SysCreateThread,
|
&Scheduler::SysCreateThread,
|
||||||
|
@ -55,6 +56,9 @@ namespace Sortix
|
||||||
&Scheduler::SysSleep,
|
&Scheduler::SysSleep,
|
||||||
&Scheduler::SysUSleep,
|
&Scheduler::SysUSleep,
|
||||||
&SysStdOutPrint,
|
&SysStdOutPrint,
|
||||||
|
&VGA::SysCreateFrame,
|
||||||
|
&VGA::SysChangeFrame,
|
||||||
|
&VGA::SysDeleteFrame,
|
||||||
};
|
};
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||||
|
|
||||||
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
Sortix is free software: you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
vga.h
|
||||||
|
A Video Graphics Array driver.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
#include <libmaxsi/memory.h>
|
||||||
|
#include "vga.h"
|
||||||
|
#include "memorymanagement.h"
|
||||||
|
#include "scheduler.h"
|
||||||
|
|
||||||
|
using namespace Maxsi;
|
||||||
|
|
||||||
|
namespace Sortix
|
||||||
|
{
|
||||||
|
namespace VGA
|
||||||
|
{
|
||||||
|
uint16_t* const vga = (uint16_t* const) 0xB8000;
|
||||||
|
|
||||||
|
DevVGAFrame* currentframe;
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
currentframe = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysCreateFrame(CPU::InterruptRegisters* R)
|
||||||
|
{
|
||||||
|
addr_t page = Page::Get();
|
||||||
|
if ( page == NULL ) { R->eax = 0; return; }
|
||||||
|
|
||||||
|
Process* process = CurrentProcess();
|
||||||
|
addr_t mapto = Page::AlignUp(process->_endcodesection);
|
||||||
|
UserFrame* userframe = (UserFrame*) mapto;
|
||||||
|
|
||||||
|
// TODO: Check if mapto collides with any other memory section!
|
||||||
|
|
||||||
|
if ( !VirtualMemory::MapUser(mapto, page) )
|
||||||
|
{
|
||||||
|
Page::Put(page); R->eax = 0; return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Memory::Set(userframe, 0, sizeof(UserFrame));
|
||||||
|
|
||||||
|
DevVGAFrame* frame = new DevVGAFrame();
|
||||||
|
if ( frame == NULL )
|
||||||
|
{
|
||||||
|
VirtualMemory::UnmapUser(mapto);
|
||||||
|
Page::Put(page); R->eax = 0; return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = process->descriptors.Allocate(frame);
|
||||||
|
if ( fd < 0 )
|
||||||
|
{
|
||||||
|
delete frame;
|
||||||
|
VirtualMemory::UnmapUser(mapto);
|
||||||
|
Page::Put(page); R->eax = 0; return;
|
||||||
|
}
|
||||||
|
|
||||||
|
userframe->fd = fd;
|
||||||
|
|
||||||
|
frame->process = process;
|
||||||
|
frame->physical = page;
|
||||||
|
frame->userframe = userframe;
|
||||||
|
|
||||||
|
process->_endcodesection = mapto + 0x1000;
|
||||||
|
|
||||||
|
R->eax = mapto;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysChangeFrame(CPU::InterruptRegisters* R)
|
||||||
|
{
|
||||||
|
int fd = (int) R->ebx;
|
||||||
|
|
||||||
|
Process* process = CurrentProcess();
|
||||||
|
Device* device = process->descriptors.Get(fd);
|
||||||
|
if ( device == NULL ) { R->eax = -1; return; }
|
||||||
|
|
||||||
|
if ( !device->IsType(Device::VGABUFFER) ) { R->eax = -2; return; }
|
||||||
|
|
||||||
|
DevVGAFrame* frame = (DevVGAFrame*) device;
|
||||||
|
|
||||||
|
ASSERT(frame->process == process);
|
||||||
|
ASSERT(frame->physical != 0);
|
||||||
|
ASSERT(frame->userframe != NULL);
|
||||||
|
ASSERT(frame->onscreen == (frame == currentframe));
|
||||||
|
|
||||||
|
// TODO: Check if userframe is actually user-space writable!
|
||||||
|
|
||||||
|
//Log::PrintF("changeframe: fd = %u, frame = 0x%p, currentframe = 0x%p\n", fd, frame, currentframe);
|
||||||
|
|
||||||
|
// Check if we need to do anything.
|
||||||
|
if ( frame == currentframe ) { R->eax = 0; return; }
|
||||||
|
|
||||||
|
// If there is already a currently used frame? If so, swap it from
|
||||||
|
// the VGA memory and back to the RAM. This should be done
|
||||||
|
// transparently such that the program doesn't feel the difference.
|
||||||
|
if ( currentframe != NULL )
|
||||||
|
{
|
||||||
|
ASSERT(currentframe->physical != frame->physical);
|
||||||
|
ASSERT(currentframe->userframe != frame->userframe);
|
||||||
|
ASSERT(currentframe->onscreen == true);
|
||||||
|
|
||||||
|
if ( currentframe->process != process )
|
||||||
|
{
|
||||||
|
VirtualMemory::SwitchAddressSpace(currentframe->process->GetAddressSpace());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remap the pages in the owning process.
|
||||||
|
// TODO: Check if userframe is actually user-space writable!
|
||||||
|
VirtualMemory::UnmapUser((addr_t) currentframe->userframe);
|
||||||
|
VirtualMemory::MapUser((addr_t) currentframe->userframe, currentframe->physical);
|
||||||
|
|
||||||
|
// Restore the contents of this frame to the VGA framebuffer.
|
||||||
|
Memory::Copy(currentframe->userframe, vga, sizeof(UserFrame));
|
||||||
|
|
||||||
|
if ( currentframe->process != process )
|
||||||
|
{
|
||||||
|
VirtualMemory::SwitchAddressSpace(process->GetAddressSpace());
|
||||||
|
}
|
||||||
|
|
||||||
|
currentframe->onscreen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now move the contents of this frame to the VGA framebuffer.
|
||||||
|
Memory::Copy(vga, frame->userframe, sizeof(UserFrame));
|
||||||
|
|
||||||
|
// Remap the pages such that the current process now uses the vga.
|
||||||
|
VirtualMemory::UnmapUser((addr_t) frame->userframe);
|
||||||
|
VirtualMemory::MapUser((addr_t) frame->userframe, (addr_t) vga);
|
||||||
|
|
||||||
|
frame->onscreen = true;
|
||||||
|
currentframe = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysDeleteFrame(CPU::InterruptRegisters* R)
|
||||||
|
{
|
||||||
|
int fd = (int) R->ebx;
|
||||||
|
|
||||||
|
Process* process = CurrentProcess();
|
||||||
|
Device* device = process->descriptors.Get(fd);
|
||||||
|
process->descriptors.Free(fd);
|
||||||
|
|
||||||
|
if ( device == NULL ) { R->eax = -1; return; }
|
||||||
|
if ( !device->Close() ) { R->eax = -1; return; }
|
||||||
|
R->eax = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DevVGAFrame::DevVGAFrame()
|
||||||
|
{
|
||||||
|
process = NULL;
|
||||||
|
userframe = NULL;
|
||||||
|
physical = 0;
|
||||||
|
onscreen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DevVGAFrame::~DevVGAFrame()
|
||||||
|
{
|
||||||
|
if ( process != NULL ) { ASSERT(CurrentProcess() == process); }
|
||||||
|
if ( userframe != NULL ) { VirtualMemory::UnmapUser((addr_t) userframe); }
|
||||||
|
if ( physical != 0 ) { Page::Put(physical); }
|
||||||
|
}
|
||||||
|
|
||||||
|
nat DevVGAFrame::Flags() { return Device::VGABUFFER; }
|
||||||
|
}
|
33
sortix/vga.h
33
sortix/vga.h
|
@ -25,8 +25,12 @@
|
||||||
#ifndef SORTIX_VGA_H
|
#ifndef SORTIX_VGA_H
|
||||||
#define SORTIX_VGA_H
|
#define SORTIX_VGA_H
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix
|
||||||
{
|
{
|
||||||
|
class Process;
|
||||||
|
|
||||||
namespace VGA
|
namespace VGA
|
||||||
{
|
{
|
||||||
// TODO: Move these to a better place
|
// TODO: Move these to a better place
|
||||||
|
@ -55,7 +59,36 @@ namespace Sortix
|
||||||
|
|
||||||
uint16_t Data[80*25];
|
uint16_t Data[80*25];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UserFrame : public Frame
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
// System Calls.
|
||||||
|
void SysCreateFrame(CPU::InterruptRegisters* R);
|
||||||
|
void SysChangeFrame(CPU::InterruptRegisters* R);
|
||||||
|
void SysDeleteFrame(CPU::InterruptRegisters* R);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DevVGAFrame : public Device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual nat Flags();
|
||||||
|
|
||||||
|
public:
|
||||||
|
DevVGAFrame();
|
||||||
|
~DevVGAFrame();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Process* process;
|
||||||
|
addr_t physical;
|
||||||
|
VGA::UserFrame* userframe;
|
||||||
|
bool onscreen;
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue