



SysInfo


                                                                Version 1.1
                                                              February 1996



SysInfo is a set of hardware and software detection routines. Among the
components and peripherals that are detected are:


*  the video card                    *  serial ports
*  the keyboard type                 *  the processor and co-processor
*  mouse support                     *  the system bus type
*  memory size and configuration     *  the processor mode
*  logical drives and their types    *  PCMCIA support
*  parallel ports                    *  long filenames


Before anything else, let it be known that the author (me) can give no
warranties concerning the correct behaviour of the SysInfo utility, or that
the use of SysInfo will not damage your computer or software setup.

Although I have designed this program with care and have tested it on the
machines I have access to, you should be aware that detection of the hardware/
software components or peripherals is tricky. Some hardware devices use the
same I/O addresses or memory regions for different purposes. An attempt to
detect one device may crash the other. If I know about such conflicts (or
suspect them), I tweak the detection routine to sail on the safe side. If that
is not possible, I throw my hands in the air and don't detect that particular
device (an example of this attitude is the fourth parallel port; SysInfo
totally ignores the possibility of having an LPT4: port because of possible
conflicts with other adapters that "stole" the address). Still, what seems
safe today may be risky when a new card comes out tomorrow. Therefore, I
cannot give any guarantees for any part of the program, and I cannot be held
liable for any damage. Use it at your own risk!



Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  1
    Can I use SysInfo? . . . . . . . . . . . . . . . . . . . . . . . . .  3
    How to use SysInfo?  . . . . . . . . . . . . . . . . . . . . . . . .  3
Function reference . . . . . . . . . . . . . . . . . . . . . . . . . . .  5
Alternative calling mechanisms . . . . . . . . . . . . . . . . . . . . . 17
    Explicit dynamic linking . . . . . . . . . . . . . . . . . . . . . . 17
    Direct call interface  . . . . . . . . . . . . . . . . . . . . . . . 18
Miscellaneous notes  . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

                                                             ITB CompuPhase
ii


"Borland", "Borland C++" and "TurboPascal" are registered trademarks of
    Borland International, Inc.
"IBM" and "OS/2" are registered trademarks of International Business
    Machines Corporation.
"Microsoft" and "Microsoft Windows" are registered trademarks of Microsoft
    Corporation.
"The Norton Utilities" is a trademark of Symantec Corporation.
"CompuPhase" and "Win4C" are registered trademarks of ITB CompuPhase, and
    "Daemon server" is a trademark of ITB CompuPhase.



Copyright (c) 1995--1996, ITB CompuPhase, Brinklaan 74-b, 1404 GL Bussum,
Netherlands (Pays Bas); tel.: +31 35 693 9261; fax: +31 35 693 9293; Com-
puServe: 100115,2074; e-mail: 100115.2074@compuserve.com

No part of this manual may be reproduced by any means, electronic, photocopy-
ing or otherwise, without prior written permission from ITB CompuPhase. The
software associated with this manual may be copied only for back-up purposes.

The examples and programs in this manual have been included for their instruc-
tional value. They have been tested with care, but are not guaranteed for any
particular purpose.

Requests for corrections and additions to the manual and the software can be
directed to ITB CompuPhase at the above address.

Typeset with TEX in "Computer Modern" 11 points. Printed at 26 Feb 1996
1:30 p.m.
                                                          Overview  ---  1

                                 Overview


Many programs need to know something about their environment. So these
programs perform various checks, to see that there are sufficient resources
for them to run. Even if you chose to ask the user what settings to use for
the program (a good decision, in my opinion), it would be very helpful for
the user that your program displays what it has found itself. For example,
the communications program I currently use prompts me whether the modem is on
COM1:, COM2:, COM3 or COM4:. Since I work on different computers, I am always
checking on the back of the computer, or just try each port until it works.
The communications program would be so much better if it told me that the
computer has only two serial ports, and that the mouse is attached to COM1:.
Thus, the modem must be on COM2:.

Checking what hardware and software is available is not always trivial,
however. You have to be careful to what you check and how. Not only is there
a risk that you fail to detect some hardware or software if you don't do
it right, in addition I have frequently crashed a machine because some
detection routine failed to reset something. Detection routines must be
crafted carefully, that is why I created SysInfo.

There are a few very good detection programs: Norton Utilities, CheckIt
and Microsoft Diagnostics (MSD) spring to mind. But these programs have a
different philosophy than what I want to know in my programs. These detection
utilities aim at detecting the "hardware" facts. They give you the number of
physical disks, the line status of the printer port, the type of accelerator
chip on the video card, etc. What SysInfo returns are more the "software"
facts, that is, it tells you what your program can use. In other words, it
returns the logical drives (and their types) rather than the physical disks;
it tells you whether a parallel port is redirected by network software (so the
line status register has no meaning); it gives you the list of supported video
modes, resolutions and colours instead of the brand of the chip; and so on.

What SysInfo does not do, is dump some general list of resources. It does
not walk the MCB list to show you what device drivers and TSRs are present.
It does not browse through the ROM headers to find copyright notices of
BIOS extensions. It does not display the contents of your AUTOEXEC.BAT or
CONFIG.SYS files. All devices and resources that SysInfo displays are what it
specifically and actively searches for.

Another difference, and probably an important one, is that SysInfo is a
daemon. It can be embedded in your program. I use it, and I find it useful.
Hopefully, you will find a use for it too.

If you do not know what a daemon is, or how to use one, look at the "Daemon
server" program that is available from ITB CompuPhase at the address on
page ii. An evaluation version of "Daemon server" is free, and it may be
available on the same disk/BBS/forum that you got SysInfo from. In a few
words, a daemon is like a DLL under Microsoft Windows or IBM OS/2. You can
load it when you need it and unload it when you are done.

For detection of equipment and resources, it is particularly useful to be able
to unload the code after it has done its work. Hardware detection typically
occurs only once in a program, and typically only at startup. You can easily
2  ---  Overview


save what SysInfo has detected in a few global variables and regain the 24
kBytes that SYSINFO.EXE takes.
                                                How to use SysInfo?  ---  3

