David Given writes:
> 
> >> what if the module had a list of function pointers at the begining of its
> >> address space?  then a snippit of org 0 asm code (well, actually just
> >> data) could be used within each module to set up the pointers properly in
> >> a 16 bit link, and the same asm stubs in the kernel would work for any
> >> module of a given type.  maybe with some cleverness, there could be only
> >> one stub and a bunch of macros or wrappers for accessing it, to make
> >> porting to other platforms easier.
> [...]
> >Oops... looks like I was right, and nobody had tried to implement
> >MSDOS/UMSDOS support in ELKS... I was thinking that using UMSDOS as the
> >primary filesystem would make it more usable (FAT is more commonly used
> >than Minix filesystem -- or am I right?). Maybe I should try again with a
> >newer kernel source.
> 
> UMSDOS is  h u g e. While it *would* make ELKS easier to use, it would most 
> likely use so much space you couldn't use it for everything. Remember you need 
> the UMSDOS, MSDOS and FAT modules to make it work. If you *can* fit it in, 
> it'd be wonderful; but I'd be surprised.
> 
> >Concerning the function pointer business... it might work for kernel
> >_functions_, but I doubt that it can work with kernel _variables_... :)
> 
> You'd have to wrap the major kernel variables in get-set functions. You 
> probably want to do this anyway, for code niceness reasons.
> 
> I was thinking, re the modules, that you could supply a system call that 
> turned a user process (with stack, CS, DS) into a system module:
> 
> struct filesystem_vtable functable = {
>       module_open,
>       module_close,
>       module_mount,
>       ...
> };
> 
> int main(int argc, char* argv[])
> {
>       become_system_module(MODULE_FILESYSTEM, (void*)functable);
> }
> 
> This would make them really easy to load; you just run (as root) the 
> appropriate program. The kernel's already got all the setup code needed. You'd 
> need some protection to stop it being killed when the kernel wasn't expecting 
> it, but that would be easy (give it a negative PID or something).
> 

Thinking in the bath last night I came up with a way of building user space
device drivers which Should work, still be quite clean, and not involve any
far pointers.

We create a meta driver called something like the user device driver which
has a whole load of generically named devices in /dev/udd0 -- /dev/udd<n>.

When a user program wants to become a device driver it does something like
this.

#define DEVICE_NAME "sda"

        struct udd_entry foo;
        struct udd_request bar;

        foo.type = UDD_BLOCK_DEVICE;
        foo.name = DEVICE_NAME;
        foo.no_minors = 5;
        /* etc... */

        x = open("/dev/udd", O_RDWR);
        if ((y = ioctl(x, UDD_INIT_DRIVER, &foo)) != 0) {
                printf("Could not initialise driver.\n");
                exit(1);
        }

        while ((y = ioctl(x, UDD_WAIT_REQUEST, &bar)) == 0) {
                process_device_request(&bar);
        }

Device requests such as open, close, reads, writes, ioctls etc are
all dealt with by calling the kernel with other ioctls which contain
information about the call. If for example it recieved a read() request
the reply would look something like this.

process_read_request(struct udd_request * bar)
{
        char buffer[MAX_SIZE];
        struct udd_request reply;
        int bytes_read;

        bytes-read = get_bytes(&buffer, bar->size);
        reply.req_no = bar->req_no;
        reply.data = &buffer;
        reply.size = bytes-read;
        
        ioctl(x, UDD_REQUEST_COMPLETE, &reply);

        return;
}


I can write the meta driver for this scheme, and a sample driver which will
probably be a loopback driver as this is the most simple to implement.

Is anyone interested in this type of scheme?

Al

Reply via email to