Add dispmsg_issue(2).

This commit is contained in:
Jonas 'Sortie' Termansen 2012-12-16 02:10:19 +01:00
parent b380dd49c1
commit 0095983c80
9 changed files with 617 additions and 1 deletions

View File

@ -135,6 +135,7 @@ close.o \
$(CPUDIR)/fork.o \
$(CPUDIR)/signal.o \
$(CPUDIR)/syscall.o \
dispmsg_issue.o \
dlfcn.o \
dup.o \
env.o \

33
libc/dispmsg_issue.cpp Normal file
View File

@ -0,0 +1,33 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of the Sortix C Library.
The Sortix C Library 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.
The Sortix C Library 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 the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
dispmsg_issue.cpp
Send a message to the display engine.
*******************************************************************************/
#include <sys/syscall.h>
#include <sys/display.h>
DEFN_SYSCALL2(int, sys_dispmsg_issue, SYSCALL_DISPMSG_ISSUE, void*, size_t);
extern "C" int dispmsg_issue(void* ptr, size_t size)
{
return sys_dispmsg_issue(ptr, size);
}

View File

@ -0,0 +1,38 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
This file is part of the Sortix C Library.
The Sortix C Library 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.
The Sortix C Library 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 the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
sys/display.h
Display message passing.
*******************************************************************************/
#ifndef INCLUDE_SYS_DISPLAY_H
#define INCLUDE_SYS_DISPLAY_H 1
#include <features.h>
#include <stdint.h>
#include <sortix/display.h>
__BEGIN_DECLS
int dispmsg_issue(void* ptr, size_t size);
__END_DECLS
#endif

View File

@ -92,6 +92,7 @@ crc32.o \
descriptors.o \
device.o \
directory.o \
dispmsg.o \
elf.o \
filesystem.o \
fs/devfs.o \

340
sortix/dispmsg.cpp Normal file
View File

