DEVICE -- Program to load/unload a DOS character device driver subsequently
to system boot as a Terminate-and-Stay-Resident program.
DOS Command Syntax (type DEVICE or DEVICE ? for this and other information):
DEVICE [ ]
where: is the device driver file to load
are any (optional) parameters needed by the driver
/? -- Displays this help message
/p -- Permanently loads device driver (disables unloading)
/v -- Verifies no duplicate loading of device driver
/e -- Deallocates environment block (may leave memory hole)
/u -- Unloads device driver most recently loaded by DEVICE
/h -- Manually unhooks interrupt vectors still hooked (only with /u)
/i -- Saves (and restores with /u) interrupt vector contents
Effect: Loads a DOS character device driver dynamically after boot time,
initializes it and links it into the DOS device driver chain,
emulating the function of IBMDOS.COM in loading DOS device drivers
while interpreting the CONFIG.SYS file.
Returns: ERRORLEVEL 0 => "Successful loading/unloading."
ERRORLEVEL 1 => "Error -- displayed message indicates reason."
* DEVICE is compatible with all known versions of DOS (PC-DOS, MS-DOS,
Compaq DOS, Seiko DOS, etc.) 3.10 and newer. It is also compatible with
most ~100% compatible DOS versions as DR-DOS and the OS/2 compatibility box,
and DOS-enhancer shells such as 4DOS.
* "Block" type device drivers, i.e., those that provide access to devices
via a drive letter, such as VDISK, disk partitioners, and CD-ROM devices,
cannot be loaded by this program. Only "character" type device drivers
can be loaded.
* Only device drivers that were previously loaded by DEVICE can be unloaded;
drivers loaded via CONFIG.SYS or other driver-loaders can't/won't be
Use the /u switch to unload the most-recently-loaded driver.
* If the same driver is loaded multiple times, each loading will supercede
the previous; this may or may not cause interaction side-effects, depending
on how the driver in question behaves in such circumstances. In any event,
memory used by prior loadings of the driver will not be reclaimed upon
Use the /v switch to verify prior to loading a particular driver that
a driver of the same device name is not already loaded.
* When DEVICE loads a device driver, it links the driver into the DOS
driver chain, at the front of the chain (just following the NUL device).
After successful loading and linking, the device driver initialization
code is invoked via a simulated DOS Initialize Device Request. The command
line passed to this request appears as if it would have had IBMDOS loaded
it: device driver filespec converted to DOS canonical (absolute path) form,
line contents translated to upper-case, null-terminated, etc. Any options
specified to DEVICE will not appear in this command line.
When DEVICE unloads a device driver it issues a Close Device Request to the
driver, unlinks it from the DOS driver chain, and deallocates the memory
for the driver.
* Because the usual DOS scheme of deploying device drivers is to load them
statically and permanently at system boot time, many drivers have not been
written in anticipation of being unloaded. Such drivers (e.g., mouse
drivers, disk-cachers, ANSI.SYS, etc.) often hook interrupt vectors and
perform other irreversable actions at the time they are loaded and
initialized; unloading them can cause unpredictable or fatal results.
As described above, when DEVICE unloads a driver it closes the device
(equivalent to closing a file) before expunging it from the driver chain.
If the loaded driver has been written such that it allocates resources
when it receives an Open request and disposes of them upon a Close request,
rather than allocating them permanently at initialization time, chances
are that the driver will load and unload hitch-free.
Examples of drivers that load/unload successfully are most communications
and special-device drivers, some '386 protected-mode drivers (e.g., Borland
Turbo Debugger's TDH386.SYS), and almost all graphics drivers (e.g. GSS*CGI,
Use the /p switch to "permanently" load such device drivers that would
cause system failure if inadvertently unloaded.
* DEVICE provides two separate strategies for circumventing the inability to
unload of device drivers because of permanently-hooked interrupts.
Use the /h switch in conjunction with the /u switch when unloading a driver
to unhook all interrupt vectors hooked by the device driver. Note that only
those interrupts which have been hooked in conformance with the official
BIOS interrupt-sharing convention (as described in the IBM BIOS Interface
Technical Reference) will be successfully unhooked. Many drivers do not
hook interrupt in this fashion; this technique will not succeed with such
drivers. The /h switch is ignored unless /u is also specified, or if /i
was specified (see below) at load time.
Use the /i switch when loading a driver to save the state of all interrupt
vectors at the time the driver was loaded. When a driver loaded with the
/i switch is subsequently unloaded, all interrupt vectors will be restored
to those original (saved) contents. This technique adds a penalty of 1K
additional size to the resident memory requirement of the loaded driver,
but subsequent unloading should then always succeed as long as the loaded
driver has no other arcane side-effects upon the DOS operating state.
* Despite some device drivers not being unloadable, virtually all character
device drivers can still be _loaded_ successfully by DEVICE. It is thus
possible to profit by using DEVICE to load such a device driver in a batch
file prior to invoking an application which needs it, thereby avoiding the
"edit CONFIG.SYS/reboot shuffle" or the necessity of always loading from
CONFIG.SYS every one of the myriad drivers that may be needed by various
(Additionally, by moving loadable-but-not-unloadable drivers to load via
DEVICE in AUTOEXEC.BAT instead of CONFIG.SYS, it becomes a simple task
to create an application-level utility to be run at boot time (subject to
some condition, say, presence of a keystroke in the buffer) which allows
the user to select from a menu of drivers to be loaded subsequently.)
* As its first action, DEVICE relocates itself in entirety upward in memory,
freeing the region just after a tiny nub following its original PSP to
become the origin where the device driver gets loaded. This reduces to
an absolute minimum the resident overhead occupied when loading via DEVICE
vs. loading directly by IBMDOS. This overhead consumed is on the order of
300 bytes or less per driver (the actual size is reported in the HELP
As a side note of interest, DEVICE does not automatically relocate itself
as high as possible in contiguous conventional memory. Such a policy would
always automatically displace the resident copy of the COMMAND shell present
there, and require it DOS to reload it every time DEVICE executed. Instead,
DEVICE relocates itself 64K beyond its original load origin, loading to the
highest segment only when limited by available memory.
* The overhead consumed by using DEVICE to load a device driver is in addition
to any environment space reserved by the TSR.
Use the /e switch to forcibly release this environment space, but be aware
that freeing environment space that is allocated physically just prior to
the device driver in memory will not only be unavailable for use, but may
also cause problems with the DOS memory allocation scheme.
* With the capability to load/unload device drivers via DEVICE, this also
provides an excellent implementation method for creating resident utilities.
The DOS device interface offers a natural, relatively full-featured, and
flexible framework for structuring control and status operations to/from
the resident utility, with a much higher degree of standardization than
through the typical TSR approach.
* The maximum memory available to a device driver loadable via DEVICE is
the lesser of 64K or the amount of conventional memory available, minus
any stack space used by DEVICE itself (approximately 100h bytes). Drivers
exceeding these memory requirements (even temporarily) ought not be loaded
via DEVICE (unpredictable results may occur).
0.00 -- Prototype Version
1.00 -- Initial Release (not distributed):
* Added code to issue Close Device request to loaded device
driver when /U (unload) option specified
* Moved more preparation code into transient area to minimize
resident size consumed.
1.01 -- Alpha Test Version:
* Added /P option for "permanent" loading of DEVICE TSR.
* Added /V option to skip loading driver(s) redundantly if
any of them are loaded already.
1.02 -- First Beta Test Version:
* Added code to get command-line option indicator character
* Added /? option -- treated identically to "?".
* Added report of size overhead to /? option.
* Changed options/filespec/params parsing to allow for whitespace
other than space characters.
* Added code to convert specified device driver passed
to Initialize Request to absolute form, accounting for current
drive, directory, and drive substitutions.
* Moved block device checking into TRANSIENT (clobbered-after-load)
area to minimize non-essential resident code.
1.03 -- Second Beta Test Version:
* Fixed lookup within drive substitution table to accomodate
table entry size having changed in DOS 4.xx from DOS 3.xx.
* Changed memory deallocation such that environment block for
DEVICE TSR is not freed unless /E option is specified (to
avoid leaving an unallocated "hole" in default case).
* Added DOS version number checking, limiting to 3.10 and newer.
* Revamped code which converts to canonical form
to make use use of undocumented DOS internal function instead.
* Added startup portion to relocate the loader code to an origin
64K beyond the PSP, and load the device driver (which must be
<64K in size) at the PSP to further contract resident code
to an absolute minimum requirement.
* Added code to ensure that the driver does not exceed the
maximum size allowed/available.
* Added /H switch as supplement to /U to unhook all interrupt
vectors hooked by the device driver (only those interrupts
hooked in conformance with the BIOS interrupt-sharing
* Added /I switch to save interrupt vectors for later restoration
upon unloading the driver.
* Loading/unloading of block device drivers.
Copyright (c) 1990-91 by CINCH Enterprises and Rod Pullmann, Boulder, CO.
All rights reserved. Distributed as Freeware.