From: carlyle@tocnet.com (Jeffrey Carlyle)
Newsgroups: comp.os.msdos.programmer,alt.msdos.programmer,comp.answers,news.answers
Subject: comp.os.msdos.programmer FAQ part 3/5
Followup-To: comp.os.msdos.programmer
Organization: Stratoware
Sender: carlyle@tocnet.com (Jeffrey Carlyle)
Approved: news-answers-request@MIT.Edu
Reply-To: carlyle@tocnet.com (Jeffrey Carlyle)
Summary: Frequently asked questions by DOS programmers with tested answers.

Archive-name: msdos-programmer-faq/part3
Comp-os-msdos-programmer-archive-name: dos-faq-pt3.txt
Posting-frequency: 20 days
Last-modified: 20 Mar 1996

------------------------------

Subject: comp.os.msdos.programmer FAQ part 3/5

This is part 3 of the frequently asked questions list for the newsgroup
comp.os.msdos.programmer.

Part 3:
  Section 5.  Disks and files
  Section 6.  Serial ports (COM ports)

------------------------------

Subject: comp.os.msdos.programmer FAQ

comp.os.msdos.programmer FAQ Version 2.06

Copyright 1996 by Jeffrey Carlyle, Stratoware. All rights reserved. This
article is not in the public domain, but it may be redistributed so long
as this notice, the acknowledgments, and the information on obtaining the
latest copy of this list are retained and no fee is charged. The code
fragments may be used freely;  credit would be polite. This FAQ is not to
be included in any static archive (e.g. CD-ROM or book); however, a pointer
to the FAQ may be included.

 =============================
 TABLE OF CONTENTS
 =============================

Part 1:
  Section 1.  General FAQ and Newsgroup Information
  Section 2.  General Reference
Part 2:
  Section 3.  Compile and Link
  Section 4.  Keyboard
Part 3:
  Section 5.  Disks and files
  Section 6.  Serial ports (COM ports)
Part 4:
  Section 7.  Other hardware questions and problems
  Section 8.  Other software questions and problems
Part 5:
  Section 9.  Downloading
  Section 10. Vendors and products

------------------------------

Subject: Section 5.  Disks and files

  <q:5.01> - What drive was the PC booted from?
  <q:5.02> - How can I boot from drive b:?
  <q:5.03> - Which real and virtual disk drives are valid? 
  <q:5.04> - How can I make my single floppy drive both a: and b:?
  <q:5.05> - How can I disable access to a drive?
  <q:5.06> - How can a batch file test existence of a directory? 
  <q:5.07> - Why won't my C program open a file with a path?
  <q:5.08> - How can I redirect printer output to a file? 
  <q:5.09> - How can I redirect the output of a batch file? 
  <q:5.10> - How can I redirect stderr? 
  <q:5.11> - How can my program open more files than DOS's limit of 20?
  <q:5.12> - How can I read, create, change, or delete the volume label?
  <q:5.13> - How can I get the disk serial number? 
  <q:5.14> - What's the format of .OBJ, .EXE., .COM files?
  <q:5.15> - How can I flush the software disk cache?
  <q:5.16> - How can I see if a drive is a RAM drive? 

------------------------------

Subject: <q:5.01> - What drive was the PC booted from?
    
    Under DOS 4.0 or later, use INT 21 AX=3305.  DL is returned with an
    integer indicating the boot drive (1=A:, etc.).

------------------------------

Subject: <q:5.02> - How can I boot from drive b:?

    Downloadable shareware:

    <ftp://oak.oakland.edu/pub/msdos/diskutil/boot_b.zip>
    <ftp://garbo.uwasa.fi/pc/bootutil/boot_b.zip>

    The included documentation says it works by writing a new boot
    sector on a disk in your a: drive that redirects the boot to your b:
    drive.  (A similar utility is bboot.zip in the same directory at
    Garbo only.)

    If that doesn't work, you can always interchange your a: and b:
    drives by switching ribbon cables and changing the setup in your
    BIOS.  From an article posted 27 Jan 1993 on another newsgroup:

    Take the "ribbon" connector, as you call it, and switch them.  To
    double check, start at the end of the cable that connects to the
    motherboard or floppy controller.  Follow the cable until you get to
    the first connector.  Connect this to the drive you want to be b:.
    After this, there should be a few lines on the cable that get
    flipped left to right.  (On most cables, they just cut the lines and
    physically reverse them.  It should be quite obvious from looking at
    the cable.)  Anyway, the connector after the pins get flipped right
    to left is the connector for your a: drive.