Can I use SysInfo?

SysInfo version 1.0 is free. Nevertheless, it is copyrighted software. SysInfo
is not public domain software. I cannot guarantee that future versions will
also be free (it depends on the efforts that are needed to maintain SysInfo).

If you want to incorporate SysInfo in your own programs, you need the "Daemon
server" package. The Daemon server product is not free. However, to try
whether you can use it, there is a free evaluation version of Daemon server,
probably on the same BBS or Compuserve forum that you found SysInfo on. The
evaluation version contains details on price and ordering.



How to use SysInfo?

To use SysInfo, you must write a program that loads the SysInfo daemon and
that calls its functions. Details of how to do this are described in the
manual of "Daemon server". Here, I will cover the subject only very briefly.

The SysInfo daemon comes with an example program, SHOWINFO.C, that uses the C
interface to load SysInfo and that calls every function of SysInfo. Segments
of the program SHOWINFO.C are examined below:

       #include <stdio.h>
       #include "daemon.h"
       #include "sysinfo.h"

The three header files contain function prototypes for: standard functions
like printf, general "Daemon server" functions like d_load and SysInfo
functions like si_keyboard.

       void main(void)
       {
         extern D_TABLE sysinfo_table;         /* from SYSINFO&.OBJ */
         short sysinfo_handle;

         if (!d_init()) {
           printf("Daemon server not present\n");
           return;
         } /* if */

         if ((sysinfo_handle = d_load("sysinfo.exe", 0)) > 0xff) {
           printf("Error %d in loading SysInfo\n", sysinfo_handle >> 8);
           return;
         } /* if */
         d_linkall(sysinfo_handle, sysinfo_table);
         . . .

The start of the function main shows the usual code for initializing a
"Daemon server"-based application and loading & linking a daemon. I do not
discuss it here, look up the Daemon server documentation for more information.
4  ---  How to use SysInfo?


After that, the program just calls all detection functions that SysInfo
exports one by one and displays all information that each function returns.
For example:

         . . .
         si_system(&cpu, &fpu, &bus, &mode);
         if (cpu == 0)
           printf("CPU:       8088 or 8086\n");
         else
           printf("CPU:       80%d86\n", cpu);
         printf("FPU:       %s\n", fpu ? "installed" : "unavailable");
         printf("CPU mode:  %s\n", mode<=1 ? "real" : "V86");
         . . .

All pointer arguments may be replaced by NULL, instead of the address of a
variable. So, if you are only interested whether a numeric co-processor is
present, use:

       si_system(NULL, &fpu, NULL, NULL);

Now, we compile the program. This is the command line for Borland C++:

       bcc showinfo.c dlib.obj sysinfo&.obj

And this is the one for Microsoft C:

       cl showinfo.c dlib.obj sysinfo&.obj

For both compilers, you have to add the "bind" step:

       dbind showinfo

In case you are wondering, DBIND.EXE and DLIB.OBJ are part of the "Daemon
server" package, and SYSINFO&.OBJ is a file with "export" definitions.
SYSINFO&.OBJ is included in the SysInfo package, and you can easily make it
again by running DOBJ (from the Daemon server package) on SYSINFO.H.

Well, that is all there is to it. The rest is explained in the function
reference. There is just one more point I would like to make: it may be clumsy
to link your program with SYSINFO&.OBJ if you just want to call one or two
functions. Therefore, SysInfo has an alternative, register based, calling
mechanism. This is explained in a separate chapter.
                                                          si_drives  ---  5

                            Function reference


First a few global remarks:

* All pointer arguments may be NULL. For example, the drivelist argument
  of function si_drives can be set to NULL if you are not interested in the
  details of any drive (but just want to know how many there are).

* If the function returns a version of a driver or an interface, this version
  is encoded in two bytes. The high order byte contains the major version
  and the low order byte contains the minor version number. So a hypothetical
  version 5.12 is encoded (in hexadecimal) as 0x50C.

  If the original interface or driver uses a different format for the version
  (e.g. the XMS interface uses 16-bit BCD, the EMS interface uses 8-bit BCD),
  SysInfo converts it to the format I just described.



si_diskette                                    The physical diskette drive


Syntax:     short D_EXPORT si_diskette(char drive)

            drive      The letter of the drive to check. You should have
                       confirmed that this drive letter refers to a removable
                       drive (using si_drive).

Returns:    One of the following values:
            DDRIVE_NONE    No diskette drive was detected. The function
                           returns this value for removable drives that are
                           not diskette drives (e.g. Syquest drives).
            DDRIVE_360K    360 kBytes.
            DDRIVE_1_2M    1.2 MBytes.
            DDRIVE_720K    720 kBytes.
            DDRIVE_1_44M   1.44 MBytes.
            DDRIVE_2_88MP  2.88 MBytes (on some AMI BIOSes and presumably
                           some IBM PS/2s).
            DDRIVE_2_88M   2.88 MBytes, on most systems.
            DDRIVE_320K    320 kBytes (obsolete).
            DDRIVE_UNKNOWN Future type?

Notes:      The function returns the (maximum) capacity of the diskette drive.
            This needs not to be the capacity of the diskette that is in the
            drive. In fact, this function does not access the diskette in the
            drive.



si_drives                                  The types of all logical drives


Syntax:     short D_EXPORT si_drives(DRIVE_INFO _far *drivelist,
                       short numdrives)

            drivelist  A pointer to an array of structures that will contain
                       the detected drives upon return.
6  ---  si_drives


           numdrives   The size of the array, i.e. the number of DRIVE_INFO
                       structures in the array.

Returns:   The number of drives that is detected. This value can be larger
           that numdrives, because SysInfo may detect more drives than the
           number you requested information on.

Notes:     The maximum number of drives that SysInfo supports is set by
           the DRIVE_NUM constant in SYSINFO.H. This is currently set to 26
           (drives A: to Z:).

           The format of DRIVE_INFO is:

                   typedef struct {
                     char letter;          /* 'A' to 'Z' for drives A: to Z: */
                     short type;           /* one of the DRIVE_TYPE values */
                     unsigned char flags;  /* a combination of the DRV_??? flags */
                   } DRIVE_INFO;

           DRIVE_TYPE is an enum with the following items:
           DRIVE_INVALID   Unknown type (should not occur).
           DRIVE_REMOVABLE Removable drive, such as a diskette drive.
           DRIVE_FIXED     Fixed disk.
           DRIVE_RAM       RAM drive, or VDISK drive.
           DRIVE_CDROM     CD-ROM drive (using MSCDEX).
           DRIVE_NETWORK   Network drive. You can get the full name of the
                           drive in UNC (universal naming convention) with
                           si_fullpath.
           DRIVE_SUBST     Phantom drive created with the DOS command
                           SUBST.

           The flags is set to a combination of bit flags. This value is
           usually only non-zero if you are running Microsoft Windows 95. The
           following flags are defined:
           DRV_CASE_SENSITIVEThe file system is case sensitive.
           DRV_CASE_PRESERVEDThe file system is case insensitive, but the
                             file and directory names are stored with upper
                             and lower case letters.
           DRV_UNICODE       Filenames are in Unicode.
           DRV_LFN_API       Long filename functions are supported.
           DRV_COMPRESSED    The disk is compressed with a DoubleSpace/
                             DriveSpace technique.

           Even though Microsoft Windows 95 claims to support Unicode for
           filenames, it really only supports the ASCII/ANSI subset of
           Unicode. The only difference with the ASCII/ANSI tables then is
           that each character is stored in 16-bits.
                                                        si_fullpath  ---  7


si_ems                                                     Expanded memory


Syntax:     short D_EXPORT si_ems(unsigned short _far *version,
                       unsigned short _far *free)

            version    The version of EMS. The most current version is 4.0
                       (which is encoded as 0x400).

            free       The number of free pages (each page is 16 kBytes).

Returns:    Zero if EMS is not available, a non-zero value if the EMS inter-
            face is available.

Notes:      When you put EMM386.EXE in your CONFIG.SYS with the noems switch
            (for a maximum UMB area), you will see that the EMS interface is
            available, but that there are 0 pages free.



si_fullpath                                    The "real" name of a path


Syntax:     char _far * D_EXPORT si_fullpath(char _far *target,
                       char _far *source, short method)

            target     The string buffer that will receive the full name of
                       the path.

            source     The string that contains a path or filename that you
                       want to parse.

            method     The method to get the full path. If this parameter is
                       1, the function returns a path with only short file
                       and directory names (the 8.3 format). If the value
                       is 2, it returns a path with long filenames if these
                       are available. If the value is 0 (zero), the function
                       only resolves drive names and relative paths, without
                       conversion (or validation) of the file and directory
                       names.

Returns:    A pointer to the argument target, or NULL if the function failed.

Notes:      Setting the method parameter can be set to 1 or 2 only if one of
            the following conditions is met:
            * The file is on a diskette or a hard disk and you are running DOS
              4.0 or above.
            * The file is on a drive for which the interface (the "block
              device driver" or the network support layer) provides the
              "Long Filename" functions. In practice, this probably means
              "when you run in a DOS box in Windows 95", because the VFAT
              virtual device driver of Windows 95 defined these functions.

            In other environments, only short filenames are recognized, and
            si_fullpath returns NULL if method is non-zero.
8  ---  si_keyboard


           This function operates similar to the well known undocumented
           DOS command by the name of "TRUENAME". The lower level DOS
           function 60H was popularized by books like "Undocumented DOS" by
           Andrew Schulman et al. In Windows 95, si_fullpath uses documented
           function 7160H instead.

           The DOS TrueName function accesses the disk. Therefore, you
           may want to check the type of the disk drive before using this
           function. Because of the disk access, DOS could encounter a
           "critical error" while performing this function. SysInfo
           grabs the critical error interrupt when you call si_fullpath
           and restores it upon return.

           According to "Undocumented DOS" second edition, the DOS TrueName
           function does not work on JOIN'ed drives.



si_keyboard                                              The keyboard type


Syntax:     short D_EXPORT si_keyboard(void)

Returns:    Zero for an XT-style keyboard (86 or 87 keys), non-zero for an
            AT-style keyboard (101--102 keys).

Notes:      This routine actually checks whether all of the extended BIOS
            functions for AT-style keyboards are functioning. So it is a more
            solid check than just looking up a flag in the BIOS data area (in
            fact SysInfo ignores the keyboard flag in the BIOS data area).



si_lpt                                            Parallel (printer) ports


Syntax:     short D_EXPORT si_lpt(PORT_INFO _far *lpt_list, short numports)

            lpt_list   An array that will hold the types and base addresses
                       of all detected printer ports.

            numports   The number of elements (PORT_INFO structures) in
                       lpt_list.

Returns:    The number of ports detected.

Notes:      The maximum number of ports that SysInfo can detect is LPT_NUM.
            This value is currently set to 3. (Only a few of the older ---XT-
            style--- computers could support a fourth parallel port; SysInfo
            ignores this fact.)

            The PORT_INFO structure is defined as:

                   typedef struct {
                     short type;   /* type of parallel port */
                     short port;   /* base address of the port */
                   } PORT_INFO;
                                                         si_lptname  ---  9

           Each type field in the PORT_INFO structure is set to one of the
           following values (enum LPT_TYPE):
           LPT_NONE   Not a valid port (no hardware, port not captured).
           LPT_NORMAL Standard, uni-directional printer port.
           LPT_BIDIR  Bidirectional printer port (IBM PS/2 standard).
           LPT_ECP    Enhanced parallel port with DMA support (Hewlett
                      Packard/Microsoft standard).
           LPT_EPP    Enhanced parallel port, sometimes called FPP (a
                      standard created by Xircom, Zenith and Intel, later
                      re-standardized in IEEE 1284).
           LPT_NET    Captured network port (i.e. the network software
                      intercepts prints to this port and send the data to
                      the server). Use si_lptname to get the print queue
                      name.

           The port value of the PORT_INFO structure is not valid for LPT_NET
           types. Otherwise, it gives the base address of the parallel port.

           Although the EPP standards (EPP 1.7 from Xircom/Zenith/Intel and
           IEEE 1284) define many new registers, they did not come up with
           a reliable way to detect the presence of an EPP adapter. SysInfo
           only detects the EPP through the presence of an EPP BIOS. The
           IEEE 1284 standard failed to fully specify the EPP BIOS, however
           (and EPP 1.7 did not define a BIOS interface at all), so not all
           manufacturers adopted the BIOS. What this sums up to is that an
           EPP port often goes undetected.



si_lptname                        The print queue name for a captured port


Syntax:     char _far * D_EXPORT si_lptname(char _far *name, short port)

            name       A string buffer into which the name is copied. This
                       buffer should be at least 128 characters long, in
                       order to hold the longest possible network name.

            port       The number of the port for which to get the network
                       name; LPT1: is 0.

Returns:    A pointer to name if the call is successful, or NULL if the
            indicated port is not captured.

Notes:      This function uses an undocumented DOS/Lan manager function to get
            the list of redirected names. These names are not path names, and
            they have other limits that the maximum path name length in DOS.

            This function is also supported in Lantastic, Novell Netware and
            Microsoft Windows 3.11 (Windows for Workgroups).
10  ---  si_memory



si_memory                                 Conventional and extended memory


Syntax:     void D_EXPORT si_memory(unsigned short _far *dos, unsigned short
                       _far *base, unsigned short _far *extended)

            dos        A pointer to the variable that receives the amount of
                       memory that DOS has at its disposition. This value is
                       read from the BIOS data area.

            base       A pointer to the variable that receives the total
                       conventional memory. This value is read from CMOS.

            extended   A pointer to the variable that receives the total
                       extended memory. This value is also read from CMOS.

Notes:      All values are in kBytes.



si_modelist                        All video modes the video card supports


Syntax:     short D_EXPORT si_modelist(VIDEO_MODE _far *modes, short nummodes)

            modes      An array of structures that will contain information
                       on every supported video mode.

            nummodes   The number of elements (i.e. the number of VIDEO_MODE
                       structures) in the modes array.

Returns:    The number of modes detected by SysInfo. This value may be larger
            that nummodes.

Notes:      The VIDEO_MODE structure is defined thus:

                   typedef struct {
                     short mode;         /* mode number */
                     short graphic;      /* 1 for a graphic mode, 0 for a text mode */
                     short resx, resy;   /* resolution in pixels or in characters */
                     short colour_bits;  /* 1=monochrome, 2=4 colors, 4=16 colors,... */
                   } VIDEO_MODE;

            The mode number usually is the BIOS mode number (for modes 0x13
            and below) or the VESA mode number (modes 0x100 and above). There
            are a few odd values in the mode list:

            * Mode 8 stands for a special VGA mode with 256 colors in a
              resolution of 360 x 480. This mode was invented/discovered by
              Michael Abrash, and used in a few IBM products. It was IBM who
              named this mode VGA8, so it looked only fair to give it mode
              number 8 (this mode number was originally reserved for the
              ---now extinct--- PC Junior).
                                                          si_mouse  ---  11

              IBM did not give the VGA8 mode a "mode number"; the IBM
              products program the hardware directly. I concocted the mode
              number, because the "Fast Graphic" modules (a set of drivers/
              daemons for fast graphic drawing) use a mode number. Inventing
              a new mode number for an otherwise unsupported video mode was
              preferable to adding an exceptional case to the interface of the
              Fast Graphic drivers.

            * Mode 0xB (or 11) is for the Hercules adapter (the original card:
              720 x 348 monochrome). This mode number is used by Microsoft's
              MSHERC driver (which was distributed with their C compilers up
              to version 6.0) and, again, by the Fast Graphic drivers.



si_mouse                                              The mouse and driver


Syntax:     void D_EXPORT si_mouse(short _far *type, short _far *software,
                       short _far *port)

            type       A pointer to the variable that receives the type of
                       the mouse. Its value is one of the following:
                       MOUSE_NONE    No mouse detected.
                       MOUSE_BUS     Microsoft compatible bus mouse.
                       MOUSE_MSSER   Microsoft compatible serial mouse.
                       MOUSE_INPORT  InPort mouse.
                       MOUSE_PS2     IBM PS/2 style mouse.
                       MOUSE_HP      HP mouse (as returned from the mouse
                                     driver).
                       MOUSE_UNKNOWN Mouse installed, but the type is
                                     unknown.

            software   A pointer to the variable that receives the driver
                       version. It is zero if no driver is installed.
                       The driver must conform the Microsoft Mouse driver
                       specification.

            port       A pointer to the variable that receives the serial
                       port address to which the mouse is installed. This can
                       currently only be detected if the mouse is hardware
                       compatible with the Microsoft Mouse (i.e. it can only
                       be detected if the mouse type is MOUSE_MSSER).

Notes:      This function is able to detect the Microsoft Mouse or a com-
            patible mouse even if no driver is installed. It can also detect
            the IBM PS/2 style mouse without driver. The IBM PS/2 mouse is
            detected by checking BIOS support for the mouse.

            The values for type are the same as what the Microsoft mouse
            driver returns (with the exception of MOUSE_UNKNOWN), but SysInfo
            double-checks the values. So for example, if the driver says that
            a "bus" mouse is attached but the mouse responds to the serial
            test, SysInfo identifies it as a serial mouse.
12  ---  si_pcmcia


           The serial mouse test fails in a DOS box under Microsoft Windows
           95, because that environment blocks all access to the serial port
           to which a mouse is attached. A serial mouse type will be flagged
           as MOUSE_UNKNOWN by SysInfo under WIndows 95. Microsoft Windows
           3.x allows the serial ports to be read and written, so the results
           are correct.

           If the driver version returns 1.0, the real version is unknown.
           SysInfo sets the driver version to 1.0 if a driver is present, but
           it does not implement the "version request" function.

           SysInfo detects the mouse driver by asking for "the number of
           button presses since the last call". This call is reliable and it
           does not change the status of the mouse. However, if your program
           also uses this function of the mouse driver (function 5), the
           program may loose a button click while SysInfo is loading.
           (The type of the mouse is determined at the startup of the
           SysInfo daemon ---like most other tests--- and not when you
           call si_mouse.)

           The port argument receives an I/O address, like 0x3F8. To map
           this to a port number (COM1: through COM4:), you can use different
           strategies:
           * Use a fixed mapping of addresses to port numbers, saying that
             0x3F8 is COM1:, 0x2F8 is COM2:, 0x3E8 is COM3: and 0x2E8 is
             COM4:.
           * Look up the BIOS Data area for the serial port address, and use
             the sequence number as the port number.
           * Ask SysInfo for the list of serial ports, and look up the
             address in the list that si_rs232 returns. The index in the list
             is the COM port. This is what SHOWINFO does.

           The port number is only filled in for serial mice.



si_pcmcia                              PCMCIA support (portable computers)


Syntax:     short D_EXPORT si_pcmcia(unsigned short _far *version, short _far
                       *sockets)

            version    The version of the PCMCIA interface (zero if PCMCIA is
                       not available).

            sockets    The number of PCMCIA sockets.

Returns:    Zero if PCMCIA is not available, a non-zero value if the PCMCIA
            interface is available.
                                                         si_system  ---  13


si_rs232                                                  The serial ports


Syntax:     short D_EXPORT si_rs232(PORT_INFO _far *rs232list, short numports)

            rs232list  An array that will hold the types and base addresses
                       of all detected serial ports.

            numports   The number of elements (PORT_INFO structures) in
                       rs232list.

Returns:    The number of ports detected.

Notes:      The maximum number of ports that SysInfo can detect is RS232_NUM.
            This value is currently set to 4.

            SysInfo imitates DOS in the numbering of serial ports; it always
            numbers sequentially. For example, if you have serial ports
            installed at addresses 0x3F8 and 0x3E8, SysInfo (like DOS)
            identifies these as COM1: and COM2:. But many other programs
            (perhaps even most other programs) use a fixed mapping of address
            to COM port, and identify the serial ports as COM1: and COM3:.

            The PORT_INFO structure is defined as:

                   typedef struct {
                     short type;   /* type of the RS232 port */
                     short port;   /* base address of the port */
                   } PORT_INFO;

            The type of the PORT_INFO structure is set to one of the following
            (enum RS232_TYPE):
            RS_NONE    No serial port found at this address.
            RS_8250    8250, 8250-B or 8250C; 56000 baud max.
            RS_16450   16450 or 8250A; 115200 baud max.
            RS_16C1450 16450 with software controlled power down & reset.
            RS_16550A  Bad FIFO type of 16550.
            RS_16550AF 16550AF, 16550C or 16550CF (good FIFO types).
            RS_16C1550 16550 with software controlled power down & reset.
            RS_16552   Dual UART.
            RS_82510   Intel instead of National Semiconductor.

            The port field holds the base address of the serial port (e.g.
            0x3F8 for COM1:).



si_system                        The processor, co-processor, bus and mode


Syntax:     void D_EXPORT si_system(short _far *cpu, short _far *fpu, short
                       _far *bus, short _far *mode)

            cpu        A pointer to the variable that receives the processor
                       number. This value is one of the following (enum
                       CPU_TYPE):
                       CPU_8086     8088 or 8086 (or NEC V20/V30)
14  ---  si_system


                       CPU_80186    80186 or 80188
                       CPU_80286
                       CPU_80386    Includes 386SX, 386SLC and others
                       CPU_80486    Includes 486SX, 486SLC and others
                       CPU_PENTIUM  The '586, really

           fpu         A pointer to the variable that receives the status of
                       the numerical co-processor. This value consists of an
                       enumaration and bit flags (as it is possible to have
                       two co-processors in the system. The low byte is one
                       of the following (enum FPU_TYPE):
                       FPU_NONE     No Intel co-processor installed
                       FPU_8087     The 8087
                       FPU_80287    The 80287
                       FPU_80387    The 80387
                       FPU_80487    Either the internal FPU of a 80486DX
                                    or the 80487 (in combination with a
                                    80486SX)
                       FPU_80587    Pentium with an internal FPU
                       FPU_587BUG   A Pentium with the infamous FDIV bug

                       The high byte has bits set for every additional
                       processor that is found. Currently, only the "Weitek
                       Abacus" 3167 or 4167 processors are defined.
                       FPU_WEITEK   Weitek Abacus 3167 or 4167

           bus         A pointer to the variable that receives the sys-
                       tem bus. This value is one of the following (enum
                       BUS_TYPE):
                       BUS_PC       Old 8-bit bus in PC or PC-XT.
                       BUS_PCJR     PC junior.
                       BUS_UNKNOWN  Other system based on a bus for 8088 or
                                    8086.
                       BUS_XT286    80286 based XT (short-lived).
                       BUS_ISA      16-bit ISA bus or AT-bus.
                       BUS_EISA     Compaq's idea of a good bus.
                       BUS_MCA      IBM's idea of a good bus.
                       BUS_PCI      Intel's idea of a good bus.

           mode        A pointer to the variable that receives the mode the
                       processor runs in. This value is one of the following
                       (enum CPU_MODE):
                       MODE_REALONLY  This processor can only run in real
                                      mode.
                       MODE_REAL      Real mode.
                       MODE_PROT      Protected mode (this value should
                                      never be returned, because Daemon
                                      server does not support protected mode
                                      at the moment).
                       MODE_V86       Virtual 86 mode (e.g. a DOS box under
                                      Microsoft Windows or when running an
                                      EMS emulator like EMM386).
                                                          si_video  ---  15

Notes:     The Intel co-processor is checked by executing and verifying
           several co-processor instructions. SysInfo does not check the co-
           processor flag in the BIOS data area. Therefore, to make SysInfo
           stop detecting a co-processor on a 80486 or 80586 processor, you
           must disable the internal co-processor in the chip by modifying
           the CR0 register.

           The Weitek Abacus processors are memory mapped devices that can
           only be accessed from protected mode (on a 80386 or higher) or
           from Virtual 86 mode. SysInfo queries EMM386 for the presence
           of the Weitek processor. Therefore, a machine must have EMM386
           installed for SysInfo to detect the Weitek processor. Due to a
           problem with the EMM386 that comes with Windows 95, the Weitek
           processor is currently not detected in a DOS box in Windows 95.

           Machines with a PCI bus usually have a combination of a few PCI
           buses and a few (old style) ISA buses. SysInfo does currently not
           detect how many PCI slots there are.



si_video                               The video card and software support


Syntax:     void D_EXPORT si_video(short _far *type,
                       unsigned short _far *memory, short _far *chipset,
                       short _far *software, unsigned short _far *version)

            type       A pointer to the variable that receives the type of
                       the video card. It is one of the following values
                       (enum VIDEO_HARDWARE):
                       VH_UNKNOWN   Unknown video card.
                       VH_NONE      No display or graphics adapter present.
                       VH_MDA       IBM Monochrome Display Adapter.
                       VH_CGA       IBM Color Graphics Adapter.
                       VH_EGA       IBM Enhanced Graphics Adapter with an
                                    enhanced display.
                       VH_EGA_CGD   EGA with a CGA display.
                       VH_EGA_MONO  EGA with an MDA display.
                       VH_MCGA      IBM Multi-Color Graphics Array (the
                                    original "model 30" in IBM's PS/2
                                    series).
                       VH_MCGA_MONO MCGA with a monochrome analogue monitor.
                       VH_VGA       IBM Virtual Graphics Array.
                       VH_VGA_MONO  VGA with a monochrome analogue monitor.
                       VH_HERCULES  Monochrome Hercules card (with an MDA
                                    display).
                       VH_SVGA      Generic SuperVGA (with VESA support).
                       VH_SVGA_MONO Generic SuperVGA with a monochrome
                                    monitor.
                       VH_8514      IBM 8514/A
                       VH_XGA       IBM Extended Graphics Array.
                       VH_XGA_MONO  XGA with a monochrome monitor.

            memory     A pointer to the variable that receives the amount of
                       video memory in kBytes.
16  ---  si_xms


           chipset     A pointer to the variable that receives the detected
                       graphics accelerator chip. Currently, this value is
                       always zero. No accelerators are detected at this
                       time.

           software    A pointer to the variable that receives the video
                       interface. It is one of the following values (enum
                       VIDEO_SOFTWARE):
                       VS_UNKNOWN No interface, or unknown interface.
                       VS_AI      IBM Adapter Interface, for 8514/A and XGA.

                       VS_DMQS    IBM Display Mode Query and Set for XGA.
                       VS_VESA    VESA Video BIOS Extensions for SVGA.

           version     A pointer to the variable that receives the version of
                       the video interface (the software).

Notes:     The 8514/A adapter is only detected on machines with an MCA
           bus. Although ISA bus implementations of the 8514/A card exist,
           the detection routine could return a false positive due to the
           incomplete address decoding of ISA motherboards and adapters. On
           an ISA bus, the 8514/A address that is tested may conflict with an
           I/O address used by COM4: or by some network adapters.

           The amount of video memory for an XGA adapter is not detected.
           Determining the amount of video memory would require to switch the
           XGA card to "extended mode", which blanks the screen. One of
           the design constraints was that SysInfo should operate invisibly,
           so clearing the screen was out. However, if you (or the user)
           installed a VESA driver for the XGA, the VESA driver has already
           switched to extended mode (and back) to determine the amount of
           memory. SysInfo checks fopr VESA support and returns the amount of
           video memory that is available through the VESA interface.

           Currently, SysInfo does not check for SVGA chipsets. It only
           checks for VESA support (in a TSR or in BIOS) and it assumes a
           SuperVGA card is present if VESA is installed.



si_xms                                                     Extended memory


Syntax:     short D_EXPORT si_xms(unsigned short _far *version,
                       unsigned short _far *free)

            version    The version of XMS. The most current version is 3.0
                       (which is encoded as 0x300).

            free       The amount of free extended memory in kBytes that is
                       available through XMS.

Returns:    Zero if XMS is not available, a non-zero value if the XMS inter-
            face is available.
                                          Explicit dynamic linking  ---  17

                       Alternative calling mechanisms



SysInfo is typically needed only at startup of an application (so the applica-
tion can detect its environment). So it is awkward to be required to link some
object file with the application (even if it is a tiny object file).

More importantly, some library function may require SysInfo. At CompuPhase, we
regularly use Win4C, a DOS based GUI library. This library uses SysInfo for
the detection of the graphics adapter and a few other items. Why would you
need to link in SYSINFO&.OBJ when you add Win4C to your application? Why not
let Win4C handle this?

Well, Win4C does handle this, and so can you. There are two alternative ways
to call the SysInfo daemon. The first is actually valid for any daemon: it is
explicit dynamic linking. The second is by using Daemon server function d_call
to call the entry function (or "callback" function) of the SysInfo daemon.



Explicit dynamic linking

Details of explicit dynamic linking are explained in the Daemon server manual.
Here we give a short example, without much explanation.

       void main(void)
       {
         void (D_EXPORT *si_system)(short _far*,short _far*,short _far*,short _far*);
         short sysinfo_handle;
         short cpu, fpu, bus, mode;

         if (!d_init()) {
           printf("Daemon server not present\n");
           return;
         } /* if */

         if ((sysinfo_handle = d_load("sysinfo.exe", 0)) > 0xff) {
           printf("Error %d in loading SysInfo\n", sysinfo_handle >> 8);
           return;
         } /* if */

         si_system = d_procaddr(sysinfo_handle, "si_system");
         si_system(&cpu, &fpu, &bus, &mode);
         if (cpu == 0)
           printf("CPU:       8088 or 8086\n");
         else
           printf("CPU:       80%d86\n", cpu);
         printf("FPU:       %s\n", fpu ? "installed" : "unavailable");
         printf("CPU mode:  %s\n", (mode==0 | mode==1) ? "real" : "V86");

         d_unload(sysinfo_handle);
       }
18  ---  Direct call interface


The main changes to the first example in the section "How to use SysInfo?"
are that instead of a link table, you declare a pointer to the function you
want to call. Then, instead of linking all the functions with d_linkall, you
request the function address of that single function with d_procaddr. For
the rest, once the function pointer is set up, you can call it like a normal
function.

In fact, if you inspect sysinfo_handle, you will see that it is always 3
(unless there was an error in loading the daemon). The SysInfo daemon always
loads at daemon number 3 (see the Daemon server manual for details on the
loading and linking of daemons).



Direct call interface

A daemon has a single callback function. One of the things this callback
function does is to handle signals and requests from Daemon server. For
example, when your application calls d_procaddr, the callback function of the
daemon receives a D_SYSREQ_ADDR signal (the Daemon server manual calls these
signals "system requests").

There are 256 possible signal values, and Daemon server only reserves the top
sixteen (240--255) for its own purposes. The other values are for the daemon's
own use. SysInfo defines a series of constants to let an application detect
hardware without even linking a function pointer.

The interface is register based and works via d_call (for C-based programs,
that is; if you program in TurboPascal or assembler, see the Daemon server
manual how to use the register based interface). You set up a few registers,
call the SysInfo daemon and read the result from other registers.

There is one important difference from the function based interface (whether
it be the semi-static linking via d_linkall or the explicit linking via
d_procaddr). If a register pair denotes a pointer, this pointer points into a
data structure inside the daemon. This structure is only valid as long as the
daemon is in memory. If you need the values after unloading the daemon, you
must copy them. The function based interface always copies the data.

The goal in this "assembler based" reference is to be as brief as possible.
So for more information, details and exceptions, look up the equivalent
function in the C reference.

When you call the callback function of a daemon (via d_call), the register AH
always contains the handle of the daemon. That is, it contains the value that
d_load returns when it loads a daemon (this value is stored in the variable
sysinfo_handle in all programming examples). In the case of SysInfo, this
value is always 3. What this sums up to is that AH must be set to 3 for all of
the calls that are listed below.

For the SysInfo daemon (as for almost all daemons that support a direct call
interface), the function number is in register AL. This number is written on
the right in each function header, both as a symbolic constant from SYSINFO.H
and as a decimal value (between parentheses).
                                             Extended memory (XMS)  ---  19


CPU                                                             SI_CPU (0)

Result:
            AX         CPU value (0=8086, 1=80186, etc)



FPU                                                             SI_FPU (1)

Result:
            AX         FPU installed flag; 0=not installed, 1=installed



CPU mode                                                    SI_CPUMODE (2)

Result:
            AX         The mode the CPU is in (real, protected); see
                       si_system



System bus                                                      SI_BUS (3)

Result:
            AX         The value if the system bus, see si_system



Keyboard                                                        SI_KBD (4)

Result:
            AX         The keyboard type; 0=86/87 keys, 1=101/102 keys



Physical memory                                                 SI_MEM (5)

Result:
            AX         Amount of DOS memory in kBytes (read from BIOS data
                       area)
            CX         Amount of conventional memory in kBytes (read from
                       CMOS)
            DX         Amount of extended memory in kBytes (read from CMOS)



Extended memory (XMS)                                           SI_XMS (6)

Result:
            AX         Version of XMS driver
            DX         Amount of free XMS memory in kBytes
20  ---  Expanded memory (EMS)



Expanded memory (EMS)                                           SI_EMS (7)

Result:
            AX         Version of the EMS driver
            DX         Number of free 16 kByte pages



Video hardware                                             SI_VIDEO_HW (8)

Result:
            AX         Type of video card; see si_video
            BX         Chipset on the video card (currently always 0)
            DX         Amount of video memory in kBytes



Video software/driver                                      SI_VIDEO_SW (9)

Result:
            AX         Type of driver or interface; see si_video
            DX         Version of the driver or interface



Video mode list                                        SI_VIDEO_MODES (10)

Result:
            AX         Number of modes the video configuration supports
            ES:DI      Pointer to a list of MODE_INFO structures; see
                       si_modelist



Logical drives                                              SI_DRIVES (11)

Result:
            AX         Number of logical drives
            ES:DI      Pointer to a list of DRIVE_INFO structures; see
                       si_drives



Serial ports                                                 SI_RS232 (12)

Result:
            AX         Number of serial ports in the system
            ES:DI      Pointer to a list of PORT_INFO structures; see
                       si_rs232



Parallel ports                                                 SI_LPT (13)

Result:
            AX         Number of parallel (printer) ports in the system
            ES:DI      Pointer to a list of PORT_INFO structures; see si_lpt
                                                     Diskette type  ---  21


Mouse                                                        SI_MOUSE (14)

Result:
            AX         Mouse type; see si_mouse
            BX         Driver version; 0=no driver detected
            DX         I/O address of the COM port to which the mouse is
                       attached (if Microsoft Mouse compatible)



PCMCIA                                                      SI_PCMCIA (15)

Result:
            AX         PCMCIA interface version
            DX         Number of PCMCIA sockets



Full path name (canonical name) function                  SI_FULLPATH (16)

Input:
            DX         The method (resolve/short name/long name), see
                       si_fullpath.
            DS:SI      Pointer to the source path string
            ES:DI      Pointer to the destination buffer (that will receive
                       the full path)

Result:
                       None (the buffer that ES:DI points to has been filled
                       in)



Queue name of captured printer port                       SI_LPT_NAME (17)

Input:
            DX         Printer port (0=LPT1:, 1=LPT2:, etc)
            ES:DI      Pointer to the destination buffer (that will receive
                       the queue name)

Result:
                       None (the buffer that ES:DI points to has been filled
                       in)



Diskette type                                             SI_DISKETTE (18)

Input:
            DX         Drive number (0=A:, 1=B:, etc)

Result:
            AX         Type of diskette unit; see si_diskette
22  ---  Miscellaneous notes


                            Miscellaneous notes


* SysInfo detects most of the environment immediately after startup. That
  is, it detects the video card already when you launch SYSINFO.EXE. It does
  not wait until you call a function like si_video. I chose to detect most
  values at startup in order to be sure of the sequence of the detection
  routines. Some values are needed for other detection routines. For example,
  the detection of the XGA and the 8514/A adapter needs to know whether the
  bus is MCA or different. The detection of the system bus at its turn needs
  to know the processor type. So by doing all detection in one early stage of
  the program, I could easily make sure all routines are called in the proper
  order (without having a function being called several times; some of these
  routines are slow).

  The result of this is that SysInfo will probably not see changes to the
  configuration that happen while it is in memory. For example, if you load
  SysInfo, capture a printer port and call si_lpt, SysInfo will not identify
  the port you just captured as a network port.

* If SysInfo hangs (or more precisely, SHOWINFO hangs), you can check what
  exact routine causes the hang-up by starting SysInfo in diagnostic mode by
  typing "sysinfo diag" at the command line. This displays the start en end
  of each detection routine. The start is indicated with a "[" and the name
  of the routine, for example "[cpu". The end is indicated with a "]". So
  if the CPU detection routine completed, the complete code "[cpu]" appears
  at the screen. If the CPU detection hangs, you only see "[cpu" (without
  the closing "]").

* An operating system like Microsoft Windows or IBM OS/2 intercepts read and
  write operations to an I/O port in order to avoid device contention (device
  contention occurs when two applications want to use the same device, for
  example when you are trying to send a fax and surf on Internet through the
  same modem). The interception on I/O ports is called virtualizing a port or
  a device.

  SysInfo reads and writes I/O ports to check the hardware capabilities. If an
  operating system virtualized that I/O port, this may offset the detection
  routine of SysInfo. In other words, SysInfo may detect something else than
  you really have in your machine.
                                                            Index  ---  23

                                  Index




16450 (RS232), 13
16550 (RS232), 13                      daemon handle, 18
16552 (RS232), 13                      Daemon server, 1, 3, 4, 14
8250 (RS232), 13                       DBIND, 4
82510 (RS232), 13                      Diagnostic mode, 22
8514/A (video), 15, 22                 Direct call interface, 18
  limited dectection of ~ , 16         Diskette, 6
                                       Diskette type, 5
                                       Display Mode Query and Set, See DMQS
3167, See Weitek Abacus & FPU          DMQS (video), 16
4167, See Weitek Abacus & FPU          DOBJ, 4
8086, See CPU                          Drive type, 5
8087, See FPU                          Dynamic linking, 1, 17
8088, See CPU
80186, See CPU
80286, See CPU                         ECP (parallel port), 9
80287, See FPU                         EGA (video), 15
80386, See CPU                         EISA (system bus), 14
80387, See FPU                         EMM386, 7, 14, 15
80486, See CPU                         EMS (memory), 7
80487, See FPU                         EPP (parallel port), 9
80587, See FPU                         Expanded memory, See EMS
                                       Extended memory, See XMS & CMOS

Abacus, See Weitek Abacus
Abrash, M., 10
Adapter Interface, See AI              False positive, 16
AI (video), 16                         Fast Graphic, 10, 11
Assembler interface, See Register      FIFO
  based interface                        bad, 13
AT-bus, See ISA                          good, 13
                                       Fixed disk, 6
                                       FPP (parallel port), 9
Bad FIFO, 13                           FPU, 14
Bidirectional parallel port, 9         Function based interface, 18
Borland C++, 4
                                       Handle (daemon), 18
C compiler, 4                          Hercules (video), 11, 15
Canonical name, See TrueName
CD-ROM drive, 6
CGA (video), 15                        ISA (system bus), 14, 16
Chicago, See Windows 95
CMOS, 10
Co-processor, See FPU                  JOIN (DOS command), 8
CPU, 13
CR0, 15
Critical error, 8                      Keyboard, 8, 19
24  ---  Index



Lantastic, 9
LFN, 6                                 RAM drive, 6
Long filename, See LFN                 Register based interface, 4, 18
LPT4:, i, 8                            Removable drive, 6
                                       RS232, 1, 12, 13
Math co-processor, See FPU               I/O addresses, 12, 13
MCA (system bus), 14, 16, 22
MCGA (video), 15
MDA (video), 15                        Serial mouse, See Mouse, 11
Memory, see also EMS, XMS, & video     Serial port, See RS232
  memory, 10                           SUBST, See Phantom drive
Microchannel, See MCA                  SuperVGA, See SVGA
Microsoft C, 4, 11                     SVGA (video), see also VESA, 15
Microsoft Diagnostics, See MSD         System bus, 14, 19
Mouse, 1, 11, 21
  IBM PS/2, 11
  serial, 11                           TrueName, 8, 21
  version, 12
MSD, 1
                                       UNC (drive), 6
Network drive, 6                       UndocumentedDOS, 7, 9
Novell Netware, 9                        Novell Netware, 9
Numerical co-processor, See FPU        Unicode, 6
                                       Universal Naming Convention, See UNC
OS/2, 1, 22
                                       Version encoding, 5
Parallel port, 8                       VESA (video), see also SVGA, 10, 16
  limited detection of ~ , i, 8        VGA (video), 15
PCI (system bus), 14                   VGA8 (video), 10
PCMCIA, 12, 21                         Video memory, 15, 16, 20
Pentium, See CPU                       Virtualizing, 22
Phantom drive, 6
Pointer arguments, 4, 5
Print queue name, 9, 21                Weitek Abacus, 14, 15
Printer port, See parallel port          limited detection of ~ , 15
PS/2 mouse, 11                         Windows 95, 6, 7, 11, 15, 22
