PCBoard accesses OS/2 comm ports directly, even though PCBoard is a DOS application. Many developers do not realize that a DOS application has access to the SAME function calls (file open, read, write, close as well as Device IOCtrl funcions) that OS/2 provides to native OS/2 applications. PCBoard takes advantage of this fact to allow it to directly access comm ports that otherwise would appear to be available only to OS/2 applications. Accessing OS/2 comm ports requires that you: 1) Use the standard DOS operating system function calls normally associated with files to open the comm port by name (e.g. you would open "COM2", as if it were a file, to access the comm port). You then keep track of the same file handle information to read from and write to the comm port using the standard DOS read file and write file function calls. And finally, you use the same file handle and standard DOS close file function call to close it. 2) To set port speed, check for carrier detect, turn DTR on or off, etc, you use the standard DOS IOCTL calls. The only trick here is ... IOCTL usage requires that you know what parameters to send it. And that information is provided by IBM in their OS/2 documentation. And *that* is the only reason why developers are largely unaware that the same functionality is available from DOS. As a quick example to send something to an OS/2 comm port, consider the following C source code: port = open("COM2",O_RDWR); write(port,"HELLO OS/2 WORLD!\r\n",19); close(port); Or consider this example which takes everything that comes in from the comm port and immediately sends it back out again: while (1) { BytesRead = read(port,Buf,sizeof(Buf)); if (BytesRead > 0) write(port,Buf,BytesRead); } As you can see, OS/2's usage of the file system makes receiving and sending bytes a fairly trivial matter. What's left is how to "control" the comm port and that is where the IOCtrl function calls come in. Here is an example of how you can control OS/2 comm ports: mov ax, 0x440C ;Ah=0x44 IOCTL, Al=0x0C Handle based call mov bx, [Handle] ;load BX with the comm port handle mov ch, 1 ;Category 1 functions are for ASYNCH mov cl, [Func] ;Load CL with the async function to be used les di, CmdPacket ;point to a cmd packet (or NULL if no command packet) mov si, es ;SI:DI = pointer to command packet push ds lds dx, DataPacket ;DS:DX = pointer to data packet (or NULL if no data) int 0x21 pop ds jc goback ;AX has the error code to return, return it now xor ax ;clear AX register before returning goback: ret The entire sequence up above can be wrapped into a function call which you can then call from anywhere within your C source code. For example, you might wrap a prototype such as the following around it: int DevIOCtl(int Handle, int Func, void far *DataPacket, void far *CmdPacket); With the above prototype, you could then set the port speed for a comm port by using the following code: long BitRate = 38400L; DevIOCtl(Port,0x41,NULL,&BitRate); Or to turn the DTR signal off, you might use the following code: int Mask = 0xFF01; /* FF = don't turn any off, 01 = turn DTR on */ long RetVal; /* return value */ DevIOCtl(Port,0x46,&RetVal,&Mask); ------------------------------------------------------------------------------ The above examples are meant merely to give you an idea as to HOW you can accomplish the task of accessing OS/2 comm ports from with a DOS program. This information is NOT meant to be a complete tutorial or reference on accessing OS/2 comm ports. It is recommended that you obtain, from IBM, the OS/2 API Reference Guide to obtain information on the IOCtrl function calls. A commonly found document, called GUIREF20.INF, which is viewable using OS/2's "VIEW" command, can be used to obtain this information. ------------------------------------------------------------------------------ Tips: Beyond the technical details of "how" to program OS/2 comm ports from a DOS application, there remains the issue of how to "optimize" your program to get the best performance possible. A few key ideas to keep in mind are: - You can send data as fast as you want by writing data to the comm port handle. OS/2 will take care of making sure that the data is fed to the comm port as fast as it can be accepted. - Obtaining data from the comm port will "block" your application if there is nothing in the comm port to be read in. This can be highly desirable in that it means your application gets *no* attention from OS/2 (no CPU cycles are wasted) unless you have data in the port to be read in. HOWEVER, if your program needs to be able to monitor local keystrokes while waiting for comm port data, or if your program has some other work to do, you will have to AVOID using this capability due to the fact that your DOS application cannot have multiple threads of execution and you don't want the entire application to be blocked. Instead, what you might consider doing is setting the Read Timeout value (IOCtrl function 53h) to a low enough value that control can be given back to you quickly if there are no bytes waiting in the input buffer. - Another thing to consider is that these function calls (read/write/ioctl) are "expensive" function calls in terms of CPU time. In other words, if you spend a lot of time calling these functions you may send the CPU usage right through the roof. For example, if you need to recognize when carrier is lost, you won't want to set up a tight look that continually calls IOCtrl to find out if carrier is lost because the CPU will be busy doing almost nothing but that function. Instead, what you might want to do is create some kind of "interval" at which you will make that function call (perhaps once a second, or whatever you deem appropriate). With these kinds of ideas in mind, you can "tune" your application to make the best use of the OS/2 API's possible.