------------------------------

Subject: <q:5.03> - Which real and virtual disk drives are valid? 
Date: Wed, 11 Jan 95 15:34:00 CDT

    Use INT 21 AH=29 (parse filename).  Point DS:SI at a null-terminated
    ASCII string that contains the drive letter and a colon, point ES:DI
    at a 37-byte dummy FCB buffer, and call INT 21 AX=2900.  On return,
    AL is FF if the drive is invalid, something else if the drive is
    valid.  RAM disks and SUBSTed drives are considered valid.

    You can detect whether the drive is ASSIGNed by using INT 2F
    AX=0601.  To check whether the drive is SUBSTed, use INT 21 AX=4409;
    or use INT 21 AH=52 to test for both JOIN and SUBST.  See Ralf
    Brown's interrupt list <q:2.03>.

    Unfortunately, the b: drive is considered valid even on a single-
    diskette system.  You can check that special case by interrogating
    the BIOS equipment byte at 0040:0010.  Bits 7-6 contain the one less
    than the number of diskette drives, so if those bits are zero you
    know that b: is an invalid drive even though function 29 says it's
    valid.

    Following is some code originally posted by Doug Dougherty to test
    valid drives (treating SUBSTed and JOINed drives as valid), with my
    fix for the b: special case, tested in Borland C++ 4.5 (in the large
    model):

        #include <dos.h>
        #include <stdio.h>
        void drvlist(void) {
            char s[3] = "A:", fcb_buff[37];
            int valid;
            for (   ;  *s<='Z';  (*s)++) {
                _SI = (unsigned) s;
                _DI = (unsigned) fcb_buff;
                _ES = _DS;
                _AX = 0x2900;
                geninterrupt(0x21);
                valid = _AL != 0xFF;
                if (*s == 'B'  &&  valid) {
                    char far *equipbyte = (char far *)0x00400010UL;
                    valid = (*equipbyte & (3 << 6)) != 0;
                }
                printf("Drive '%s' is %sa valid drive.\n",
                        s, valid ? "" : "not ");
            }
        }

    This code was translated to MSC 7.0 and tested it in small model:

        #include <dos.h>
        #include <stdio.h>
        void drvlist(void) {
            char s[3] = "A:", fcb_buff[37], *buff=fcb_buff;
            int valid;
            for (   ;  *s<='Z';  (*s)++) {
                __asm mov si,s      __asm mov di,buff
                __asm mov ax,ds     __asm mov es,ax
                __asm mov ax,0x2900 __asm int 21h
                __asm xor ah,ah     __asm mov valid,ax
                valid = (valid != 0xFF);
                if (*s == 'B'  &&  valid) {
                    char far *equipbyte = (char far *)0x00400010UL;
                    valid = (*equipbyte & (3 << 6)) != 0;
                }
                printf("Drive '%s' is %sa valid drive.\n",
                        s, valid ? "" : "not ");
            }
        }

------------------------------

Subject: <q:5.04> - How can I make my single floppy drive both a: and b:?

    Under any DOS since DOS 2.0, you can put the command

        assign b=a

    into your AUTOEXEC.BAT file.  Then, when you type "dir b:" you'll no
    longer get the annoying prompt to insert diskette B (and the even
    more annoying prompt to insert A the next time you type "dir a:").

    You may be wondering why anybody would want to do this.  Suppose you
    use two different machines, maybe one at home and one at work.  One
    of them has only a 3.5" diskette drive; the other machine has two
    drives, and b: is the 3.5" one.  You're bound to type "dir b:" on
    the first one, and get the nuisance message

        Insert diskette for drive B: and press any key when ready.

    But if you assign drive b: to point to a:, you avoid this problem.

    Caution:  there are a few commands, such as DISKCOPY, that will not
    work right on ASSIGNed or SUBSTed drives.  See the DOS manual for
    the full list.  Before typing one of those commands, be sure to turn
    off the mapping by typing "assign" without arguments.

    The DOS 5.0 manual says that ASSIGN is obsolete, and recommends the
    equivalent form of SUBST: "subst b: a:\".  Unfortunately, if this
    command is executed when a: doesn't hold a diskette, the command
    fails.  ASSIGN doesn't have this problem, so under DOS 5.0 you
    should disregard that particular bit of advice in the manual.

