Friday, November 21, 2008

Jari OS: device drivers development wellness

I have a lot of time spent with drivers development in different OSes/kernels. Generally it was microkernel or hybrid kernels and I cannot told that this process takes me into pleasure.
Jari OS on other side is a new microkernel OS that can takes in advance all my skills with system design.
Actually every Jari driver is a microkernel service working in userspace like a trusted task. All IO mechanics has a protocol and every time you need to support it with all changes. It's a bad, but for this case I've designed a generic device server layer that will hide all semantics within several library functions.
All of this located in system libraries - in LibOS part.
Include and you will have server implemented. Really is a generic layer - on top of this I will design and implement other layers - for console drivers, input drivers, block drivers and so on.
Like example of this I will show a code snippet of the generic VGA console driver uses this generic layer:


#include <sys/types.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wchar.h>
#include <errno.h>
#include <time.h>
#include <datalib/usrtc.h>
#include <ns/ns.h>
#include <scheduler.h>
#include <proto/rpc.h>
#include <devio/devio.h>
#include <devio/server.h>
#include <termio/termio.h>

#include <termio/term.h>

#include "vga.h"
#include "hwops.h"

#define DRVNAME "vgacons.d"
#define DEVNAME "/console"

static size_t __vga_write(void *buf,uni_rpc_t rpc,size_t size,size_t offset);
static size_t __vga_read(void *buf,uni_rpc_t rpc,size_t size,size_t offset);
static int __vga_ioctl(void *buf,uni_rpc_t *rpc,size_t size);

struct device_ops dev_op = {
__vga_write,
__vga_read,
NULL,
__vga_ioctl,
__vga_write,
__vga_read,
NULL,
NULL,
};

int main(int argc,char **argv)
{
device_server_t *sys;
int r=0;
void *iobuf=mmap(NULL,4096,MMAP_RW|MMAP_PHYS,NOFD,(void*)VGA_TM_BASE);
char buff[256];

task_scheduler_control(getpid(),SYS_SCHED_CTL_SET_PRIORITY,30);

vga_init(iobuf);

vga_print("[vgacons] i've started\n");

sys=malloc(sizeof(*sys));
if(!sys)
abort();

r=init_device_server(sys,DIRECTIO_READ | DIRECTIO_WRITE | HW_READ | HW_WRITE,
2048,4096,512,1,DRVNAME,DEVNAME,&dev_op,4);

sprintf(buff,"sys->allowed = %p\n",sys->allowed);
vga_print(buff);

if(r!=0) {
sprintf(buff,"r=%d\n",r);
vga_print(buff);
abort();
}

vga_print("[vgacons] device server run\n");

device_server_start(sys);

vga_print("[vgacons] :((\n");

return 0;
}

static size_t __vga_write(void *buf,uni_rpc_t rpc,size_t size,size_t offset)
{
char *msg=buf;
size_t rsize=size;

if(size<=sizeof(rpc)) {
return -EINVAL;
}
msg+=sizeof(rpc);
size-=sizeof(rpc);

switch(rpc.arg3) {
case PHYT_WRITE:
uni_print((cschar_t*)msg,size);
break;
case PHYT_WRITEPOS:
uni_printxy((cschar_t*)msg,size,rpc.arg4,rpc.arg5);
break;
case PHYT_SCROLL:
if(rpc.arg4==SCROLL_UP) {
uni_scrollup(rpc.arg5);
uni_printxy((cschar_t*)msg,size,0,0);
} else if(rpc.arg3==SCROLL_DOWN) {
uni_scrolldown(rpc.arg5);
uni_printxy((cschar_t*)msg,size,0,uni_height()-rpc.arg5);
} else
return -EINVAL;
break;
default:
return -EINVAL;
break;
}

return rsize;
}

void ascii_puts(const char *msg)
{
return;
}

static size_t __vga_read(void *buf,uni_rpc_t rpc,size_t size,size_t offset)
{

vga_print("ridden\n");

return 0;
}

static int __vga_ioctl(void *buf,uni_rpc_t *rpc,size_t size)
{
uni_rpc_t rrpc;

if(size<sizeof(rrpc))
return EINVAL;

memcpy(&rrpc,buf,sizeof(rrpc));
switch(rrpc.arg3) {
case PHYT_DISABLEAUTOSCROLL:
uni_scrolldisable();
rpc->rpc_call=0;
break;
case PHYT_ENABLESCROLL:
uni_scrollenable();
rpc->rpc_call=0;
break;
case PHYT_GETSIZE:
rpc->rpc_call=0;
rpc->arg0=uni_width();
rpc->arg1=uni_height();
break;
case PHYT_CLEAR:
uni_clear();
break;
default:
return EINVAL;
break;
}

return 0;
}

No comments: