Portable Driver Interface
Posted: Tue Aug 05, 2008 6:18 pm
I have an idea for a portable driver interface but would like feedback and direction on its development. I know UDI and EDI already exist but they dont fit the simpler design I like.
The basic idea is each driver is written as a relocatable binary, the file format is yet to be defined but ELF is a standard that might handle the loading/relocation. The entry point in the header is always to initdevice.
In general a pdi driver is written with all its supported functions passed to the OS in a device ops struct. A native OS driver acts as a wrapper to the pdi functions. Any functions not suported by the OS are ignored, any functions that an OS requires are included in a specific version. If the function is not handled by the driver the OS either drops back its function support or unloads the driver. A minimum amount of library support is included in the kernel.
The interface is designed for asm using ecx as a parameter count and edx as a pointer to the parameters. C drivers will need a save these values to use the parameters.
An example driver for vga is shown below.
pdi_vga.c
and the OS specific driver
vgadrv.c
This just the simple version to give you an idea. Id like to know if this is something useful or interesting to other OSdevers or not. Thanks.
The basic idea is each driver is written as a relocatable binary, the file format is yet to be defined but ELF is a standard that might handle the loading/relocation. The entry point in the header is always to initdevice.
In general a pdi driver is written with all its supported functions passed to the OS in a device ops struct. A native OS driver acts as a wrapper to the pdi functions. Any functions not suported by the OS are ignored, any functions that an OS requires are included in a specific version. If the function is not handled by the driver the OS either drops back its function support or unloads the driver. A minimum amount of library support is included in the kernel.
The interface is designed for asm using ecx as a parameter count and edx as a pointer to the parameters. C drivers will need a save these values to use the parameters.
An example driver for vga is shown below.
pdi_vga.c
Code: Select all
struct videoop{
// required for every device
int opversion; // driver operations version
int (*initdevice)(void) // initializes the device
int (*resetdevice)(void) // resets the device
int (*enddevice)(void) // stops the device
int (*deviceinfo)(void) // info about the device
// device specific
int (*setmode)(void) // sets the video mode
int (*getmode)(void) // gets the video mode
int (*gotoxy)(void) // set cursor position
int (*getxy)(void) // get cursor position
int (*putchar)(void) // writes a character
int (*getchar)(void) // reads a character
int (*putpixel)(void) // puts a pixel
int (*getpixel)(void) // gets a pixel
// svga/3d acceleration goes here in an extended version
};
#define VGA_OP_VERSION 1
struct videoop vgaops={
.opversion=VGA_OP_VERSION,
.initdevice=initvga,
.resetdevice=resetvga,
.enddevice=endvga,
.deviceinfo=infovga,
.setmode=setmode,
.getmode=getmode,
.gotoxy=gotoxy,
.getxy=getxy,
.putchar=putchar,
.getchar=getchar,
.putpixel=putpixel,
.getpixel=getpixel
};
int initvga(void)
{
int argc,*argv;
int ver;
asm(
mov [argc],ecx
mov [argv],edx
);
if(!argc){
return -1; // no version number
}
ver=*argv[0]; // required version of videoop for OS
if(ver>VGA_OP_VERSION){
return -1; // unsupported version
}
asm(
mov edx,&vgaops // return vgaops in edx
);
return 0;
}
int setmode(void)
{
int argc,*argv;
int mode;
asm(
mov [argc],ecx
mov [argv],edx
);
if(!argc){
return -1; // no mode number
}
return writeregs(mode);
}
vgadrv.c
Code: Select all
struct videoops *vgaops;
struct videoops *initvga(int ver)
{
struct videoops *ops;
int (*initdevice)(void);
initdevice=pdi_vga_entry; // entry point in driver file
asm(
mov edx,&ver
mov ecx,1
);
initdevice();
asm(
mov [ops],edx
);
return ops;
}
int driver_init(...)
{
load("pdi_vga.drv");
vgaops=initvga(1,1); // initdevice vgaops version 1 required
setmode(T80x25x16); // set display to a known mode
return 0;
}
int setmode(int mode)
{
asm(
mov edx,&mode
mov ecx,1
);
return vgaops->setmode();
}