@ -0,0 +1,340 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
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/>.
dispmsg.cpp
User-space message-based interface for video framework access.
*******************************************************************************/
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sortix/display.h>
#include <sortix/syscallnum.h>
#include <sortix/kernel/platform.h>
#include <sortix/kernel/video.h>
#include <sortix/kernel/string.h>
#include "syscall.h"
#include "dispmsg.h"
namespace Sortix {
namespace DisplayMessage {
const uint64_t ONE_AND_ONLY_DEVICE = 0;
const uint64_t ONE_AND_ONLY_CONNECTOR = 0;
__attribute__((unused))
static char* StringOfCrtcMode(struct dispmsg_crtc_mode mode)
{
char bppstr[sizeof(mode.fb_format) * 3];
char xresstr[sizeof(mode.view_xres) * 3];
char yresstr[sizeof(mode.view_yres) * 3];
char magicstr[sizeof(mode.magic) * 3];
snprintf(bppstr, sizeof(bppstr), "%ju", (uintmax_t) mode.fb_format);
snprintf(xresstr, sizeof(xresstr), "%ju", (uintmax_t) mode.view_xres);
snprintf(yresstr, sizeof(yresstr), "%ju", (uintmax_t) mode.view_yres);
snprintf(magicstr, sizeof(magicstr), "%ju", (uintmax_t) mode.magic);
char* drivername = Video::GetDriverName(mode.driver_index);
if ( !drivername )
return NULL;
char* ret = String::Combine(10,
"driver=", drivername, ","
"bpp=", bppstr, ","
"width=", xresstr, ","
"height=", yresstr, ","
"modeid=", magicstr);
delete[] drivername;
return ret;
}
__attribute__((unused))
struct dispmsg_crtc_mode CrtcModeOfString(const char* string, uint64_t driverid)
{
char* xstr = NULL;
char* ystr = NULL;
char* bppstr = NULL;
char* modeidstr = NULL;
char* unsupportedstr = NULL;
struct dispmsg_crtc_mode ret;
ret.control = 0;
if ( !strcmp(string, "driver=none") )
return ret;
if ( !ReadParamString(string,
"width", &xstr,
"height", &ystr,
"bpp", &bppstr,
"modeid", &modeidstr,
"unsupported", &unsupportedstr,
NULL, NULL) )
return ret;
ret.driver_index = driverid;
ret.view_xres = xstr ? atol(xstr) : 0;
delete[] xstr;
ret.view_yres = ystr ? atol(ystr) : 0;
delete[] ystr;
ret.fb_format = bppstr ? atol(bppstr) : 0;
delete[] bppstr;
ret.magic = modeidstr ? atoll(modeidstr) : 0;
delete[] modeidstr;
if ( !unsupportedstr )
ret.control = 1;
delete[] unsupportedstr;
return ret;
}
__attribute__((unused))
static bool TransmitString(struct dispmsg_string* dest, const char* str)
{
size_t size = strlen(str) + 1;
size_t dest_size = dest->byte_size;
dest->byte_size = size;
if ( dest_size < size )
return errno = ERANGE, false;
strcpy(dest->str, str);
return true;
}
__attribute__((unused))
static char* ReceiveString(struct dispmsg_string* src)
{
if ( !src->byte_size )
bad_input:
return errno = EINVAL, (char*) NULL;
char* ret = new char[src->byte_size];
if ( !ret )
return NULL;
memcpy(ret, src->str, src->byte_size);
if ( ret[src->byte_size-1] != '\0' ) { delete[] ret; goto bad_input; }
return ret;
}
static int EnumerateDevices(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_enumerate_devices) )
return errno = EINVAL, -1;
struct dispmsg_enumerate_devices* msg =
(struct dispmsg_enumerate_devices*) ptr;
// TODO: HACK: Only one device is currently supported by our backend.
size_t num_devices = 1;
if ( msg->devices_length < num_devices )
{
msg->devices_length = num_devices;
return errno = ERANGE, -1;
}
msg->devices[0] = ONE_AND_ONLY_DEVICE;
return 0;
}
static int GetDriverCount(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_get_driver_count) )
return errno = EINVAL, -1;
struct dispmsg_get_driver_count* msg =
(struct dispmsg_get_driver_count*) ptr;
if ( msg->device != ONE_AND_ONLY_DEVICE )
return errno = EINVAL, -1;
msg->driver_count = Video::GetNumDrivers();
return 0;
}
static int GetDriverName(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_get_driver_name) )
return errno = EINVAL, -1;
struct dispmsg_get_driver_name* msg =
(struct dispmsg_get_driver_name* ) ptr;
if ( msg->device != ONE_AND_ONLY_DEVICE )
return errno = EINVAL, -1;
char* name = Video::GetDriverName(msg->driver_index);
if ( !name )
return -1;
bool success = TransmitString(&msg->name, name);
delete[] name;
return success ? 0 : -1;
}
static int GetDriver(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_get_driver) )
return errno = EINVAL, -1;
struct dispmsg_get_driver* msg = (struct dispmsg_get_driver*) ptr;
if ( msg->device != ONE_AND_ONLY_DEVICE )
return errno = EINVAL, -1;
msg->driver_index = Video::GetCurrentDriverIndex();
return 0;
}
static int SetDriver(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_set_driver) )
return errno = EINVAL, -1;
struct dispmsg_set_driver* msg = (struct dispmsg_set_driver*) ptr;
if ( msg->device != ONE_AND_ONLY_DEVICE )
return errno = EINVAL, -1;
return errno = ENOSYS, -1;
}
static int SetCrtcMode(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_set_crtc_mode) )
return errno = EINVAL, -1;
struct dispmsg_set_crtc_mode* msg = (struct dispmsg_set_crtc_mode*) ptr;
if ( msg->device != ONE_AND_ONLY_DEVICE )
return errno = EINVAL, -1;
if ( msg->connector != ONE_AND_ONLY_CONNECTOR )
return errno = EINVAL, -1;
char* modestr = StringOfCrtcMode(msg->mode);
if ( !modestr )
return -1;
bool success = Video::SwitchMode(modestr);
delete[] modestr;
return success ? 0 : -1;
}
static int GetCrtcMode(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_get_crtc_mode) )
return errno = EINVAL, -1;
struct dispmsg_get_crtc_mode* msg = (struct dispmsg_get_crtc_mode*) ptr;
if ( msg->device != ONE_AND_ONLY_DEVICE )
return errno = EINVAL, -1;
if ( msg->connector != ONE_AND_ONLY_CONNECTOR )
return errno = EINVAL, -1;
char* modestr = Video::GetCurrentMode();
if ( !modestr )
return -1;
msg->mode = CrtcModeOfString(modestr, Video::GetCurrentDriverIndex());
delete[] modestr;
return 0;
}
static int GetCrtcModes(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_get_crtc_modes) )
return errno = EINVAL, -1;
struct dispmsg_get_crtc_modes* msg = (struct dispmsg_get_crtc_modes*) ptr;
if ( msg->device != ONE_AND_ONLY_DEVICE )
return errno = EINVAL, -1;
if ( msg->connector != ONE_AND_ONLY_CONNECTOR )
return errno = EINVAL, -1;
size_t nummodes;
char** modes = Video::GetModes(&nummodes);
if ( !modes )
return -1;
size_t dest_length = msg->modes_length;
int ret;
if ( nummodes <= dest_length )
{
ret = 0;
for ( size_t i = 0; i < nummodes; i++ )
{
const char* modestr = modes[i];
uint64_t driver_index = Video::LookupDriverIndexOfMode(modestr);
msg->modes[i] = CrtcModeOfString(modestr, driver_index);
}
}
else
{
errno = ERANGE;
ret = -1;
}
msg->modes_length = nummodes;
for ( size_t i = 0; i < nummodes; i++ )
delete[] modes[i];
delete[] modes;
return ret;
}
static int GetMemorySize(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_get_memory_size) )
return errno = EINVAL, -1;
struct dispmsg_get_memory_size* msg =
(struct dispmsg_get_memory_size*) ptr;
msg->memory_size = Video::FrameSize();
return 0;
}
static int WriteMemory(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_write_memory) )
return errno = EINVAL, -1;
struct dispmsg_write_memory* msg = (struct dispmsg_write_memory*) ptr;
if ( msg->device != ONE_AND_ONLY_DEVICE )
return errno = EINVAL, -1;
if ( OFF_MAX < msg->offset )
return errno = EOVERFLOW, -1;
off_t offset = msg->offset;
if ( Video::WriteAt(offset, msg->src, msg->size) < 0 )
return -1;
return 0;
}
static int ReadMemory(void* ptr, size_t size)
{
if ( size != sizeof(struct dispmsg_read_memory) )
return errno = EINVAL, -1;
struct dispmsg_read_memory* msg = (struct dispmsg_read_memory*) ptr;
if ( msg->device != ONE_AND_ONLY_DEVICE )
return errno = EINVAL, -1;
if ( OFF_MAX < msg->offset )
return errno = EOVERFLOW, -1;
off_t offset = msg->offset;
if ( Video::ReadAt(offset, msg->dst, msg->size) < 0 )
return -1;
return 0;
}
// TODO: Secure this system call against bad user-space pointers.
static int sys_dispmsg_issue(void* ptr, size_t size)
{
struct dispmsg_header* hdr = (struct dispmsg_header*) ptr;
if ( size < sizeof(*hdr) )
return errno = EINVAL, -1;
switch ( hdr->msgid )
{
case DISPMSG_ENUMERATE_DEVICES: return EnumerateDevices(ptr, size);
case DISPMSG_GET_DRIVER_COUNT: return GetDriverCount(ptr, size);
case DISPMSG_GET_DRIVER_NAME: return GetDriverName(ptr, size);
case DISPMSG_GET_DRIVER: return GetDriver(ptr, size);
case DISPMSG_SET_DRIVER: return SetDriver(ptr, size);
case DISPMSG_SET_CRTC_MODE: return SetCrtcMode(ptr, size);
case DISPMSG_GET_CRTC_MODE: return GetCrtcMode(ptr, size);
case DISPMSG_GET_CRTC_MODES: return GetCrtcModes(ptr, size);
case DISPMSG_GET_MEMORY_SIZE: return GetMemorySize(ptr, size);
case DISPMSG_WRITE_MEMORY: return WriteMemory(ptr, size);
case DISPMSG_READ_MEMORY: return ReadMemory(ptr, size);
default:
return errno = ENOSYS, -1;
}
}
void Init()
{
Syscall::Register(SYSCALL_DISPMSG_ISSUE, (void*) sys_dispmsg_issue);
}
} // namespace DisplayMessage
} // namespace Sortix

36
sortix/dispmsg.h Normal file
View File

@ -0,0 +1,36 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
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/>.
dispmsg.h
User-space message-based interface for video framework access.
*******************************************************************************/
#ifndef SORTIX_DISPMSG_H
#define SORTIX_DISPMSG_H
namespace Sortix {
namespace DisplayMessage {
void Init();
} // namespace DisplayMessage
} // namespace Sortix
#endif

View File

@ -0,0 +1,162 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2012.
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/>.
display.h
Display message declarations.
*******************************************************************************/
#ifndef SORTIX_INCLUDE_DISPLAY_H
#define SORTIX_INCLUDE_DISPLAY_H
#include <features.h>
#include <stdint.h>
__BEGIN_DECLS
struct dispmsg_string
{
size_t byte_size; // Including the terminating NUL-byte.
char* str;
};
struct dispmsg_crtc_mode
{
uint64_t driver_index;
uint64_t magic;
uint32_t control;
uint32_t fb_format;
uint32_t view_xres;
uint32_t view_yres;
uint64_t fb_location;
uint64_t pitch;
uint32_t surf_off_x;
uint32_t surf_off_y;
uint32_t start_x;
uint32_t start_y;
uint32_t end_x;
uint32_t end_y;
uint32_t desktop_height;
};
struct dispmsg_header
{
uint64_t msgid; // in
};
#define DISPMSG_ENUMERATE_DEVICES 0x00
struct dispmsg_enumerate_devices
{
uint64_t msgid; // in
size_t devices_length; // in, out
uint64_t* devices; // in, *out
};
#define DISPMSG_GET_DRIVER_COUNT 0x01
struct dispmsg_get_driver_count
{
uint64_t msgid; // in
uint64_t device; // in
uint64_t driver_count; // out
};
#define DISPMSG_GET_DRIVER_NAME 0x02
struct dispmsg_get_driver_name
{
uint64_t msgid; // in
uint64_t device; // in
uint64_t driver_index; // in
struct dispmsg_string name; // out
};
#define DISPMSG_GET_DRIVER 0x03
struct dispmsg_get_driver
{
uint64_t msgid; // in
uint64_t device; // in
uint64_t driver_index; // out
};
#define DISPMSG_SET_DRIVER 0x04
struct dispmsg_set_driver
{
uint64_t msgid; // in
uint64_t device; // in
uint64_t driver_index; // in
};
#define DISPMSG_SET_CRTC_MODE 0x05
struct dispmsg_set_crtc_mode
{
uint64_t msgid; // in
uint64_t device; // in
uint64_t connector; // in
struct dispmsg_crtc_mode mode; // in
};
#define DISPMSG_GET_CRTC_MODE 0x06
struct dispmsg_get_crtc_mode
{
uint64_t msgid; // in
uint64_t device; // in
uint64_t connector; // in
struct dispmsg_crtc_mode mode; // out
};
#define DISPMSG_GET_CRTC_MODES 0x07
struct dispmsg_get_crtc_modes
{
uint64_t msgid; // in
uint64_t device; // in
uint64_t connector; // in
size_t modes_length; // in, out
struct dispmsg_crtc_mode* modes; // in, *out
};
#define DISPMSG_GET_MEMORY_SIZE 0x08
struct dispmsg_get_memory_size
{
uint64_t msgid; // in
uint64_t device; // in
uint64_t memory_size; // out
};
#define DISPMSG_WRITE_MEMORY 0x09
struct dispmsg_write_memory
{
uint64_t msgid; // in
uint64_t device; // in
uint64_t offset; // in
size_t size; // in
uint8_t* src; // in, *in
};
#define DISPMSG_READ_MEMORY 0x0A
struct dispmsg_read_memory
{
uint64_t msgid; // in
uint64_t device; // in
uint64_t offset; // in
size_t size; // in
uint8_t* dst; // in, *out
};
__END_DECLS
#endif

View File

@ -77,6 +77,7 @@
#define SYSCALL_TCGETWINSIZE 52
#define SYSCALL_RAISE 53
#define SYSCALL_OPENAT 54
#define SYSCALL_MAX_NUM 55 /* index of highest constant + 1 */
#define SYSCALL_DISPMSG_ISSUE 55
#define SYSCALL_MAX_NUM 56 /* index of highest constant + 1 */
#endif

View File

@ -66,6 +66,7 @@
#include "mount.h"
#include "directory.h"
#include "interrupt.h"
#include "dispmsg.h"
#include "fs/devfs.h"
// Keep the stack size aligned with $CPU/base.s
@ -277,6 +278,9 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
// Initialize the BGA driver.
BGA::Init();
// Initialize the Display Message framework.
DisplayMessage::Init();
// Now that the base system has been loaded, it's time to go threaded. First
// we create an object that represents this thread.
Process* system = new Process;