PROGRAMMING TECHNIQUES UNDER MS DOS

last updated November 1, 2001

There   are three methods   to   write application   programs to   control   serial communication. 

  1. Use device driver name to perform I/O.

  2. Use    PCCOM   library     through   DOS interrupt routines.

  3. Use low-level BIOS interrupt routines.   

6.1 How to Use Device Driver 

After  device driver is  installed,  you may use device name (such as COM5, COM6,  ... etc.)  as a file to perform  I/O  operations. Since  many  high  level  languages   provide several  kinds of I/O operations, e.g.  in  C language,  the write statement for low  level I/O and fprintf for high level I/O. You  must care which I/O routine is used by yourself to prevent the lose of I/O data, if you use high level I/O, you must use flush to dump  buffer contents to serial device when necessary.    

In  the  distribution disk,  we  provide BASIC, C, PASCAL, and FoxPro examples, all of these programs use device driver. 

    LOOPBACK.BAS

        Loopback test.

    DTX.BAS

        Transfer file.

    DRX.BAS

        Receive file.

    LOOPBACK.C

        Loopback test.

   DTERM.C

        ASCII terminal emulator.

    DCLOCK.C

        Receive clock message.

    LOOPBACK.PAS

        Loopback test.

    DTERM.PAS

        ASCII terminal emulator. 

6.2 PCCOM Library 

PCCOM   provides  C, PASCAL,  BASIC,  and FOXPRO library routines to let user to  write application   programs  to   control   serial communication via device drivers. 

To  write an  application  program,  you must link COMLI115.C or COMLI460.C (Borland C), COMLIBMS.C (MSC),  PCCOM115.PAS or PCCOM460.PAS (PASCAL), COMLIBGW.BAS (GWBASIC),   COMLIBQK.BAS   (Quick    BASIC) or  COMLIBQ.BAS  (Q BASIC) file according to your selection language. In  the following, we describe the PCCOM library more details: 

Routine Name

Description

cominit

setup communication parameters

comtxch

send a character

comrxch

receive a character

comstat

check communication status

comactive

check if port is usable

comsetDTR

set DTR signal ON or OFF

compeek

check next char in queue

comsetflow

set flow control

comtxblk

send one block data

comrxblk

receive one block data

combreak

end break signal

cominstalled

check if driver installed

comsetport

set address of serial port

comsetvector

set interrupt vector

set active low or high

comsetMCR

set MCR contents

compurgerxbuf

remove received buffer data

comtxs

send a character string

comrxs

receive a character string

comsettimeout

set time out

comgettimeout

get time out

combufstat

return no. of chars in queue

comgetMCR

get MCR contents

comgetFC

get flow control

comgetsets

get number of PCCOM sets

comgetsetinfo

get PCCOM set information

comgetinfo

get port status

comgetports

get number of PCCOM ports

comdetectport

detect if the port exist

comgetportinfo

get one port information

comrxoff

stop send data

comrxon

restart send data

 

 

1. cominit(portno, baud, db, parity, sb) 

   int cominit

   unsigned int  baud

   int  portno, db, parity, sb 

The cominit is used to setup several communication parameters. 

portno (int)

port    number    that    defined     in configuration file.

baud (unsigned int)

baud  rate. Either B38400, B19200, B9600, B4800, B2400, B1200, B600, B300.    

        B38400 (38400)

38400 baud.

        B19200 (19200)

19200 baud.

        B9600  (9600)

9600 baud.

        B4800  (4800)

4800 baud.

        B2400  (2400)

2400 baud.

        B1200  (1200)

1200 baud.

        B600    (600)     

600 baud.

        B300    (300)    

300 baud.

db (int)

     data  bits.  Either CS8,  CS7, CS6, CS5. 

  CS8 (8)

  8 bits

  CS7 (7)

  7 bits

  CS6 (6)

  6 bits

 CS5 (5)

  5 bits

parity (int)

     parity bit. Either PNONE, PEVEN, PODD. 