------------------------------

Subject: <q:5.05> - How can I disable access to a drive?

    Reader Eric DeVolder writes that he has made available a program to
    do this.  I haven't tried it, but it's downloadable as

    <ftp://oak.oakland.edu/pub/msdos/diskutil/rmdriv20.zip>
    <ftp://garbo.uwasa.fi/pc/sysutil/rmdriv20.zip>

------------------------------

Subject: <q:5.06> - How can a batch file test existence of a directory?
Date: Tue, 7 Mar 95 12:00:00 CDT

    The standard way, which in fact is documented in the DOS manual, is

        if exist d:\path\nul goto found

    Unfortunately, this is not entirely reliable.  I found it failed in
    Pathworks (a/k/a PCSA, DEC's network that connects PCs and VAXes),
    or on a MARS box that uses an OEM version of MS-DOS 5.0.  Readers
    have reported that it gave the wrong answer on Novell networks, on
    DR-DOS, and in a DOS window under OS/2.  By "failed" I mean that it
    "found" a directory that didn't exist, or failed to find one that
    did exist, or both.  (I'm told that IBM fixed the OS/2 bug in
    version 2.11 of OS/2.) As a legacy from earlier versions of DOS it
    always succeedes if the path is DEV.

    There appears to be no foolproof way to use pure batch commands to
    test for existence of a directory.  The real solution is to write a
    program, which returns a value that your batch program can then test
    with an "if errorlevel".  Reader Duncan Murdoch kindly posted the
    following Turbo Pascal version:

        program existdir;
            { Confirms the existence of a directory given on the command
            line.  Returns errorlevel 2 on error, 1 if not found, 0 if
            found. }

        uses
            dos;

        var
            s : searchrec;

        begin
            if paramcount <> 1 then
            begin
                writeln('Syntax:  EXISTDIR directory');
                halt(2);
            end
            else
            begin
                findfirst(paramstr(1),Directory,S);
                while (Doserror = 0) and ((Directory and S.Attr) = 0) do
                    findnext(S);
                if Doserror <> 0 then
                begin
                    Writeln('Directory not found.');
                    halt(1);
                end
                else
                begin
                    Writeln('Directory found.');
                    halt(0);
                end;
            end;
        end.

    Timo Salmi also has a Turbo Pascal version in his Turbo Pascal FAQ,
    which is downloadable as

    <ftp://garbo.uwasa.fi/pc/ts/tsfaqp*.zip>

------------------------------

Subject: <q:5.07> - Why won't my C program open a file with a path?

    You've probably got something like the following code:

        char *filename = "c:\foo\bar\mumble.dat";
        FILE *fptr;
        . . .
        fptr = fopen(filename, "r");

    The problem is that \f is a form feed, \b is a backspace, and \m is
    m.  Whenever you want a backslash in a string constant in C, you
    must use two backslashes:

        char *filename = "c:\\foo\\bar\\mumble.dat";

    This is a feature of every C compiler, because Dennis Ritchie
    designed C this way.  It's a problem only on MS-DOS systems, because
    only DOS (and Atari ST/TT running TOS) uses the backslash in
    directory paths.  But even in DOS this backslash convention applies
    _only_ to string constants in your source code.  For file and
    keyboard input at run time, \ is just a normal character, so users
    running your program would type in file specs the same way as in DOS
    commands, with single \ characters.

    Another possibility is to code all paths in source programs with /
    rather than \ characters:

        char *filename = "c:/foo/bar/mumble.dat";

    Ralf Brown writes, "All versions of the DOS kernel accept either
    forward or backslashes as directory separators.  I tend to use this
    form more frequently than backslashes since it is easier to type and
    read."  This applies to DOS function calls (and therefore to calls
    to the file library of every programming language), but not to DOS
    commands.

------------------------------

Subject: <q:5.08> - How can I redirect printer output to a file?

    Recommended: PRN2FILE from PC Magazine, downloadable as:

    <ftp://oak.oakland.edu/pub/msdos/printer/prn2file.zip>
    <ftp://garbo.uwasa.fi/pc/printer/prn2file.zip>

    PC Magazine has given copies away as part of its utilities disks, so
    you may already have a copy.

    The directories mentioned above have lots of other utilities to
    redirect printer output.

------------------------------

Subject: <q:5.09> - How can I redirect the output of a batch file?

    Assuming the batch file is called batch.bat, to send its output
    (stdout) to another file, just invoke COMMAND.COM as a secondary
    command processor:

        command /c batch parameters_if_any >outfile

    Timo Salmi's notes on this and other batch tricks are downloadable:

    <ftp://oak.oakland.edu/pub/msdos/batutil/tsbat44.zip>
    <ftp://garbo.uwasa.fi/pc/ts/tsbat44.zip>

------------------------------

Subject: <q:5.10> - How can I redirect stderr?

    Use freopen(..., stderr) and then execute the desired command via
    system().  There are downloadable versions of programs to do this.
    I recommend this file, which includes TP4 source and executable:

    <ftp://oak.oakland.edu/pub/msdos/sysutil/rdstderr.zip>

    A C example is downloadable as

    <ftp://oak.oakland.edu/pub/msdos/c/redirect.c>

    I compiled it with MSC 7.0, and it works fine with one exception:
    Contrary to the included comments, redirected output starts writing
    at the beginning of the output file rather than appending.  That is
    easily solved by adding "fseek(stderr, 0L, SEEK_END);" after the
    freopen() call for stderr.

------------------------------

Subject: <q:5.11> - How can my program open more files than DOS's
        limit of 20?

    This is a summary of an article Ralf Brown posted on 8 August 1992,
    with some additions from a Microsoft tech note and information from
    Chin Huang.)

    DOS imposes some limits.  Once you overcome those, which is pretty
    easy, you may have to take additional measures to overcome the
    limitations built into your compiler's run-time library.

    1) Limitations imposed by DOS

    There are separate limits on files and file handles.  For example,
    DOS opens three files but five file handles:  CON (stdin, stdout,
    and stderr), AUX (stdaux), and PRN (stdprn).

    The limit in FILES= in CONFIG.SYS is a system-wide limit on files
    opened by all programs (including the three that DOS opens and any
    opened by TSRs); each process has a limit of 20 handles (including
    the five that DOS opens).  Example:  CONFIG.SYS has FILES=40.  Then
    program #1 will be able to open 15 file handles.  Assuming that the
    program actually does open 15 handles pointing to 15 different
    files, other programs could still open a total of 22 files (40-3-15
    = 22), though no one program could open more than 15 file handles.

    If you're running DOS 3.3 or later, you can increase the per-process
    limit of 20 file handles by a call to INT 21 AH=67, Set Handle
    Count.  Your program is still limited by the system-wide limit on
    open files, so you may also need to increase the FILES= value in
    your CONFIG.SYS file (and reboot).  The run-time library that you're
    using may have a fixed-size table of file handles, so you may also
    need to get source code for the module that contains the table,
    increase the table size, and recompile it.

    2) Limitations in Microsoft C run-time library

    In Microsoft C the run-time library limits you to 20 file handles.
    To change this, you must be aware of two limits:

    - file handles used with _open(), _read(), etc.: Edit _NFILE_ in
      CRT0DAT.ASM.

    - stream files used with fopen(), fread(), etc.: Edit _NFILE_ in
      _FILE.C for DOS or FILE.ASM for Windows/QuickWin.  This must not
      exceed the value of _NFILE_ in CRT0DAT.ASM.

    (QuickWin uses the constant _WFILE_ in CRT0DAT.ASM and WFILE.ASM for
    the maximum number of child text windows.)

    After changing the limits, recompile using CSTARTUP.BAT.  Microsoft
    recommends that you first read README.TXT in the same directory.

    3) Limitations in Borland C++ run-time library

    (Reader Chin Huang provided this information on 12 Sep 1993.)

    To increase the open file limit for a program you compile with
    Borland C++ 3.1, edit the file _NFILE.H in the include directory and
    change the _NFILE_ value.  Compile and link the modules FILES.C and
    FILES2.C from the lib directory into your program.

