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!
Need Suggestions for my new design
- codemastersnake
- Member
- Posts: 148
- Joined: Sun Nov 07, 2004 12:00 am
- Contact:
Re: Need Suggestions for my new design
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.
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
Module Implementation Example
A graphics driver's interface structure might look like this.. using the same variable names as above.
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.
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]
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 */
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;
}
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
}
};
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
Very nice explanation. Something for the wiki?
Cheers,
Adam
Cheers,
Adam