PNONE (0

none parity check.

PODD  (1

odd parity.

PEVEN (2)

even parity.

sb (int)

     stop bits. Either ST1 or ST2.     

ST1 (1)

one stop bit.

ST2 (2)

two stop bits.

return value (int)

        0 : success.

        1 : fail. 

2. comtxch(portno, ch) 

   int comtxch

   int portno

   char ch 

The comtxch is used to send a  character to serial port. 

ch (char)

     transmitted character

return value (int)       

0

success.

1

fail.

 3. comrxch(portno, ch) 

   int comrxch

   int portno

   char *ch    

     The comrxch is used to get a character. 

ch (char*)

     received character.

return value (int) 

        0   

success.

        1

fail (receive no character).

4. comstat(portno) 

   int comstat

   int portno 

The  comstat is used to get  serial  port status,  the status indicator is shown in the following. 

return value (int) 

bit 15

  time out error.

  bit 14

 transmitter shift register empty.

  bit 13

  transmitter holding register empty.

  bit 8

 data ready (data available in  input buffer). 

  bit 7

  received line signal detect (RLSD).

  bit 5

  data set ready (DSR).

  bit 4

  clear to send (CTS).

You  may check the parameters to  detect which bit is set. 

definition

position

value

S_CTS

4

0X0010

  S_DSR

5

0X0020

  S_DCD

7

0X0080

  S_RDA

8

0X0100

  S_THRE

13

0X2000

  S_TSRE

14

0X4000

  S_TIMEOUT

15

0X8000

5. comactive(portno) 

    int comactive

    int portno 

     Check if the port is active. 

return value (int) 

    1

active

    0

inactive

6. comsetDTR(portno,n)    

   void comsetDTR

   int portno,n  

    Set DTR signal ON or OFF.

n (int)    

ACTIVE   (1)

set DTR ON

INACTIVE (0)

set DTR OFF  

7. compeek(portno)

    int compeek

    int portno 

The   compeek   is   used   to   perform nondestructively  read a character. The  read character remains in the receive buffer. 

return value (int)       

0XFFFF

no character

          ?

received character

8. comsetflow(portno,n) 

   void comsetflow

   int portno, n 

     To set communication protocol. 

n (int)

    F_XONXOF (0X09)

set XON/XOFF protocol.

    F_RTSCTS (0X01)

set CTS/RTS protocol.

    F_DTRDSR (0X04)

set DSR/DTR protocol.

9. comtxblk(portno, pointer, n) 

   int comtxblk

   int portno,n

   void *pointer 

To transmit a block of data, it uses one BIOS call to transmit a block of data. 

pointer (pointer)

     pointer to start of block.

n (int)

     block length.

return value (int)

     number of characters be sent. 

10. comrxblk(portno, pointer, n) 

   int comrxblk

   int portno, n

   void *pointer 

To receive a block of data,  it uses one BIOS call to receive a block of data. 

pointer (pointer)

     pointer to start of block.

n (int)

     number of characters should be received.

return value (int)

     number of characters actually received. 

11. combreak(portno,brk) 

    void combreak

    int portno, brk 

     Send the break signal to driver. 

brk (int)

     ACTIVE   (1)

break the communication.

     INACTIVE (0)

unbreak the communication

12. cominstalled(portno) 

    int cominstalled

    int portno 

     Check if the driver is installed ? 

return value (int)

0

is installed

1

not installed

13. comsetport(portno, addr) 

    void comsetport

    int portno, addr 

The  comsetport  is used to  set  serial port address. 

addr (int)

     serial port address. 

14. comsetvector(portno, addr) 

    void comsetvector

    int portno, addr 

The   comsetvector   is  used   to   set interrupt  vector  address.  After  interrupt vector is set, when interrupt is emerged then the  device  driver  will  detect   interrupt vector  to  check  which  port  emerges   the interrupt. 

addr (int)

     interrupt vector address. The address is designed at hardware adapter. 

15. comsetactive(portno, active) 

    void comsetactive

    int portno

    char active 

The   comsetactive   is  used   to   set interrupt vector is active low or high. 

active (char)

0

  active low.

1

  active high

16. comsetMCR(portno, mcr) 

    void comsetMCR

    int portno, mcr 

The  comsetMCR  is used to  control  the contents  of modem control  register.  Please see APPENDIX B for more details. 

mcr (int)

bit 7

0

bit 6

0

bit 5

0

bit 4

loopback.

bit 3

OUT2 signal

bit 2

OUT1 signal

bit 1

RTS signal

bit 0

DTR signal

17. compurgerxbuf(portno) 

    void compurgerxbuf

    int portno 

Remove  any  received buffer  data  from specify port. 

18. comtxs(portno, s) 

    int comtxs, portno

    char *s 

The comtxs is used to send one string to serial   port  by  calling  BIOS   for   each character. 

s (char*)

     one character string to be sent.

return value (int)     

 0

success

  1   

fail

19. comrxs(portno, s) 

    int comrxs, portno

    char *s

The  comrxs  is used to get  one  string from  ring  buffer by calling BIOS  for  each character. This routine gets characters  from ring buffer until it find <CR> or ring buffer is empty. 

s (char*)

     received string. 

return value (int)

0

fail

1   

Success

20. comsettimeout(portno,timeout) 

    void comsettimeout

    int portno

    unsigned int timeout 

Set  time  out  value  about  tx;   when transmitter  buffer in the specified port  is full, the driver will wait until buffer empty or the timeout value is expired. 

timeout (unsigned int)

time out value, the unit is 1/18 sec. 

21. comgettimeout(portno) 

    unsigned int comgettimeout

    int portno 

     Get the tx timeout value. 

     return value (unsigned int)

     The time out value, unit is 1/18 sec. 

22. combufstat(portno) 

    int combufstat

    int portno 

The  combufstat  is used  to  count  the received characters in buffer. 

return value (int)    

0xFFFF

Buffer overflow

otherwise

Number of characters in received buffer

23. comgetMCR(portno) 

    char comgetMCR

    int portno 

     Get the value of MCR. 

     return value (char)

              modem control value (see comsetMCR). 

24. comgetFC(portno) 

    char comgetFC

    int portno 

     Get flow control value. 

     return value (int)

               Flow control value (see comsetflow). 

25. comgetsets() 

    int comgetsets 

Get  number  of  PCCOM  set  which   are controlled by device driver. 

return value (int)

     Number of PCCOM set. 

26. comgetsetinfo(portno) 

   BiosComSet_t *comgetsetinfo

   int portno 

To get PCCOM set information   about specified port, which belongs to this set. 

return value (BiosComSet_t*)

     The set information, which is defined as  

typedef struct {

       unsigned char irq;

       unsigned int portno;

       unsigned int groupno;

       unsigned int whichgroup;

       struct {

          unsigned int base;

          unsigned int vector;

          unsigned char active;

          unsigned char portno;

       } group[8];

     } BiosComSet_t;

     Where

irq

irq number of this set.

portno

number of serial ports in this set.

groupno

number of groups in this set.

whichgroup

the specified belongs to  which group

base

base I/O port address.

vector

interrupt vector address.

active

active status.

port

number of ports in this group.

27. comgetinfo(portno, baud, db, parity, sb) 

    void comgetinfo

    unsigned int *baud

    int portno, *db, *parity, *sb 

The   comgetinfo   is   used   to   get communication parameters of specified port. 

baud (unsigned int*)

     baud rate.

db (int*)

     data bits. Either 5, 6, 7 or 8 data bits.

parity (int*)

     parity bit. Either NONE, EVEN, ODD. 

        NONE (0)

none parity check.

        ODD  (1)

odd parity.

        EVEN (2)

even parity.

sb (int*)

     stop bits. Either 1 or 2 stop bits. 

28. comgetports() 

    int comgetports 

Get the number of PCCOM ports controlled by the PCCOM driver. 

return value (int)

     The number of PCCOM ports. 

29. comdetectport(portno) 

    int comdetectport

    int portno 

The comdetectport is used to detect  the serial port is exist or not. 

return value (int)

     0

the port is bad.

     1

the  port  is  ok.

30. comgetportinfo(portno) 

   BiosComport_t *comgetportinfo

   int portno 

 Retrieve   all  information  about   one specified PCCOM port. 

return value (BiosComport_t*)

     The port information which is defined as

    typedef struct {

       unsigned int addr;

       unsigned int baud;

       unsigned char lcr;

       unsigned char mcr;

       unsigned char fc;

       unsigned char rx_qsz;

       unsigned char rx_qfree;

       unsigned char rx_enable;

       unsigned char tx_enable;

     } BiosComport_t;

Where

addr

port address.

baud

baud rate.

lcr

line control register  value.

mcr

modem control register value.

fc

flow control protocol.

rx_qsz

received ring buffer size.

rx_qfree

free space in rx ring buffer.

rx_enable

flag    to   notify    the   port  receivable.

tx_enable

flag    to   notify    the   port  transmission.

31. comrxoff(portno) 

    void comrxoff

    int portno 

     Notify the peer to stop sending data. 

32. comrxon(portno) 

    void comrxon

    int portno

     Notify the peer to restart sending data.   

 

6.3 Examples 

In the distribution disk, we provide file transfer and setup program, all of these programs use PCCOM library. 

    RSETUP.C

        Setup communication parameters.

    RTX.C

        Transfer file.

    RRX.C

        Receive file. 

6.4 I/O Control Via Software Interrupt 

To  communicate  directly  with   device drivers,   the  PCCOM  provides  a   set   of sub-functions  under extended BIOS  INT  14H, and  DOS IOCTL INT 21H.  All these  functions are  included in the PCCOM library,  however, if   you  want  control  I/O   through   BIOS interrupt  by yourself, you need prepare  CPU register contents and fork a system call.  In the  following,  we will describe  these  I/O control functions and teach users to use it.  

All  BIOS  functions are designed  as  a FOSSIL  driver, the specification  of  FOSSIL driver is shown in the "FOSSIL.DOC" file. Our PCCOM BIOS functions specification are  shown in the "PCCOM.SPC" file. The examples of  DOS IOCTL   function  calls  are  shown  in   the

"COMDOS.C" file.  

Before you perform system call, you must specify sub-function number in ah register. 

Ah

Description

 00H

setup communication parameters

 01H

send one character           

 02H

receive one character         

 03H

get serial port status     

 04H

activate port

 05H

deactivate port

 06H

set DTR

 07H

return time tick information

 0AH

purge input buffer

 0BH

send one character with no wait

 0CH

nondestructive read ahead

 0FH

flow control for serial I/O

 18H

block read

 19H

block write

 1AH

break begin or end

 1BH

return information about this driver

 30H

get buffer status

 31H

set port address

 32H

set interrupt vector address

 3AH

get the number of PCCOM sets

 3BH

check port exist

 3CH

get port information

 3DH

stop sending data

 3EH

restart sending data

 3FH

set time out

 40H

get time out value

 44H

IOCTL input/output functions (INT 21H)

1. set up communication parameters 

ah register

      always set to 0h.

al register

     al   is  used  to  setup   communication parameters. 

     bit 7, 6, 5 : setup baud rate.

     bit 4, 3    : setup parity.

     bit 2       : setup stop bits.

     bit 1, 0    : setup data bits.  

baut rate

bit 7

bit 6

bit 5

9600

1

1

1

4800

1

1

0

2400

1

0

1

1200

1

0

0

600

0

1

1

300

0

1

0

38400

0

0

1

19200

0

0

0

               

     parity

4

3

     even

1

1

      odd

0

1

      none

x

0

 

stop bit

bit 2

2

1

1

0

 

data bit

bit1

bit 0

8

1

1

7

1

0

6

0

1

5

0

0

dx register

     port number.

return value (ax register)

bit 15 to bit 8 : line status.

bit 7 to bit 0  : modem status. 

  bit 15

time out error

  bit 14

transmitter shift register empty

  bit 13

transmitter holding register empty

  bit 12

0

  bit 11

0

  bit 10

0

  bit 9

Input buffer overrun

  bit 8

data available in receive buffer

  bit 7

data carrier detect

  bit 6

ring indicator

  bit 5

data set ready

  bit 4

clear to send.

  bit 3

always set to 1 upon return

  bit 2

delta data carrier detect

  bit 1

delta DSR

  bit 0

delta CTS

2. send a character 

ah register

     always set to 1h.   

al register

     character.

dx register

     port number.

return value (ax register)

     line status and modem status.       

3. receive a character      

ah register

     always set to 2h.   

al register

     received character.

dx register

     port number.

return value

     ah : line status.

     al : receive character. 

4. get port status       

ah register

     always set to 3h.   

dx register

     port number.

return value (ax register)

     line status and modem status. 

5. activate port 

ah register

     always set to 4h.

dx register

     port number.

return value

     ax : 1954h if successful.

     bl : maximum function number supported.

     bh : rev of FOSSIL specification.            

6. set DTR 

ah register

     always set to 6h.

al register

    0

turn off DTR.

    1

turn on DTR.

dx register

     port number. 

7. nondestructive read ahead 

ah register

     always set to Ch.

dx register

     port number.

return value

     ah : 0, if character is available.

     al : the read character.

     ax : FFFF, if no character is available. 

The  character read by this operation is  not removed from input queue. This means that the same character will be obtained in next  read operation. 

8. set flow control 

ah register

     always set to Fh.

al register

     enable or disable flow control. When set to 1, means enable. 

     bit 0

 enable  /  disable     receiving XON/XOFF

     bit 1

 enable / disable RTS/CTS.

     bit 2

 enable /disable DTR/DSR.

     bit 3

 enable  /  disable  transmitting XON/XOFF        

 dx register

     port number. 

9. receive block from a port 

ah register

     always set to 18h.

dx register

     port number.

cx register

     length of block.

es:di register

     starting address of block.

return value (ax register)

      count of received bytes. 

10. send block to a port 

ah register

     always set to 19h.

dx register

     port number.

cx register

    number of bytes to be sent.

es:di register

     starting address for received block.

return value (cx register)

    count of sent bytes. 

11. send break signal 

ah register

    always set to 1Ah.

dx register

    port number.

al register             

1

send break signal.

0

stop to send break signal.

12. return information about PCCOM driver 

ah register

    always set to 1Bh.

dx register

    port number.

cx register

     length of block.

es:di register

    starting address of block. 

This  function will transfer  information   about  PCCOM  and its   current status  to the  caller. 

return value (ax register)

The  data structure  (assembly  language style)currently  returned by PCCOM  is  as follows:

 ;DEFINE BEGIN OF STRUCTURE

      INFO      EQU  $            

 ;SIZE OF THIS STRUC IN BYTES

      STRSIZ    DW   INFO_SIZE   

 ;FOSSIL SPECIFICATION REV

      MAJVER    DB   CURR_FOSSIL

 ;REV OF THIS DRIVER.

      MINVER    DB   CURR_REV   

 ;"FAR" POINTER TO ASCIIZ

 ;DRIVER DESCRIPTION STRING.

      IDENT     DD   ID_STRING    

 ;BYTE SIZE OF THE INPUT BUFFER

      IBUFR     DW   IBSIZE    

 ;NUMBER OF BUFFERED RECV BYTES 

      IFREE     DW   ?           

 ;BYTE SIZE OF THE XMIT BUFFER

      OBUFR     DW   OBSIZE      

 ;NUMBER OF BUFFERED XMIT BYTES

      OFREE     DW   ?        

 ;WIDTH OF DISPLAY SCREEN

      SWIDTH    DB   SCREEN_WIDTH

 ;HEIGHT OF DISPLAY SCREEN 

      SHEIGHT   DB   SCREEN_HEIGHT 

 ;BAUD RATE, COMPUTER TO MODEM

      BAUD      DB   ?      

13. get buffer status 

ah register

    always set to 30h.

dx register

   port number.

return value (cx)

    number of characters in buffer.

    FFFh : overflow. 

14. set port address 

ah register

     always set to 31h.

dx register

     port number.

bx register

     port address. 

15. set vector address 

ah register

    always set to 32h.

dx register

    port number.

bx register

     vector address. 

16. set active status in vector 

ah register

     always set to 33h.

dx register

    port number.

al register

  0

Active low

  1

Active high

17. set modem control 

ah register

     always set to 34h.

dx register

     port number.

al register

    modem control value. 

 bit 7

0

bit 6

0

bit 5

0

bit 4

Loopback

bit 3

OUT2

bit 2

OUT1

bit 1

RTS

bit 0

DTR

 18. get port parameters 

ah register

     always set to 35h.

dx register

     port number.

return value(al)

    communication parameters. (see 00H) 

19. get modem control value 

ah register

always set to 36h.

dx register

            port number.

al register

            modem control value. 

20. get flow control value 

ah register

     always set to 37h.

dx register

     port number.

return value (al)

      flow control value. see 0fH. 

21. get the total number of PCCOM sets 

ah register

     always set to 38h.

return value (ax)

      total number of PCCOM sets. 

22. get information about each PCCOM set 

ah register

     always set to 39h.

dl register

     set number.

es:di register

     starting address of block.

return value (ax)

      number  of  bytes  returned  in   buffer point by es:di 

      register.  

Data structure : 

irq             db  ;interrupt request

portno      dw  ;total number of ports in

                         ;this set

groupno   dw  ;total number of groups in

                        ;this set

whichgroup  dw  ;specified port in which group

base         dw  ;base address for this com set

vector      dw  ;interrupt vector address

active       db  ;active hi or lo in vector

portno     db  ;total number of ports in

                       ;this com set

  :          :             :

  :          :             :

base        dw  ;base address for this com set

vector     dw  ;interrupt vector address

active      db  ;active hi or lo in vector

portno    db  ;total number of ports in  

Represented in C:

  typedef struct {

              unsigned char irq;

              unsigned int  portno;

              unsigned int  groupno;

              unsigned int  whichgroup

              struct {

                 unsigned int  base;

                 unsigned int  vector;

                 unsigned char active;

                 unsigned char portno;

           } group[8];

    } BiosComSet_t; 

23. get the total number of PCCOM ports 

ah register

            always set to 3Ah.

return value (ax)

 total number of ports. 

24. detect whether the the port is existent 

ah register

     always set to 3Bh.

dx register

   port number.

return value (ax)                         

55AA

  this port exists.

0

  this port not existent.

     

25. get information of one PCCOM port 

ah register

    always set to 3Ch.

dx register

    port number.

es:di register

    pointer   to   space   containing   port information. 

turn value (ax)

Data structure :

addr            dw  ;port address

baud_rate  dw  ;baud rate

lcr               db  ;line control register value

mcr             db  ;modem control register value

fc                 db  ;flow control protocol

q_sz            dw  ;rx ring buffer size

q_free        dw  ;free space in ring buffer

rx_enable  db  ;flag to notify the port

                         ;receivable

tx_enable  db  ;flag to notify the port

                        ;transmission

Represented in C:

typedef struct {

              unsigned int  addr;

              unsigned int  baud;

              unsigned char lcr;

              unsigned char mcr;

              unsigned char fc;

              unsigned char rx_qsz;

              unsigned int  rx_qfree;

              unsigned char rx_enable;

              unsigned char tx_enable;

           } BiosComPort_t;

26. notify peer to stop sending data 

ah register

     always set to 3Dh.

dx register

     port number. 

27. notify peer to restart sending data 

ah register

     always set to 3Eh.

dx register

    port number. 

28. set time out value  

ah register

    always set to 3Fh.

dx register

     port number.

cx register

     time out value in unit of 1/18 sec. 

29. get time out value  

ah register

always set to 3Fh.

dx register

port number.

return value (cx)

              time out value in unit of 1/18 sec. 

6.5 PCCOM DOS IOCTL functions 

Under  the  DOS interrupt  21H  and  its sub function 44H, user can use IOCTL to access PCCOM character device. 

1. IOCTL input function 

  Input:

    AH    = 44H

    AL    = 02H

    BX    = handle number

    CX    = number of bytes to transfer

    DS:DX = segment: offset of data buffer

            (viewed as control block) 

  Output:

    If function is successful:

       Carry flag is clear.

       AX    = number of bytes to transfer.

       Data buffer at DS:DX contains data

       read from device driver. 

    If function is not successful:

       Carry flag is set.

       AX = error code:        

01H

invalid function

05H

access denied

06H

invalid handle

0DH

invalid data (bad control block)

The transfer address(DS:DX) points to  a control  block  that is used  to  communicate with the device driver. The first byte of the control block determines the request that  is being made. 

Code

Bytes

Function

 0

3

get serial port status

 1

3

get port communication parameters

 2

3

get modem control value

 3

3

get flow control value

 4

3

get the size of available data in rx buffer

         ?/span>

HOME