------------------------------

Subject: <q:5.12> - How can I read, create, change, or delete the volume
        label?

    In DOS 5.0 (and possibly in 4.0 as well), there are actually two
    volume labels: the LABEL command reports only the first but changes
    both of them.

    - The traditional volume label is an entry with "volume label"
      attribute in the root directory of the disk.  The DIR, VOL, and
      LABEL commands report this volume label, and LABEL sets it.

    - There is a second volume label, which may be different, in the
      boot record along with the serial number. In DOS 4.0 and later,
      INT 21 AH=69 gets or sets the boot record's serial number and
      volume label together; see "<q:5.13> - How can I get the disk serial
      number?"  DIR and VOL ignore this volume label; the LABEL command
      doesn't report it but does set it.

    The rest of this answer assumes that by "volume label" you mean the
    traditional one, the one that DIR and VOL display.  Though it's a
    directory entry in the root directory, you can't change it using the
    newer DOS file-access functions (INT 21 AH=3C, 41, 43); instead, use
    the old FCB-oriented directory functions.  Specifically, you need to
    allocate a 64-byte buffer and a 41- byte extended FCB (file control
    block).  Call INT 21 AH=1A to find out whether there is a volume
    label.  If there is, AL returns 0 and you can change the label using
    DOS function 17 or delete it using DOS function 13.  If there's no
    volume label, function 1A will return FF and you can create a label
    via function 16.  Important points to notice are that ? wildcards
    are allowed but * are not; the volume label must be space filled not
    null terminated.

    The following MSC 7.0 code worked for me in DOS 5.0; the functions
    it uses have been around since DOS 2.0.  The function parameter is 0
    for the current disk, 1 for a:, 2 for b:, etc.  It doesn't matter
    what your current directory is; these functions always search the
    root directory for volume labels.  (I didn't try to change the
    volume label of any networked drives.)

        // Requires DOS.H, STDIO.H, STRING.H
        void vollabel(unsigned char drivenum) {
            static unsigned char extfcb[41], dta[64], status, *newlabel;
            int chars_got = 0;
            #define DOS(buff,func) __asm { __asm mov dx,offset buff   \
                __asm mov ax,seg buff  __asm push ds  __asm mov ds,ax \
                __asm mov ah,func  __asm int 21h  __asm pop ds        \
                __asm mov status,al }
            #define getlabel(buff,prompt) newlabel = buff;  \
                memset(newlabel,' ',11);  printf(prompt);   \
                scanf("%11[^\n]%n", newlabel, &chars_got);  \
                if (chars_got < 11) newlabel[chars_got] = ' ';

            // Set up the 64-byte transfer area used by function 1A.
            DOS(dta, 1Ah)
            // Set up an extended FCB and search for the volume label.
            memset(extfcb, 0, sizeof extfcb);
            extfcb[0] = 0xFF;           // denotes extended FCB
            extfcb[6] = 8;              // volume-label attribute bit
            extfcb[7] = drivenum;       // 1=A,2=B,...; 0=current drive
            memset(&extfcb[8], '?', 11);// wildcard *.*
            DOS(extfcb,11h)
            if (status == 0) {          // DTA has volume label's FCB
                printf("volume label is %11.11s\n", &dta[8]);
                getlabel(&dta[0x18],
                    "new label (\"delete\" to delete): ");
                if (chars_got == 0)
                    printf("label not changed\n");
                else if (strncmp(newlabel,"delete  ",11) == 0) {
                    DOS(dta,13h)
                    printf(status ? "label failed\n" :
                                    "label deleted\n");
                }
                else {                  // user wants to change label
                    DOS(dta,17h)
                    printf(status ? "label failed\n" :
                                    "label changed\n");
                }
            }
            else {                      // no volume label was found
                printf("disk has no volume label.\n");
                getlabel(&extfcb[8], "new label (<Enter> for none): ");
                if (chars_got > 0) {
                    DOS(extfcb,16h)
                    printf(status ? "label failed\n" :
                                    "label created\n");
                }
            }
        }        // end function vollabel

