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.EXE with the RAM or NOEMS switch) must be loaded.
  • The kernel must be linked to the UMB pool via the DOS=UMB or DOS=HIGH,UMB directive.

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 MEMMAKER utility, 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 /L switch: 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 specified minsize (or the full driver file size if minsize is omitted).
  • Without the /L switch: 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:

  1. The kernel allocates a Memory Control Block (MCB) in the UMB arena designated for the driver.
  2. The executable file is read from the disk and placed directly into the allocated upper memory space.
  3. 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:

  1. 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.
  2. MS-DOS reads this break address and shrinks the original UMB allocation so that it only covers the area up to the break address.
  3. 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.
  4. The driver is permanently appended to the system's character or block device chain.