Page 1 of 1

Need Suggestions for my new design

Posted: Mon Aug 04, 2008 11:27 am
by codemastersnake
Hi all!

Well I have been thinking of redesigning my OS from the scratch.
My aim is to design a monolithic kernel. So far what I have been doing is that making classes of every module like console driver, fdc driver and then initializing each of them in main kernel function.

Now what I want is a architecture by which the expansion of the code can be made very easy and also I want to add communication power to the modules. I need suggestion for that. What should I do? or how should I implement that architecture.

Any help would be appreciated!

Re: Need Suggestions for my new design

Posted: Mon Aug 04, 2008 7:05 pm
by kmcguire
The big fact is that different types of drivers need different interfaces. A interface could be implemented in many different ways but the easiest is to use actual call instructions and a __cdecl calling convention. For an example you might have:

PCI Driver Interface
Open( ... )
Close( ... )
...

PCIE Driver Interface
Open( ... )
Close( ... )
...

Graphics Driver Interface
SetPixel( ... )
GetPixel( ... )
BltBlt( ... )
...

Block Device Interface
Read( ... )
Write( ... )
GetBlockSize( ... )
GetGeometryInformation( ... )

PCI Controller Driver Interface
Open( ... )
Close( ... )
... < which very well might actually load the driver for the devices attached to it's controller and buss(es) of the controller> ..

I myself always liked to use a motherboard module. I have to call it a module because there were a lot of people that raised a holy war when I called it a motherboard driver, but I always felt that some motherboard offer specialized features. Take for instance if your OS is compiled and ran on a platform besides the x86 for instance ARM. On ARM the board is generally very specific and at times there exists no way to enumerate the devices attached.. only a driver for the board would know what is there or not. Then you also have the ability to write a general x86 motherboard driver.. oops... module so it can handle all general cases such as built-in floppy controllers at backwards-compatibility ports..ect..ect.

I like the idea of building flexible stacks of driver, but I think there is a cost of time and space. You have a more complicated design, more instructions to execute, and increased storage requirements.

Code: Select all

[motherboard module] 
             |
             +------------[PCI Controller Driver]
                                            |
                                            +---------------------[PCI Driver Interface][Graphics Driver Interface]
Where some drivers actually have more than one interface. Allowing them to export functions specific for the PCI implementation and other specific to the driver they manage such as a graphics cards in which the driver would allow control of through a graphics driver interface.

The actual implementation could be done like this:
Kernel Module Header Included By Module During Compile-Time

Code: Select all

typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;

typedef struct
{
	uint16_t				id;
	void					*iface;
} KINT_ENTRY;

typedef struct
{
	uint32_t				kiv;							/* kernel interface version */
	uint16_t				ecnt;
	KINT_ENTRY		*e;
} KINT_HDR;

typedef struct
{
	void	(*Startup)(void);
	void	(*Shutdown)(void);
} KINT_DRV_MOTHERBOARD;

#define KINT_DRVID_PROCESSOR				1
#define KINT_DRVID_MOTHERBOARD			2
#define KINT_DRVID_PCICONTROLLER		3
#define KINT_DRVID_USBCONTROLLER		4
#define KINT_DRVID_PCIDRIVER				5
#define KINT_DRVID_GRAPHICS					6
#define KINT_DRVID_BLOCK						7
#define KINT_VERSION								0xa3448654			/* 0xa3 major, 0x44 minor, and maybe 0x8654 is the revision.. doesnt matter */
Module Implementation Example

Code: Select all

void gmb_Startup(void);
void gmb_Shutdown(void);

static KINT_DRV_MOTHERBOARD mod_ki_motherboard = {
	&gmb_Startup,
	&gmb_Shutdown,
};

static KINT_ENTRY mod_kie[] = {
	{
		KINT_DRVID_MOTHERBOARD,
		&mod_ki_motherboard
	}
};

KINT_HDR mod_ki_hdr = {
	KINT_VERSION,
	sizeof(mod_kie) / sizeof(KINT_ENTRY),
	&mod_kie[0]
};

void gmb_Startup(void)
{
}
void gmb_Shutdown(void)
{
}

/* some test code to demonstrate the 'ecnt' field works */
int _tmain(int argc, _TCHAR* argv[])
{
	printf("number of interface:%u\n", mod_ki_hdr.ecnt);
	return 0;
}
A graphics driver's interface structure might look like this.. using the same variable names as above.

Code: Select all

static KINT_DRV_PCIDRIVER mod_ki_pcidriver = {
	....
};
static KINT_DRV_GRAPHICS mod_ki_graphics = {
	...
};

static KINT_ENTRY mod_kie[] = {
	{
		KINT_DRVID_PCIDRIVER,
		&mod_ki_pcidriver
	},
	{
		KINT_DRVID_GRAPHICS,
		&mod_ki_graphics
	}
};
Monolithic/Module/Compile-In
The implementation above supports monolithic modules or modules that are compiled in. The only difference is the way the KINT_HDR is aquired. If they are compiled in you need the kernel to either search for modules in it's image OR generate a array during compile-time that the kernel uses to register each driver's KINT_HDR. If you later move the module to loadable you can simply load the image and find a symbol for the KINT_HDR and the same concept applies.

Re: Need Suggestions for my new design

Posted: Tue Aug 05, 2008 2:50 am
by AJ
Very nice explanation. Something for the wiki?

Cheers,
Adam