### QHIMEM -- DOS XMS Manager, V3.8
===================================
### 1. Description
QHIMEM is an extended (XMS) memory management driver for DOS. It is a replacement for HIMEM, FDXMS, and other similar drivers.
QHIMEM actively supports UMBPCI drivers version 3.70 or higher written by Uwe Sieber. Many users prefer UMBPCI because it uses much less memory than EMM386. If UMBPCI is loaded first, then QHIMEM can be directly loaded into upper memory. In this way, QHIMEM can provide both upper and XMS memory for the DOS system. It contains an "IO catcher" similar to QDBOOT, which can catch IO requests for floppy disks and hard disks above 640K. To avoid DMA errors in the "shadow memory" of UMBPCI, such IO is completed through the DOS workspace buffer in lower memory. In a small system with only XMS access, if UMBPCI is not loaded, QHIMEM does not include the IO catcher by default and is loaded into lower memory. QHIMEM generally occupies 2496 bytes of upper memory for UMBPCI, handles 32 XMS handles, and can reach up to 3456 bytes and handle 128 handles. QHIMEM does not need any "boot" driver itself, nor does it need to load QDBOOT/QDREL for the disk, and does not occupy any lower memory! When QHIMEM is loaded into lower memory by default, it occupies 2048 bytes, handles 32 XMS handles, and can reach up to 3008 bytes and 128 handles.
QHIMEM also supports EMM386 versions 4.49 and 4.95 (corresponding to MS-DOS 6.22 or 7.10) and JEMM drivers. It provides 10-byte XMS handles and other components required by "EMM386" - class drivers. JEMM386/EMM386 requires an XMS manager to be loaded first, so QHIMEM is first loaded in "boot" mode with the /B switch. At this time, it occupies a temporary memory space. After JEMM386/EMM386 is loaded and starts working, QHIMEM itself is loaded into upper memory without the /B parameter. Then it copies all previous temporary data and takes over the XMS operation from its "boot" mode part. Since QHIMEM's normal 32 XMS handles only occupy 384 bytes of lower memory, JEMM386/EMM386 can access these handles at a fixed address. All other logical codes of QHIMEM reside in upper memory, enabling DOS users to run larger programs in the memory space below 640K. When loaded by its own "boot" part, QHIMEM occupies 1728 bytes of upper memory and 384 to 1344 bytes of lower memory (for its table of 32 to 128 handles). If the XMS installation initialization is delayed by DOS until after QHIMEM is loaded, an additional 240 to 480 bytes of upper memory may be required. Similar to the UMBPCI introduction part, when working with "EMM386" - class drivers, QHIMEM can be loaded into lower memory alone (without loading the "boot" part first). At this time, it occupies 2048 bytes, handles 32 XMS handles, and can reach up to 3008 bytes and handle 128 handles.
QHIMEM version 3.8 and above now sets specific DOS driver names to indicate how it is loaded. If the /H switch is used and the driver is loaded into UMBPCI upper memory, a 32-byte long driver header with the driver name "XMSUUU0" will reside in lower memory. Then the automatic installation script can determine whether UMBPCI and QHIMEM are loaded in sequence by "if exist XMSUUUU0". /H and the "header" are necessary because otherwise UMBPCI and QHIMEM leave nothing in lower memory. If the driver is loaded by default (without UMBPCI) or alone, its name will be XMSXXXX0, the same as MS-DOS HIMEM. When the /B switch is used, the driver enters upper memory in "boot" mode, its handle table in lower memory will be named XMSBOOT0, and the driver name will be XMSXXXX0. In this way, the automatic installation script can test whether it is loaded in "boot" mode by "if exist XMSBOOT0" and test the driver itself by "if exist XMSXXXX0".
QHIMEM is written in accordance with the XMS 3.0 specification and can handle XMS memory up to 4GB. A CPU of 80386 or above and at least 512K of extended memory are required. Any system with at least 2MB of RAM can use QHIMEM. For how to use the /N switch to set XMS handles and other switch usages, please see part 4 below. For more introduction to QHIMEM, please refer to part 7 below.
QHIMEM version 3.8 and above adds the above-mentioned driver name support. Thanks a lot to Erwin Veermans for providing such a useful idea. QCACHE version 4.8 and above and QCDROM version 4.2 and above have been upgraded to be able to recognize QHIMEM version 3.8 and above and can continue to use its "fast XMS operation" logical code.
***Note***
Due to the continuous appearance of unpleasant posts on the FreeDOS forum, it is prohibited to use this driver together with FreeDOS. Loading this driver in this system will fail and exit. There is no impact on using this driver in other DOS systems (such as MS-DOS, EDR-DOS, etc.), and technical support is still available.
### 2. No Warranty Statement
QHIMEM is provided to you as free software in its current state, use it at your own risk. And no warranties are made, nor are there any implied warranties of merchantability or fitness for any purpose!
Any questions or comments about the driver can visit Johnson Lam's website <johnson@tmfc.net>. The author of QHIMEM in the United States will try to reply and keep the driver running normally.
### 3. Version Update Records
V3.8 January 14, 2007 QHIMEM now sets specific driver names to facilitate the use of automatic installation scripts. Thanks to Erwin Veermans for this idea.
V3.7 January 9, 2007 Correct the error in QHIMEM setting 128 handles.
V3.6 January 4, 2007 QHIMEM now becomes an all-in-one driver!
V3.5 December 31, 2006 If UMBPCI is not found, QXHIMEM will be loaded into lower memory. Thanks to Erwin Veermans for this idea.
V3.4 December 17, 2006 QXHIMEM supports UMBPCI and JEMM386/EMM386.
V3.3 December 6, 2006 Since UMBPCI version 3.70 has supported QXHIMEM, QXUMBPCI is removed. Thanks to Uwe Sieber! Prohibit using this driver on FreeDOS!
V3.2 October 30, 2006 Add "all-in-one" QXHIMEM driver and QXUMBPCI.
V3.1 August 15, 2006 Correct a serious handle error in QHMBOOT/QHIMEM.
V3.0 August 7, 2006 To fully support EMM386, add QHIMEM2 and QHMBOOT2.
V2.9 July 31, 2006 Correct possible QHIMEM "Int 2Fh/15h" logical error.
V2.8 July 11, 2006 Faster "XMS operation" logical code for QDMA and QCDROM to use.
V2.7 June 27, 2006 Fix the error of QHIMEM "132 Handles" if /N is invalid.
V2.6 June 23, 2006 The memory area of QHMBOOT can be set through the /M switch.
V2.5 June 4, 2006 QHIMEM adds /386 and /486 switches for old CPUs.
V2.4 July 1, 2006 Add /T switch and better extended memory logical code.
V2.3 May 7, 2006 QHIMEM now only occupies 64 bytes of lower memory.
V2.2 May 6, 2006 Correct the "VDS lock" error in QHIMEM that affects EMM386.
V2.1 May 1, 2006 QHIMEM/QHMBOOT is updated to V2.1 to support EMM386.
V1.4 April 29, 2006 Add "reallocates" to fully support the XMS V3.0 specification.
V1.3 April 22, 2006 Correct the empty handle logical code. Slight speed improvement.
V1.2 April 15, 2006 Correct two errors, one large and one small.
V1.1 April 13, 2006 Add 4GB processing capacity and implement most logical codes in line with the XMS 3.0 specification.
V1.0 April 10, 2006 Initial version.
### 4. Switch Options
QHIMEM uses the following switch options:
/386
/486 These switches indicate that the current system uses old CPUs of 80386 or 80486. CPUs after 486 do not need these options. When using "boot" mode, these switches will be ignored by the "boot" driver and must be used when loading the formal driver later.
/B Specify to use "boot" mode. /B makes the driver load into a temporary memory space until the later loaded UMBPCI or EMM386 allows upper memory access. Without /B, the driver will load into normal memory and take over the XMS processing function from its "boot" part. Please refer to the config.sys example in part 5 below.
/H Require QHIMEM to leave a 32-byte long DOS driver name "XMSUUUU0" in lower memory if loaded after UMBPCI. When used with UMBPCI and without the /H switch, the driver will not use any lower memory. The /H switch helps the automatic installation script test whether UMBPCI and QHIMEM are loaded together. If UMBPCI is not loaded or loaded incorrectly, the driver will ignore this parameter.
/Mn Specify a temporary memory space for loading the driver in "boot" mode or for handling IO of UMBPCI upper memory before DOS starts the workspace buffer. Optional values are:
/M1 = 00010300h (64K). /M5 = 00050300h (320K).
/M2 = 00020300h (128K). /M6 = 00060300h (384K).
/M3 = 00030300h (192K). /M7 = 00070300h (448K).
/M4 = 00040300h (256K). /M8 = 00080300h (512K).
If there is no /M switch, the driver defaults to /M5 and uses a 320K area. Please note that some DOS systems do not load from address 0, usually their temporary data is scattered in memory! The /Mn switch allows adjusting the temporary memory area of the driver to find a safe area to use. If not used with UMBPCI and not in "boot" mode, the driver will ignore the /M switch.
/Nnn Indicate how many XMS handles can be used by DOS programs. The value can be 32, 48, 64, 96, or 128. Without the /N switch, the default is 32. If the /T switch indicates using the BIOS "E820h" request test and the driver is loaded alone or with UMBPCI, 48 will be set as the minimum value. In "boot" mode, any value of /N from 32 to 128 is acceptable and will be used in the later normal driver loading. 32 handles work well in most DOS systems, and some large systems with a large number of XMS operations may need more handles.
/Tn Indicate that the driver tries the following BIOS requests to obtain extended memory:
/T1 Only perform "E820h" request.
/T2 Only perform "E801h" request.
/T3 First try "E820h" request, then try "E801h" request.
/T4 Only perform the old 64MB request.
/T5 First try "E820h" request, then try the old 64-MB request.
/T6 First try "E801h" request, then try the old 64-MB request.
/T7 First try "E820h" request, then try "E801h" request, and finally try the old 64-MB request.
Usually, the /T switch can be omitted because the default is /T6. For details about BIOS requests and when to use the /T switch, please refer to part 7 below. In "boot" mode, the "boot" driver must use the /T switch because it must test upper memory first. When loading the driver body, any /T parameter is ignored.
/W If loaded with UMBPCI, indicate using the DOS workspace buffer to handle upper memory IO. In this case, DOS 5.0 or above or a similar DOS system is required. When the /W switch is omitted, either an old DOS system is being used or DOS does not provide the "workspace" function, and at this time QHIMEM will set a 512-byte buffer and a 32-byte header in lower memory. When not used with UMBPCI, the driver ignores the /W switch.
For all switches, users can use "-" instead of "/" according to their preference, and the letters in the switches are case-insensitive.
### 5. Installation and Configuration
QHIMEM is loaded in config.sys. Therefore, your config.sys should have a line like this: DEVICE = QHIMEM.SYS
Example: DEVICE=C:\BIN\QHIMEM /N48 /W
DEVICE=C:\DOS\QHIMEM.SYS /M6 /T7 /B
DEVICEHIGH=C:\BIN\QHIMEM.SYS /486
When UMBPCI version 3.70 or above is used together with QHIMEM, no "boot" driver is required. In this case, UMBPCI is loaded first to allow access to upper memory, and then QHIMEM provides upper memory and XMS memory for DOS and other drivers. JEMM386/EMM386 is an optional component. In a system using only XMS, UMBPCI can be omitted.
The following is an example of config.sys when UMBPCI version 3.70 or above is used together with QHIMEM:
SHELL=C:\DOS\COMMAND.COM C:\DOS /E:512 /P
DEVICE=C:\BIN\UMBPCI.SYS
DEVICE=C:\BIN\QHIMEM /N32 /W
DOS=HIGH,UMB
DEVICE=C:\BIN\EMM386.EXE I=B000-B7FF X=C400-EFFF NOEMS
DEVICEHIGH=C:\BIN\QCACHE.SYS /F /L
DEVICEHIGH=C:\BIN\QCDROM.SYS /D:CDROM1 /UF /L
..
.. Etc.
..
When QHIMEM is loaded alone, it must be the first DOS driver loaded, and it must be loaded in lower memory, as in the following example:
SHELL=C:\DOS\COMMAND.COM C:\DOS /E:512 /P
DEVICE=C:\BIN\QHIMEM.SYS /N32
DOS=HIGH,UMB
DEVICE=C:\DOS\EMM386.EXE I=B000-B7FF NOEMS
..
.. Etc.
..
When QHIMEM is used together with JEMM386/EMM386, generally QHIMEM is first loaded in "boot" mode, then the EMM driver is loaded, and finally QHIMEM is loaded into upper memory. Since the EMM driver does not use "shadow memory" as upper memory, QCACHE/QDMA/QCDROM do not need to use the /L switch. The following is an example of config.sys using the QHIMEM "boot" process:
SHELL=C:\DOS\COMMAND.COM C:\DOS /E:512 /P
DEVICE=C:\BIN\QHIMEM.SYS /N32 /B
DOS=HIGH,UMB
DEVICE=C:\DOS\EMM386.EXE I=B000-B7FF NOEMS
DEVICEHIGH=C:\BIN\QHIMEM.SYS
DEVICEHIGH=C:\BIN\QCACHE.SYS /F
DEVICEHIGH=C:\BIN\QCDROM.SYS /D:CDROM1 /UF
..
.. Etc.
..
Please note that if an EMM driver is used, usually QDBOOT/QDREL is not needed, and QHIMEM will only set its IO catcher if UMBPCI is loaded. If a rare system needs an IO catcher to handle upper memory IO, QHIMEM can also be loaded with QDBOOT/QDREL as in the following example:
SHELL=C:\DOS\COMMAND.COM C:\DOS /E:512 /P
DEVICE=C:\BIN\QHIMEM.SYS /N32 /B
DOS=HIGH,UMB
DEVICE=C:\BIN\QDBOOT.SYS /R /W
DEVICE=C:\DOS\EMM386.EXE I=B000-B7FF NOEMS
DEVICEHIGH=C:\BIN\QDREL.SYS
DEVICEHIGH=C:\BIN\QHIMEM.SYS
DEVICEHIGH=C:\BIN\QDMA.SYS /F /X /L
DEVICEHIGH=C:\BIN\QCDROM.SYS /D:CDROM1 /UF /L
DEVICEHIGH=C:\BIN\QCACHE.SYS /N
..
.. Etc.
..
In this example, QHIMEM with /B temporarily handles XMS requests, then QDBOOT (if used) safely loads the driver into upper memory. Then EMM386/UMBPCI is loaded to allow upper memory access. QDREL (if used) can put QDBOOT's instructions into upper memory. Then the main body of QHIMEM is loaded. QCACHE (or QDMA, when used with QCACHE) should be loaded after QHIMEM so that it can request its XMS buffer. When using QCDROM, it must be loaded after QCAHCE (or QDMA, if also used) to share this XMS buffer. The QCACHE driver must be loaded after QDMA or other separate disk drivers. When there are no other disk drivers, QCACHE can be directly loaded after QHIMEM. Please refer to the instructions of QDMA and QCDROM for more information. All other drivers loaded in config.sys (SETVER.exe, ANSI.SYS, etc.) can be loaded in any order.
### 6. Error Returns
QHIMEM returns error codes in accordance with the standard XMS specification. These error codes are described in detail in the XMS 3.0 specification. Users can obtain the XMS 3.0 specification document from Microsoft or other websites.
### 7. Special Instructions
With UMBPCI loaded, QHIMEM is loaded into upper memory before the DOS system declares it. The memory occupied by QHIMEM is not part of the DOS memory list, so the memory occupied by QHIMEM is not directly listed in the memory occupancy list. Please note that the memory occupancy shows that the occupied space of UMBPCI starts at offset 009Ch in a certain memory block (if there are more than 32 XMS handles, the offset is larger). QHIMEM occupies the part of the space skipped by upper memory due to this offset.
BIOS programs support three extended memory requests. Modern BIOS systems generally can accept all three, but some may not, and BIOS produced before 1994 can only accept the old request! QHIMEM indicates which BIOS extended memory requests need to be used through the /T switch. These three are:
A) BIOS "Int 15h, AX=E820h" request, which provides a list of all memory areas. ROM, ACPI, mapped IO, or other non-usable memory "holes" at any address are recorded. This is the latest (1995) and best BIOS method. The "E820h" request is relatively complex and requires more logical code, so the /T switch must be used to use this request.
B) BIOS "Int 15h, AX=E801h" request, which returns two memory ranges below and above 16MB addresses. This request can produce a memory "hole" below 16MB addresses. Any memory "hole" crossing 16MB addresses will limit the upper limit of memory. When the BIOS does not accept the "E820h" request, it will switch to this request. QHIMEM takes this request as the standard request because it requires less logical code to write and works well in most modern systems. The number of found memories is slightly less than that of the "E820h" request because it only returns 65K memory blocks above 16MB addresses and ignores the remaining fragmented areas.
C) BIOS "Int 15h, AH=88h" request, which returns a memory range up to 64MB addresses. Any memory "hole" below 64MB addresses will limit the boundary of this memory range. This is the old (1980) method. It is usually used in old systems or when both "E820h" and "E801h" requests are rejected.
Users can first try QHIMEM without using the /T switch because the default /T6 value will first try to use the "E801h" request to find usable memory and then use the old 64MB request if necessary. If an error occurs without using /T or not all XMS memory is found, users can try /T4, /T2, and /T1 alone to determine which request is accepted by their BIOS. BIOS produced before 1994 should ignore the "E801h" request and then accept the old 64MB request. If not, this old system needs to use /T4 to load QHIMEM.
According to the XMS 3.0 specification, memory installation initialization does not start until the first driver request. When loaded alone or shared with UMBPCI, QHIMEM temporarily saves the XMS installation initialization code in its XMS handle table. Therefore, the logical code using the "E820h" request requires a 48-item handle table, and 32-item handle tables are sufficient when the "E820h" request is not used. When QHIMEM is loaded in "boot" mode, the XMS installation initialization logical code does not need to use the XMS handle table of QHIMEM in lower memory (this logical code and its "boot" part are stored in a temporary memory area together), so when shared with JEMM386/EMM386, a 32-item handle table can be used.
QHIMEM uses the /386 and /486 switches to indicate that the current system uses an old CPU. In protected mode, XMS operations are completed by BIOS, but some BIOS codes handle XMS operations in an interrupt-disabled state! To avoid "losing" any interrupts, the XMS driver divides XMS operations into multiple small data segments and enables interrupts between each small data segment. Pentium, AMD K5/K6/K7/Athlon, and other newer CPUs are fast enough to allow processing 16K-sized data segments. 486 CPUs need to be divided into 4K data segments, and 386 CPUs need to be divided into 1K data segments so that they do not keep interrupts disabled for too long! Real-mode operations, such as when shared with UMBPCI, are not affected. QHIMEM in "boot" mode temporarily uses 1K data segments for all CPUs. The /386 and /486 switches may be required when loading the driver body after the "boot" mode.
===================================
### 1. Description
QHIMEM is an extended (XMS) memory management driver for DOS. It is a replacement for HIMEM, FDXMS, and other similar drivers.
QHIMEM actively supports UMBPCI drivers version 3.70 or higher written by Uwe Sieber. Many users prefer UMBPCI because it uses much less memory than EMM386. If UMBPCI is loaded first, then QHIMEM can be directly loaded into upper memory. In this way, QHIMEM can provide both upper and XMS memory for the DOS system. It contains an "IO catcher" similar to QDBOOT, which can catch IO requests for floppy disks and hard disks above 640K. To avoid DMA errors in the "shadow memory" of UMBPCI, such IO is completed through the DOS workspace buffer in lower memory. In a small system with only XMS access, if UMBPCI is not loaded, QHIMEM does not include the IO catcher by default and is loaded into lower memory. QHIMEM generally occupies 2496 bytes of upper memory for UMBPCI, handles 32 XMS handles, and can reach up to 3456 bytes and handle 128 handles. QHIMEM does not need any "boot" driver itself, nor does it need to load QDBOOT/QDREL for the disk, and does not occupy any lower memory! When QHIMEM is loaded into lower memory by default, it occupies 2048 bytes, handles 32 XMS handles, and can reach up to 3008 bytes and 128 handles.
QHIMEM also supports EMM386 versions 4.49 and 4.95 (corresponding to MS-DOS 6.22 or 7.10) and JEMM drivers. It provides 10-byte XMS handles and other components required by "EMM386" - class drivers. JEMM386/EMM386 requires an XMS manager to be loaded first, so QHIMEM is first loaded in "boot" mode with the /B switch. At this time, it occupies a temporary memory space. After JEMM386/EMM386 is loaded and starts working, QHIMEM itself is loaded into upper memory without the /B parameter. Then it copies all previous temporary data and takes over the XMS operation from its "boot" mode part. Since QHIMEM's normal 32 XMS handles only occupy 384 bytes of lower memory, JEMM386/EMM386 can access these handles at a fixed address. All other logical codes of QHIMEM reside in upper memory, enabling DOS users to run larger programs in the memory space below 640K. When loaded by its own "boot" part, QHIMEM occupies 1728 bytes of upper memory and 384 to 1344 bytes of lower memory (for its table of 32 to 128 handles). If the XMS installation initialization is delayed by DOS until after QHIMEM is loaded, an additional 240 to 480 bytes of upper memory may be required. Similar to the UMBPCI introduction part, when working with "EMM386" - class drivers, QHIMEM can be loaded into lower memory alone (without loading the "boot" part first). At this time, it occupies 2048 bytes, handles 32 XMS handles, and can reach up to 3008 bytes and handle 128 handles.
QHIMEM version 3.8 and above now sets specific DOS driver names to indicate how it is loaded. If the /H switch is used and the driver is loaded into UMBPCI upper memory, a 32-byte long driver header with the driver name "XMSUUU0" will reside in lower memory. Then the automatic installation script can determine whether UMBPCI and QHIMEM are loaded in sequence by "if exist XMSUUUU0". /H and the "header" are necessary because otherwise UMBPCI and QHIMEM leave nothing in lower memory. If the driver is loaded by default (without UMBPCI) or alone, its name will be XMSXXXX0, the same as MS-DOS HIMEM. When the /B switch is used, the driver enters upper memory in "boot" mode, its handle table in lower memory will be named XMSBOOT0, and the driver name will be XMSXXXX0. In this way, the automatic installation script can test whether it is loaded in "boot" mode by "if exist XMSBOOT0" and test the driver itself by "if exist XMSXXXX0".
QHIMEM is written in accordance with the XMS 3.0 specification and can handle XMS memory up to 4GB. A CPU of 80386 or above and at least 512K of extended memory are required. Any system with at least 2MB of RAM can use QHIMEM. For how to use the /N switch to set XMS handles and other switch usages, please see part 4 below. For more introduction to QHIMEM, please refer to part 7 below.
QHIMEM version 3.8 and above adds the above-mentioned driver name support. Thanks a lot to Erwin Veermans for providing such a useful idea. QCACHE version 4.8 and above and QCDROM version 4.2 and above have been upgraded to be able to recognize QHIMEM version 3.8 and above and can continue to use its "fast XMS operation" logical code.
***Note***
Due to the continuous appearance of unpleasant posts on the FreeDOS forum, it is prohibited to use this driver together with FreeDOS. Loading this driver in this system will fail and exit. There is no impact on using this driver in other DOS systems (such as MS-DOS, EDR-DOS, etc.), and technical support is still available.
### 2. No Warranty Statement
QHIMEM is provided to you as free software in its current state, use it at your own risk. And no warranties are made, nor are there any implied warranties of merchantability or fitness for any purpose!
Any questions or comments about the driver can visit Johnson Lam's website <johnson@tmfc.net>. The author of QHIMEM in the United States will try to reply and keep the driver running normally.
### 3. Version Update Records
V3.8 January 14, 2007 QHIMEM now sets specific driver names to facilitate the use of automatic installation scripts. Thanks to Erwin Veermans for this idea.
V3.7 January 9, 2007 Correct the error in QHIMEM setting 128 handles.
V3.6 January 4, 2007 QHIMEM now becomes an all-in-one driver!
V3.5 December 31, 2006 If UMBPCI is not found, QXHIMEM will be loaded into lower memory. Thanks to Erwin Veermans for this idea.
V3.4 December 17, 2006 QXHIMEM supports UMBPCI and JEMM386/EMM386.
V3.3 December 6, 2006 Since UMBPCI version 3.70 has supported QXHIMEM, QXUMBPCI is removed. Thanks to Uwe Sieber! Prohibit using this driver on FreeDOS!
V3.2 October 30, 2006 Add "all-in-one" QXHIMEM driver and QXUMBPCI.
V3.1 August 15, 2006 Correct a serious handle error in QHMBOOT/QHIMEM.
V3.0 August 7, 2006 To fully support EMM386, add QHIMEM2 and QHMBOOT2.
V2.9 July 31, 2006 Correct possible QHIMEM "Int 2Fh/15h" logical error.
V2.8 July 11, 2006 Faster "XMS operation" logical code for QDMA and QCDROM to use.
V2.7 June 27, 2006 Fix the error of QHIMEM "132 Handles" if /N is invalid.
V2.6 June 23, 2006 The memory area of QHMBOOT can be set through the /M switch.
V2.5 June 4, 2006 QHIMEM adds /386 and /486 switches for old CPUs.
V2.4 July 1, 2006 Add /T switch and better extended memory logical code.
V2.3 May 7, 2006 QHIMEM now only occupies 64 bytes of lower memory.
V2.2 May 6, 2006 Correct the "VDS lock" error in QHIMEM that affects EMM386.
V2.1 May 1, 2006 QHIMEM/QHMBOOT is updated to V2.1 to support EMM386.
V1.4 April 29, 2006 Add "reallocates" to fully support the XMS V3.0 specification.
V1.3 April 22, 2006 Correct the empty handle logical code. Slight speed improvement.
V1.2 April 15, 2006 Correct two errors, one large and one small.
V1.1 April 13, 2006 Add 4GB processing capacity and implement most logical codes in line with the XMS 3.0 specification.
V1.0 April 10, 2006 Initial version.
### 4. Switch Options
QHIMEM uses the following switch options:
/386
/486 These switches indicate that the current system uses old CPUs of 80386 or 80486. CPUs after 486 do not need these options. When using "boot" mode, these switches will be ignored by the "boot" driver and must be used when loading the formal driver later.
/B Specify to use "boot" mode. /B makes the driver load into a temporary memory space until the later loaded UMBPCI or EMM386 allows upper memory access. Without /B, the driver will load into normal memory and take over the XMS processing function from its "boot" part. Please refer to the config.sys example in part 5 below.
/H Require QHIMEM to leave a 32-byte long DOS driver name "XMSUUUU0" in lower memory if loaded after UMBPCI. When used with UMBPCI and without the /H switch, the driver will not use any lower memory. The /H switch helps the automatic installation script test whether UMBPCI and QHIMEM are loaded together. If UMBPCI is not loaded or loaded incorrectly, the driver will ignore this parameter.
/Mn Specify a temporary memory space for loading the driver in "boot" mode or for handling IO of UMBPCI upper memory before DOS starts the workspace buffer. Optional values are:
/M1 = 00010300h (64K). /M5 = 00050300h (320K).
/M2 = 00020300h (128K). /M6 = 00060300h (384K).
/M3 = 00030300h (192K). /M7 = 00070300h (448K).
/M4 = 00040300h (256K). /M8 = 00080300h (512K).
If there is no /M switch, the driver defaults to /M5 and uses a 320K area. Please note that some DOS systems do not load from address 0, usually their temporary data is scattered in memory! The /Mn switch allows adjusting the temporary memory area of the driver to find a safe area to use. If not used with UMBPCI and not in "boot" mode, the driver will ignore the /M switch.
/Nnn Indicate how many XMS handles can be used by DOS programs. The value can be 32, 48, 64, 96, or 128. Without the /N switch, the default is 32. If the /T switch indicates using the BIOS "E820h" request test and the driver is loaded alone or with UMBPCI, 48 will be set as the minimum value. In "boot" mode, any value of /N from 32 to 128 is acceptable and will be used in the later normal driver loading. 32 handles work well in most DOS systems, and some large systems with a large number of XMS operations may need more handles.
/Tn Indicate that the driver tries the following BIOS requests to obtain extended memory:
/T1 Only perform "E820h" request.
/T2 Only perform "E801h" request.
/T3 First try "E820h" request, then try "E801h" request.
/T4 Only perform the old 64MB request.
/T5 First try "E820h" request, then try the old 64-MB request.
/T6 First try "E801h" request, then try the old 64-MB request.
/T7 First try "E820h" request, then try "E801h" request, and finally try the old 64-MB request.
Usually, the /T switch can be omitted because the default is /T6. For details about BIOS requests and when to use the /T switch, please refer to part 7 below. In "boot" mode, the "boot" driver must use the /T switch because it must test upper memory first. When loading the driver body, any /T parameter is ignored.
/W If loaded with UMBPCI, indicate using the DOS workspace buffer to handle upper memory IO. In this case, DOS 5.0 or above or a similar DOS system is required. When the /W switch is omitted, either an old DOS system is being used or DOS does not provide the "workspace" function, and at this time QHIMEM will set a 512-byte buffer and a 32-byte header in lower memory. When not used with UMBPCI, the driver ignores the /W switch.
For all switches, users can use "-" instead of "/" according to their preference, and the letters in the switches are case-insensitive.
### 5. Installation and Configuration
QHIMEM is loaded in config.sys. Therefore, your config.sys should have a line like this: DEVICE = QHIMEM.SYS
Example: DEVICE=C:\BIN\QHIMEM /N48 /W
DEVICE=C:\DOS\QHIMEM.SYS /M6 /T7 /B
DEVICEHIGH=C:\BIN\QHIMEM.SYS /486
When UMBPCI version 3.70 or above is used together with QHIMEM, no "boot" driver is required. In this case, UMBPCI is loaded first to allow access to upper memory, and then QHIMEM provides upper memory and XMS memory for DOS and other drivers. JEMM386/EMM386 is an optional component. In a system using only XMS, UMBPCI can be omitted.
The following is an example of config.sys when UMBPCI version 3.70 or above is used together with QHIMEM:
SHELL=C:\DOS\COMMAND.COM C:\DOS /E:512 /P
DEVICE=C:\BIN\UMBPCI.SYS
DEVICE=C:\BIN\QHIMEM /N32 /W
DOS=HIGH,UMB
DEVICE=C:\BIN\EMM386.EXE I=B000-B7FF X=C400-EFFF NOEMS
DEVICEHIGH=C:\BIN\QCACHE.SYS /F /L
DEVICEHIGH=C:\BIN\QCDROM.SYS /D:CDROM1 /UF /L
..
.. Etc.
..
When QHIMEM is loaded alone, it must be the first DOS driver loaded, and it must be loaded in lower memory, as in the following example:
SHELL=C:\DOS\COMMAND.COM C:\DOS /E:512 /P
DEVICE=C:\BIN\QHIMEM.SYS /N32
DOS=HIGH,UMB
DEVICE=C:\DOS\EMM386.EXE I=B000-B7FF NOEMS
..
.. Etc.
..
When QHIMEM is used together with JEMM386/EMM386, generally QHIMEM is first loaded in "boot" mode, then the EMM driver is loaded, and finally QHIMEM is loaded into upper memory. Since the EMM driver does not use "shadow memory" as upper memory, QCACHE/QDMA/QCDROM do not need to use the /L switch. The following is an example of config.sys using the QHIMEM "boot" process:
SHELL=C:\DOS\COMMAND.COM C:\DOS /E:512 /P
DEVICE=C:\BIN\QHIMEM.SYS /N32 /B
DOS=HIGH,UMB
DEVICE=C:\DOS\EMM386.EXE I=B000-B7FF NOEMS
DEVICEHIGH=C:\BIN\QHIMEM.SYS
DEVICEHIGH=C:\BIN\QCACHE.SYS /F
DEVICEHIGH=C:\BIN\QCDROM.SYS /D:CDROM1 /UF
..
.. Etc.
..
Please note that if an EMM driver is used, usually QDBOOT/QDREL is not needed, and QHIMEM will only set its IO catcher if UMBPCI is loaded. If a rare system needs an IO catcher to handle upper memory IO, QHIMEM can also be loaded with QDBOOT/QDREL as in the following example:
SHELL=C:\DOS\COMMAND.COM C:\DOS /E:512 /P
DEVICE=C:\BIN\QHIMEM.SYS /N32 /B
DOS=HIGH,UMB
DEVICE=C:\BIN\QDBOOT.SYS /R /W
DEVICE=C:\DOS\EMM386.EXE I=B000-B7FF NOEMS
DEVICEHIGH=C:\BIN\QDREL.SYS
DEVICEHIGH=C:\BIN\QHIMEM.SYS
DEVICEHIGH=C:\BIN\QDMA.SYS /F /X /L
DEVICEHIGH=C:\BIN\QCDROM.SYS /D:CDROM1 /UF /L
DEVICEHIGH=C:\BIN\QCACHE.SYS /N
..
.. Etc.
..
In this example, QHIMEM with /B temporarily handles XMS requests, then QDBOOT (if used) safely loads the driver into upper memory. Then EMM386/UMBPCI is loaded to allow upper memory access. QDREL (if used) can put QDBOOT's instructions into upper memory. Then the main body of QHIMEM is loaded. QCACHE (or QDMA, when used with QCACHE) should be loaded after QHIMEM so that it can request its XMS buffer. When using QCDROM, it must be loaded after QCAHCE (or QDMA, if also used) to share this XMS buffer. The QCACHE driver must be loaded after QDMA or other separate disk drivers. When there are no other disk drivers, QCACHE can be directly loaded after QHIMEM. Please refer to the instructions of QDMA and QCDROM for more information. All other drivers loaded in config.sys (SETVER.exe, ANSI.SYS, etc.) can be loaded in any order.
### 6. Error Returns
QHIMEM returns error codes in accordance with the standard XMS specification. These error codes are described in detail in the XMS 3.0 specification. Users can obtain the XMS 3.0 specification document from Microsoft or other websites.
### 7. Special Instructions
With UMBPCI loaded, QHIMEM is loaded into upper memory before the DOS system declares it. The memory occupied by QHIMEM is not part of the DOS memory list, so the memory occupied by QHIMEM is not directly listed in the memory occupancy list. Please note that the memory occupancy shows that the occupied space of UMBPCI starts at offset 009Ch in a certain memory block (if there are more than 32 XMS handles, the offset is larger). QHIMEM occupies the part of the space skipped by upper memory due to this offset.
BIOS programs support three extended memory requests. Modern BIOS systems generally can accept all three, but some may not, and BIOS produced before 1994 can only accept the old request! QHIMEM indicates which BIOS extended memory requests need to be used through the /T switch. These three are:
A) BIOS "Int 15h, AX=E820h" request, which provides a list of all memory areas. ROM, ACPI, mapped IO, or other non-usable memory "holes" at any address are recorded. This is the latest (1995) and best BIOS method. The "E820h" request is relatively complex and requires more logical code, so the /T switch must be used to use this request.
B) BIOS "Int 15h, AX=E801h" request, which returns two memory ranges below and above 16MB addresses. This request can produce a memory "hole" below 16MB addresses. Any memory "hole" crossing 16MB addresses will limit the upper limit of memory. When the BIOS does not accept the "E820h" request, it will switch to this request. QHIMEM takes this request as the standard request because it requires less logical code to write and works well in most modern systems. The number of found memories is slightly less than that of the "E820h" request because it only returns 65K memory blocks above 16MB addresses and ignores the remaining fragmented areas.
C) BIOS "Int 15h, AH=88h" request, which returns a memory range up to 64MB addresses. Any memory "hole" below 64MB addresses will limit the boundary of this memory range. This is the old (1980) method. It is usually used in old systems or when both "E820h" and "E801h" requests are rejected.
Users can first try QHIMEM without using the /T switch because the default /T6 value will first try to use the "E801h" request to find usable memory and then use the old 64MB request if necessary. If an error occurs without using /T or not all XMS memory is found, users can try /T4, /T2, and /T1 alone to determine which request is accepted by their BIOS. BIOS produced before 1994 should ignore the "E801h" request and then accept the old 64MB request. If not, this old system needs to use /T4 to load QHIMEM.
According to the XMS 3.0 specification, memory installation initialization does not start until the first driver request. When loaded alone or shared with UMBPCI, QHIMEM temporarily saves the XMS installation initialization code in its XMS handle table. Therefore, the logical code using the "E820h" request requires a 48-item handle table, and 32-item handle tables are sufficient when the "E820h" request is not used. When QHIMEM is loaded in "boot" mode, the XMS installation initialization logical code does not need to use the XMS handle table of QHIMEM in lower memory (this logical code and its "boot" part are stored in a temporary memory area together), so when shared with JEMM386/EMM386, a 32-item handle table can be used.
QHIMEM uses the /386 and /486 switches to indicate that the current system uses an old CPU. In protected mode, XMS operations are completed by BIOS, but some BIOS codes handle XMS operations in an interrupt-disabled state! To avoid "losing" any interrupts, the XMS driver divides XMS operations into multiple small data segments and enables interrupts between each small data segment. Pentium, AMD K5/K6/K7/Athlon, and other newer CPUs are fast enough to allow processing 16K-sized data segments. 486 CPUs need to be divided into 4K data segments, and 386 CPUs need to be divided into 1K data segments so that they do not keep interrupts disabled for too long! Real-mode operations, such as when shared with UMBPCI, are not affected. QHIMEM in "boot" mode temporarily uses 1K data segments for all CPUs. The /386 and /486 switches may be required when loading the driver body after the "boot" mode.
