DOS
DEVICE DRIVER DIAGNOSTIC TEST SOFTWARE PC COM V2

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

ยท




HOME