How MS-DOS 6.22 Loads Drivers With DEVICEHIGH
This article details the internal procedure MS-DOS 6.22 follows when
processing the DEVICEHIGH directive in
CONFIG.SYS. It covers the system prerequisites required to
access upper memory, the sequence of checks performed by the operating
system, how Upper Memory Blocks (UMBs) are selected and allocated, the
execution of the driver's initialization routine, and the final memory
reduction or fallback actions taken by the kernel.
1. Verification of Upper Memory Support
Before MS-DOS 6.22 can allocate memory in the Upper Memory Area (UMA—the region between 640 KB and 1 MB), specific memory infrastructure must already be active:
- An extended memory manager (
HIMEM.SYS) must be running. - An expanded memory manager capable of providing UMBs
(
EMM386.EXEwith theRAMorNOEMSswitch) must be loaded. - The kernel must be linked to the UMB pool via the
DOS=UMBorDOS=HIGH,UMBdirective.
When the MS-DOS kernel encounters a DEVICEHIGH command,
it queries the XMS driver to verify that the UMB link is established. If
UMB support is not present or initialization has failed, MS-DOS bypasses
upper memory entirely and defaults to loading the driver into
conventional memory as if the standard DEVICE directive had
been used.
2. Directive Parsing and Switch Evaluation
MS-DOS reads the parameters associated with the directive. The basic
syntax is:
DEVICEHIGH [[/L:region1[,minsize1][;region2[,minsize2]...] [/S]]] = [drive:][path]filename [parameters]
The kernel parses any optional switches:
- /L (Load Region): Specifies one or more specific memory regions and the minimum memory size required in each region for loading.
- /S (Shrink): Typically created by the
MEMMAKERutility, this switch instructs the system to shrink the UMB to its minimum size while the driver initializes.
If no switches are provided, MS-DOS prepares to find the largest single available UMB across the entire UMA pool.
3. Scanning and Selecting the Upper Memory Block
MS-DOS 6.22 searches the list of free UMBs maintained by the memory manager:
- With the
/Lswitch: The kernel attempts to allocate memory in the specified order of regions. It checks if the designated region contains an unallocated block at least as large as the specifiedminsize(or the full driver file size ifminsizeis omitted). - Without the
/Lswitch: The kernel traverses the entire UMB arena and selects the largest contiguous free block available.
If no available UMB is large enough to contain the driver binary and satisfy its load requirements, MS-DOS abandons upper memory allocation and immediately falls back to allocating conventional memory (below 640 KB).
4. Binary Loading and Relocation
Once a suitable memory block is allocated:
- The kernel allocates a Memory Control Block (MCB) in the UMB arena designated for the driver.
- The executable file is read from the disk and placed directly into the allocated upper memory space.
- If the driver is an executable requiring relocation, the internal segment references are fixed relative to the starting segment of the allocated UMB.
5. Execution of Driver Initialization (INIT)
MS-DOS calls the driver’s initialization strategy and interrupt
routines with a request header specifying the INIT command
code:
- The driver runs its setup routines (detecting hardware, configuring interrupts, allocating internal buffers).
- Many device drivers require more memory during their initialization phase than they do once resident. The temporary UMB allocation holds this extra setup code and buffer space.
If the driver fails during its initialization routine and returns an error in the request header, MS-DOS aborts the load, unlinks the driver from the device chain, and frees the allocated UMB.
6. Memory Shrinking and Finalization
Upon successful completion of the INIT call:
- The driver returns a "break address" to MS-DOS inside the request header, which defines the end of the resident portion of the driver code and data.
- MS-DOS reads this break address and shrinks the original UMB allocation so that it only covers the area up to the break address.
- Any memory remaining between the break address and the end of the initial block is converted back into an available, free UMB for subsequent drivers or TSR programs.
- The driver is permanently appended to the system's character or block device chain.