------------------------------

Subject: <q:5.13> - How can I get the disk serial number?

    If the disk was formattted by DOS 4.0 or later, use INT 21: AX=6900
    gets the serial number; AX=6901 sets it.  (The disk serial number
    doesn't exist if the disk was formatted with an earlier version of
    DOS, or with some third-party formatters.)  See Ralf Brown's
    interrupt list <q:2.03>, or PC Magazine July 1992 (xi:13) page 496,
    for details.

    INT 21 AH=69 also gets and sets the volume label in the boot record,
    which is not necessarily the same as "the" volume label displayed by
    the DIR, VOL, and LABEL commands.  For that volume label, see
    <q:5.12> - "How can I read, create, change, or delete the volume
    label?"

------------------------------

Subject: <q:5.14> - What's the format of .OBJ, .EXE., .COM files?

    Please see <q:3.06> "What's the format of an .OBJ file?"; <q:3.07>
    "What's the format of an .EXE header?"; and <q:3.08> "What's the
    difference between .COM and .EXE formats?"

------------------------------

Subject: <q:5.15> - How can I flush the software disk cache?

    Please see "<q:8.01> - How can a program reboot my PC?"

------------------------------

Subject: <q:5.16> - How can I see if a drive is a RAM drive? 
Date: Tue, 7 Mar 95 12:00:00 CDT

    Use INT 21 AX=4409h. See Ralph Brown's interrupt list <q:2.03> for
    more information.

------------------------------

Subject: Section 6.  Serial ports (COM ports)

  <q:6.01> - How do I set my machine up to use COM3 and COM4?
  <q:6.02> - How do I find the I/O address of a COM port? 
  <q:6.03> - But aren't the COM ports always at I/O addresses 3F8, 2F8,
             3E8, and 2E8?
  <q:6.04> - How do I configure a COM port and use it to transmit data?

------------------------------

Subject: <q:6.01> - How do I set my machine up to use COM3 and COM4?

    Unless your machine is fairly old, it's probably already set up.
    After installing the board that contains the extra COM port(s),
    check the I/O addresses in word 0040:0004 or 0040:0006.  (In DEBUG,
    type "D 40:4 L4" and remember that every word is displayed low byte
    first, so if you see "03 56" the word is 5603.)  If those addresses
    are nonzero, your PC is ready to use the ports and you don't need
    the rest of this answer.

    If the I/O address words in the 0040 segment are zero after you've
    installed the I/O board, you need some code to store these values
    into the BIOS data segment:

        0040:0004  word  I/O address of COM3
        0040:0006  word  I/O address of COM4
        0040:0011  byte (bits 3-1): number of serial ports installed

    The documentation with your I/O board should tell you the port
    addresses.  When you know the proper port addresses, you can add
    code to your program to store them and the number of serial ports
    into the BIOS data area before you open communications.  Or you can
    use DEBUG to create a little program to include in your AUTOEXEC.BAT
    file, using this script:

        n SET_ADDR.COM      <--- or a different name ending in .COM
        a 100
        mov  AX,0040
        mov  DS,AX
        mov  wo [0004],aaaa <--- replace aaaa with COM3 address or 0
        mov  wo [0006],ffff <--- replace ffff with COM4 address or 0
        and  by [0011],f1
        or   by [0011],8    <--- use number of serial ports times 2
        mov  AH,0
        int  21
                            <--- this line must be blank
        rCX
        1f
        rBX
        0
        w
        q

------------------------------

