Comments: Authenticated sender is From: "Alaric B. Williams" To: "Mike A. Harris" Date: Fri, 21 Mar 1997 07:09:16 +0000 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: Re: [opendos] FSSTND Reply-to: alaric AT abwillms DOT demon DOT co DOT uk CC: OpenDOS Mailing List References: <199703150101 DOT CAA04384 AT magigimmix DOT xs4all DOT nl> In-reply-to: Message-ID: <858928000.1021765.0@abwillms.demon.co.uk> On 20 Mar 97 at 7:12, Mike A. Harris wrote: > So basically if there is going to be a OPENDOS.STD file, it > should come installed with certain defaults. If you want to > change them then you have to edit the file. Sounds reasonable to > me. Personally I'd prefer a "worded standard", but this seems a > comfortable comprimise. I'm going to wait and see what everyone > else thinks first. Whatever seems to be the most popular I will > add to the wishlist. Otherwise I'll add them all as > possibilities to the wishlist. Ya know, I've had a thought; some people might like to paint their visions of what OpenDOS should be like and post them. Not wishlists (I want IFS, I want...); actual descriptions of how this can be implemented - so that legacy DOS apps will work, so apps using these APIs can still work on DOS, how modules will be dealt with, how much of the system runs in protected mode, etc. I'll put mine together, we'll see what we get. Much better than idle posturing! (There is now a slight pause while gears click within Alaric's head) I still like the idea of a single TSR that provides the extended API and is licensed to be freely copyable to MS-DOS so we can port our fancy apps there. The TSR shall be a valid DPMI client, and will run under CWSDPMI, Windows DOS box, dosemu, etc. It shall provide a real mode interface which does: - Access to realmode DLLs - Access to protmode DLLs in the way DPMI provides access to real mode ints; allocate a transfer buffer in PM memory, use calls to copy stuff there, use a call to invoke the DLL - Register a DLL (real or prot mode) file with the system (it will be demand loaded) - Request/release memory map regions (screen mem etc), IO port ranges, IRQs. - Enter protected mode The last one deserves some explanation. It is called with a filename for to a protected mode image in our own format (probably just COFF, nice and easy to make with DJGPP). So a real mode stub can contain the protected mode "payload" within the .EXE, after it's official end, and simply call "OD_pm_invoke(argv[0]);". The protected mode environment is thus: All apps/dlls live in the same address space under DPMI, along with the OD.EXE TSR. This has pros and cons. But it's backwards comptabile, so like it or lump it or come up with a better way of doing this! When they are invoked, they are given a pointer to the OD.EXE TSR protected mode entry point, which provides: - Access to protmode DLLs - Access to realmode DLLs via transfer buffers - Register a DLL file - Request/release hardware - End execution Now, the DLL thing is the core of the matter. There are two distinct type, real mode modules (*.M16) and protmode modules (*.M32). I know 32/16 bit isn't the distinction between real and protected mode, but if we keep it that way, 16 bit stuff will always work on <386s and 32 bit stuff will always have protected mode available. Real and protected mode DLLs are very different. Realmode ones must demand load to fit in 640k. They are relocatable, and the header contains an ID string, version, and title. The ID string is remembered by the system when a DLL is registered, and a program uses the following type of interface: void (*print)(char *text); int (*status)(); OD_M16_handle printer = OD_M16_lock("Printer"); OD_M16_bind(printer,&print,"PrintAsciizString"); OD_M16_bind(printer,&status,"ReturnStatusWord"); if(status() == PRINTER_READY) print("Hello!"); OD_M16_release(printer); ........... application locks the DLL, which loads it into RAM if necessary, identifying it by the ID string in the .M16 header. Once locked, it's stuck in memory. It then requests some pointers into named entry points of the DLL, calls the entry points, and unlinks the DLL. Reference counting is used to decide when to zap .M16s from memory. They get special hook entry points: _First_Loaded (reset hardware, called once per session only) _Unload (save state to file if necessary, remove ISRs, option of refusing to unload - ISR must be serviced, etc.) _Loaded (pick up system state from file, install ISRs) An OD-only version of the TSR would cooperate with the kernel over memory management, unloading DLLs when space got tight. The DOS version would have to dump modules as soon as they are not in use. The protected mode DLL interface is pretty similar, only the modules aren't swapped in and out, since we have loads of virtual memory to play with! Now, a set of standard modules is provided: FILER.M16, FILER.M32: Replaces DOS filesystem interface. Special device modules may register with the filer to replace stdout, for example, with a fast direct version. Filers may install under here by "mounting" into the filer tree. TASKS.M16, TASKS.M32: Multitasker interface, preemptive. This one never unloads. The two of them cooperate internally. CONFIG.M16, CONFIG.M32: A nice configuration system (See below) etc. In the FILER case, FILER.M16 can just be a stub that passes on to the FILER.M32 interface. Either way, they share the filer extension tables, so that 32 bit filers are visible from real mode and vice versa. The tasker, being more intricate, will really need to be one module that works in both modes - split into two halves. The 16 bit part deals with legacy tasking and OD-compliant 16 bit tasking (which is nice since all device access is through drivers, which know about multiple tasks and don't get screwed up by them), while the 32 bit part works with the clean world of protected mode tasking. A DLL can fork inside itself, one fork returning to the caller, the other doing something useful. DLLs can use other DLLs as well. The configuration system also specifies system paths. Ther is no standard on directory names, only a standard on directory variables in the environment. Configuration files are like so: INCLUDE Dirs\OpenDOS + "CONFIG\HARDWARE.CFG" INCLUDE Dirs\OpenDOS + "CONFIG\LANGUAGE.CFG" INCLUDE Dirs\Drivers + "\SOUND\SOUND.CFG" GROUP "User information" STRING "UserName" "Alaric B. Williams" INTEGER "UserHeadRadius/cm" 13 ENDGROUP GROUP "Memory areas" MEMORY "Cache" 64Mb ENDGROUP GROUP "Messages" STRING "NoRam" "There isn't enough system RAM, sorry!" ENDGROUP So we might write: puts(OD_env("Messages\NoRam")); If a path is renamed, the OD kernel will change any PATH statements involved in a configuration file. There are some standard configuration files - such as LANGUAGE.CFG, which defines the "Messages" group. Different copies of LANGUAGE.CFG for different languages can be made. Applications can use the standard ones, like NoRam, as well as ones that are added to the OpenDOS configuration via their own configuration file, which should include the standard Dirs\OpenDOS + "OPENDOS.CFG" file. Note that all config files automatically include the config file defining the directory structure by defining the "Dirs" group, so it can find others! Erm... ...that's just about it for now. ABW -- Alaric B. Williams (alaric AT abwillms DOT demon DOT co DOT uk) ---<## OpenDOS FAQ ##>--- Plain HTML: http://www.delorie.com/opendos/faq/