Subject: <q:6.02> - How do I find the I/O address of a COM port?

    Look in the four words beginning at 0040:0000 for COM1 through COM4.
    (The DEBUG command "D 40:0 L8" will do this.  Remember that words
    are stored and displayed low byte first, so a word value of 03F8
    will be displayed as F8 03.)  If the value is zero, that COM port is
    not installed (or you've got an old BIOS; see "5.01> - How do I set my
    machine up to use COM3 and COM4?").  If the value is nonzero, it is
    the I/O address of the transmit/receive register for the COM port.
    Each COM port occupies eight consecutive I/O addresses (though many
    chips use only the first seven).

    Here's some C code to find the I/O address:

        unsigned ptSel(unsigned comport) {
            unsigned io_addr;
            if (comport >= 1  &&  comport <= 4) {
                unsigned far *com_addr = (unsigned far *)0x00400000UL;
                io_addr = com_addr[comport-1];
            }
            else
                io_addr = 0;
            return io_addr;
        }

    You might also want to explore Port Finder, downloadable as

    <ftp://oak.oakland.edu/pub/msdos/io_util/pf271.zip>
    <ftp://nic.funet.fi/pub/msdos/utilities/sysutl/pf271.zip>

    I haven't tried it myself, but a posted article reviewed it very
    favorably and said it also lets you swap ports around.

------------------------------

Subject: <q:6.03> - But aren't the COM ports always at I/O addresses 3F8,
                2F8, 3E8, and 2E8?

    The first two are usually right (though not always); the last two
    are different on many machines.

------------------------------

Subject: <q:6.04> - How do I configure a COM port and use it to transmit
        data?
Date: Sun, 21 May 95 12:00:00 CDT

    Do you want actual code, or do you want books that explain what's
    going on?

    1) Source code

    First, check your compiler's run-time library.  Many compilers offer
    functions similar to Microsoft C's _bios_serialcom() or Borland's
    bioscom(), which may meet your needs.

    Second, check for downloadable resources at SimTel and Garbo.  At
    SimTel, <ftp://oak.oakland.edu/pub/msdos/c/pcl4c34.zip> (March 1993)
    is described as "Asynchronous communications library for C"; Garbo
    has a whole <ftp://garbo.uwasa.fi/pc/comm> directory.  Also, an
    extended example is in Borland's TechFax TI445, downloadable as
    part of

    <ftp://oak.oakland.edu/pub/msdos/turbo-c/bchelp10.zip>
    <ftp://garbo.uwasa.fi/pc/turbopas/bchelp10.zip>

    Though written by Borland, much of it is applicable to other forms
    of C, and it should give you ideas for other programming languages.

    2) Reference books

    Highly recommended: Joe Campbell's {C Programmer's Guide to Serial
    Communications}, ISBN 0-672-22584-0.  He gives complete details on
    how serial ports work, along with complete programs for doing polled
    or interrupt-driver I/O.  The book is quite thick, and none of it
    looks like filler.

    If Campbell's book is overkill for you, you'll find a good short
    description of serial I/O in {DOS 5: A Developer's Guide}, ISBN
    1-55851-177-6, by Al Williams.

    Finally, a reader has recommended {Serial Communications Programming
    in C/C++} by Mark Goodwin (ISBN 1558281983), with source code in the
    book and on disk.  Topics include the basics, various methods of
    serial communications on the PC (with consideration of high-speed
    modems), ANSI screen interface, file transfer protocols (Xmodem and
    Ymodem), etc.  There is code in C, and that code is extended into a
    C++ class for those who use C++.  There are also subroutines in
    Assembly.

    3) Downloadable information files

    A "Serial Port FAQ" is occasionally posted to this newsgroup, and is
    downloadable as multiple files:

    <ftp://ftp.phil.uni-sb.de/pub/staff/chris/*Serial*>
    <ftp://rtfm.mit.edu/pub/usenet/comp.os.msdos.programmer/
           The_Serial_Port*>

    For rtfm.mit.edu instructions, see <q:1.13> "Where are FAQ lists
    archived?"

------------------------------

Subject: End

(End of comp.os.msdos.programmer FAQ Version 2.06 Part 3/5)
(This text is copyright 1996 by Jeffrey Carlyle. All rights reserved.)
