PLIP112.TXT (for PLIP v11.2, June 2003) by Fred C. Macall Introduction The first time I tried PLIP v11.1 was a pretty disappointing experience. Well, I am here to tell you that this story has a happy ending. Getting to that depended, for the most part, on some fixes and enhancements I have made in PLIP v11.2. However, an attitude readjustment and some big discoveries have also played roles in this success story. The big discoveries have to do with TELBIN and TRMPING (introduced below), a strange relationship existing between them, and a Windows 9x configuration "secret". At the time of this writing, at the end of June 2003, I have successfully used PLIP v11.2 to make DOS-DOS, DOS-Linux, and DOS-Windows 9x parallel port TCP/IP connections between PCs of widely varying vintage and speed. I have every reason to expect that this technology also makes Linux-Linux, Linux-Windows 9x, and Windows 9x-Windows 9x parallel port TCP/IP connections feasible. (The Linux kernel's plip module provides packet driver(s) for Linux on the connections with Linux. Linux or Windows TCP/IP applications replace TELBIN and TRMPING in the Linux or Windows environments.) These connections should support all of the usual TCP/IP applications and tools nearly as well as ethernet connections do. Meanwhile, my big disappointment came the day I tried connecting parallel ports, on my PCs: Booker and Sailboard, with a "LapLink parallel cable". Booker and Sailboard were both running DOS and PLIP version 11.1, which is a packet driver TSR for parallel ports. One of them was running TELBIN.EXE version CUTE:2.2D/BC-Rutgers-1.0, as a TCP/IP FTP server. The other was running the FTP.EXE version 0.70 TCP/IP FTP client. I was also using tvdog's undocumented ping.exe (45,024 octets), which I have renamed TRMPING.EXE, and a WATTCP based PING program, which I have renamed WATPING.EXE, for testing. This kind of setup has worked well for me with interconnected ethernet cards and matching packet driver TSRs in place of the interconnected parallel ports and PLIP TSRs. With 10 M bits/second ethernet cards, this kind of setup usually provides transfer rates around 125 K bytes/second. So, there is the beginning of our attitude readjustment. That transfer rate is only about a tenth of what we might expect from dividing 10 M bits/second by 8 bits/byte. But, the parallel ports based setup didn't seem to work at first. Then, after some ping testing, it started working after a fashion. The ping tests were reporting long response times and relatively high packet loss rates. I was able to transfer a file from Sailboard to Booker with TELBIN running on Booker. I think the transfer rate was about 2 K bytes/second. When I tried to repeat the same transfer from Sailboard to Booker with TELBIN running on Sailboard, Booker hung in FTP. The system timers on both PCs lost a lot of time during the transfers that succeeded. Oh, and did I mention that strangely colored digits between 0 and 7 were crawling up the right hand column of the displays? So, I gave LapLink version 3 a turn on Booker and Sailboard. It seemed to validate my parallel port hardware setup by doing my test file transfer, in either direction, at an average rate of about 48 K bytes/second. The DOS INTERLNK/INTERSVR package is nearly as fast. However, I haven't found any software that can beat LapLink's file transfer speed, on lowest common denominator ("4 bit") parallel ports and cabling. So, here is some more attitude readjustment. The parallel ports transfer rate to beat is only about a 25th of the rate we might have estimated at first for 10 M bits/second ethernet cards. Although I haven't yet told you what transfer rate I was finally able to get with PLIP and the TCP/IP FTP applications, you probably can guess by now that it was quite a bit less than what LapLink can do. So, before I waste your time with the rest of this story, let me point out some things that have become obvious: If you've decided to use a parallel port connection to share, say, a CD-ROM reader between two PCs that can both run DOS, you'll be better off using something like LapLink or INTERLNK/INTERSVR. On the other hand, if you're looking for a low cost or temporary way to connect an odd PC running DOS into a TCP/IP based network (and on to the internet), then read on! If you want better networking performance than lowest common denominator parallel ports and PLIP will provide, you may as well put an ethernet card into your odd PC. Your network connection will need to be made via a PC running a DOS bridge program such as YAPCBR, Linux, or Windows 98. Though DOS-Windows 95 parallel port TCP/IP connections may be made, Windows 95 seems to have to be an end point for the communications on such connections. That is, I haven't found any way to get Windows 95 to relay or route those communications. It looks as though this depends on adding an EnableRouting=1 value to the MSTCP section of SYSTEM.INI or the registry. When I tried this, Windows hung in the next boot, saying: Windows protection error. I had to copy SYSTEM.DA0 over SYSTEM.DAT in order to restore my registry and get Windows up again. Since performing that trial, I have found Microsoft knowledge base article Q142543. It confirms the behavior I experienced. Q142543 goes on to say: "IP routing is not a supported feature of Windows 95." My experience is that this limitation has been removed from Windows 98 SE. I am not sure which side of the IP routing limitation fence Windows 98 (first edition) falls on. However, I haven't found a knowledge base article like Q142543 that mentions Windows 98. Names and References Bashful -- My 1994 vintage '486DX-66 based desktop PC. Ran DOS and NAPT with a 56 K dial modem and ethernet card to provide an Internet gateway for this report's trials. Booker -- My 1995 vintage Pentium-166 based notebook PC. Ran DOS for this report's trials. Digerydo -- My 1997 vintage Pentium-150 based desktop PC. Ran DOS and Windows 98 SE for this report's trials. DosLynx v0.24b -- DOS Web browser for lowest common denominator PCs. http://members.nccw.net/fmacall/dlx24bin.zip DOSPLIP -- A package, by Mike Leonhard, including LSL.COM, PDETHER.EXE, PLIP.COM v11.1, and a README.TXT explaining how to set them up to make PLIP usable, as an "Existing ODI Driver", in Windows 9x. (This package's otherwise thorough document seems to omit an important Windows 9x configuration secret or instruction that had to be rediscovered during the course of work reported here.) http://www.tamale.net/windows/dosplip.zip EPPPD -- DOS PPP client packet driver emulator TSR. It is the heart of the DOSPPP06 package. http://personal.redestb.es/tonilop/dosppp/dosppp06.zip FTP v0.70 -- DOS FTP client program based on the Waterloo TCP/IP stack. ftp://ftp.oldskool.org/pub/tvdog/internet/ftp07.zip ftp://ftp.oldskool.org/pub/tvdog/internet/ftp07.txt INTERLNK/INTERSVR -- DOS file and printer sharing add on for serial and parallel PC connections. Included in Microsoft DOS versions 6.x and Windows 95. INTERLNK is a block device driver installed in the "client" machine's CONFIG.SYS. INTERSVR is a server program for the "host" machine. http://www.microsoft.com/ LapLink -- DOS (and, in later versions, Windows) file transfer program for serial and parallel PC connections. (The latest version(s) of LapLink don't support parallel port connections anymore.) http://www.laplink.com/aboutus/ LapLink Parallel Cable -- Also known as: Parallel Data Transfer Cable. Five data outputs are connected to five sense inputs, in each direction. With a signal ground lead, these make an eleven wire cable. Some Internet sites appear to be offering cables like this for as little as $ 2.95 for a six footer. NAPT -- DOS Network Address Port Translator (Internet gateway) program, for use with packet drivers. It is the heart of the Internet Extender package. http://www-acc.scu.edu/~jsarich/ieweb/download.htm PARALLEL v1.45 -- DOS Parallel Port Information Utility program. This tool can tell you if your parallel port(s) are better than lowest common denominator. (With PLIP, that doesn't matter.) And, together with a simple paper clip loopback jumper, it can check a port's IRQ number, IRQ input level sensing polarity, and IRQ functionality. The package includes a large documentation file. ftp://ftp.lpt.com/parallel/para14.zip parport.txt -- A documentation file included with the Linux kernel source since kernel version 2.1.33. This file may be found at: /usr/src/linux/Documentation/parport.txt in your Linux system. It explains how parport.o, parport_pc.o, and parport_probe.o have to be used with lp.o, plip.o, and other parallel port using modules, starting with version 2.1.33. http://www.charmed.com/support/kernel/docs/parport.txt PLIP v11.1 -- DOS packet driver TSR for PC parallel ports, with source. Portions Copyright 1992, Russell Nelson (The present package appears to have been published in 1995.) ftp://ftp.crynwr.com/drivers/plip.zip PLIP v11.2 -- Fred Macall's June 2003 update of Russell Nelson's package. http://members.nccw.net/fmacall/PLIP112.ZIP PLIP -- Linux PLIP Mini How To document. Includes a section on using PLIP for DOS-Linux interconnection. (This document has fallen behind developments in the newer Linux kernels. You may have to take parts of it as only a guide. In addition to the Linux parallel port support changes discussed in parport.txt, newer Linux kernels may incorporate "ipfw" or "ipchains" facilities that will have to be administered to enable TCP/IP packet forwarding.) http://www.ibiblio.org/pub/Linux/docs/HOWTO/mini/PLIP Q142543 -- Microsoft Knowledge Base article entitled: Windows 95 Hangs with TCP/IP Routing Enabled ftp://ftp.microsoft.com/MISC/KB/en-us/142/543.HTM Sailboard -- My 1994 vintage '486DX-33 based desktop PC. Ran DOS, Linux, and Windows 95 for this report's trials. TELBIN vCUTE:2.2D/BC-Rutgers-1.0 -- Clarkson University (DOS) TCP Communication Package (Rutgers Interim Release). Used as an FTP server for this report's trials. ftp://ftp.oldskool.org/pub/tvdog/internet/cutcp-b.zip TRMPING -- tvdog's undocumented DOS ping.exe program, renamed. ftp://ftp.oldskool.org/pub/tvdog/internet/ping.exe ftp://ftp.oldskool.org/pub/tvdog/internet/ping.txt WATPING -- DOS PING program based on the Waterloo TCP/IP stack, renamed. One of a number of WATTCP applications included in: http://www.ncf.ca/ncf/pda/computer/dos/net/watapps1.zip YAPCBR -- Yet Another (DOS) PC BRidge program, for use with packet drivers. ftp://ftp.crynwr.com/drivers/ypcbr102.zip Zeke -- My 1988 desktop PC with switch selectable 8088 and '286 processors. Its 8088 processor was used for most of this report's trials. This machine's parallel port has inverted level interrupt sensing. Ran DOS v3.3 for this report's trials. Preliminary Revisions Since the PLIP package includes complete assembler source, I decided to have a look and see if I could find what might be causing the poor results I was getting. I had noticed that the results seemed to depend on which end of the Booker/Sailboard connection was running TELBIN. That suggested that I was looking for timing issue(s). I found that all of the source goes into just three modules, which are easy to assemble and link. The three modules come from HEAD.ASM, PLIP.ASM, and TAIL.ASM. Those sources carry INCLUDEs for all of the other .ASM files used. Well, after reading the three assembly listings for a day or two, I had found a number of questionable or debatable things. That is, things that might or might not be contributing to the poor results that I was getting. I was able to see these things relatively quickly because this software is so well structured and commented. Most of the questionable things I found were easier to "fix" than to be proved culprits. So, I simply fixed them to my liking. I've added comments, documenting the changes I made, to the beginning of each .ASM file that I revised. There are only five of these. Also, for the most part, I've used upper case assembler mnemonics on the lines I've changed or added. Perhaps the thing most clearly in need of fixing, that I found at this point, had to do with how recv_byte sampled or strobed the four bit data nibbles that it receives. (recv_byte is located in the PLIP.ASM module.) The packet sender at any given time signals the presence of each new data nibble by toggling the fifth data bit that it OUTputs in parallel with the new nibble. recv_byte INputs the five interconnected sense lines, in a loop, while waiting for that fifth bit to change. The first INput nibble accompanied by the expected fifth bit value was being taken as the received nibble. Well, that approach depends on any skew, in the timing of the signal changes among the five bits, being such that the fifth bit is never seen to change until after all of the data bits have their correct values. I don't know that there is anything in typical parallel port interfaces or cables to assure that. However, if it is ever possible for the fifth bit to be seen to change before all four data bits have their correct values, I am sure that recv_byte would then, at least occasionally, mis-read a received nibble. To fix that exposure, I've extended recv_byte to continue its loop until it has INput two consecutive matching nibbles with the expected fifth bit value. The loop timing is such that this precaution should accommodate more noise and timing skew than will ever be experienced with cables of a reasonable length. With this fix, recv_byte will require at least one additional loop cycle for each received nibble. Clearly, I have traded a performance reduction for a reliability improvement. That probably makes this fix just as debatable as my others. I also found a couple of obvious lapses in PLIP's (debug) statistics collecting. send_pkt's exceptions weren't being counted in the errors_out count. So, that count was always zero. And, relatively harmless "spurious interrupts", which occur quite frequently in some environments, were being counted along with more significant receive exceptions in the errors_in count. That seriously diminished the usefulness of the errors_in count. To fix these problems, I added some code to f_send_pkt in HEAD.ASM, to count send_pkt calls returning an exception indication, in the errors_out count. And, I added a new count called spurioushwints. I have revised recv, in PLIP.ASM, to increment that count, rather than the errors_in count, when it detects a spurious interrupt. That leaves the errors_in count free to report unambiguously on the other kinds of receive exceptions. Antique Hardware Hack Command Line Option Well, my real goal in this project was to get my oldest PC, Zeke, connected into my home network. Zeke has no ethernet card. I hoped to accomplish my objective by means of a parallel port connection to my PC, Digerydo. Digerydo is the one PC in my home network that usually runs Windows 98 SE. A parallel printer port is available on Digerydo because my network's printer is connected to Sailboard. (Unfortunately, a parallel port interconnection will be contending with a Zip drive for use of Zeke's parallel port.) So, my next step was to move my LapLink parallel cable to connect Zeke and Digerydo. This section's trials were performed with Digerydo running DOS. With both machines running PLIP, it quickly became clear that Zeke was not receiving much, if anything, from Digerydo. However, INTERLNK/INTERSVR works fine on this connection. (When I use that software, Zeke runs INTERSVR and Digerydo runs INTERLNK.) For a third vote, I tried LapLink version 3. It wouldn't work on the connection, seconding PLIP. After a lot of head scratching, I finally ran PARALLEL on Zeke. I could immediately see that PARALLEL's report for Zeke was different from the ones it had given for Booker and Sailboard. PARALLEL reported that the ACK line input level polarity triggering an IRQ is reversed from normal on Zeke's parallel port! This may stem from confusion in the early years of the PC industry over IBM's convention for this interrupt. I haven't opened Zeke up to see if it might have a jumper or switch for changing this polarity. PLIP uses the parallel port's IRQ to start its receive process when the other end's PLIP wants to send a packet. While idle, both PLIPs send 00000 on their respective sets of five interconnected data lines. When either PLIP wants to send a packet, it changes its code to 01000 to bid for the transfer. The changed data line in that bid code is connected to the other end's ACK input. A 0 to 1 transition on that line is expected to trigger an IRQ in the PC that is to receive. If the ACK input's interrupt polarity is reversed, a 1 to 0 transition is needed instead, on that line, to produce an IRQ. So, Zeke wasn't getting IRQs signalling Digerydo's attempts to send. And, that was keeping Zeke from receiving Digerydo's packets. I decided to see if I could fix this by changing PLIP's bid code. An interrupt awakened PLIP responds to a sending PLIP's bid by changing the 00000 (idle code) it is sending to 00001. Seeing that, the sending PLIP uses 1abcd to convey its first nibble of packet (length) data. Seeing that, the receiving PLIP sends 10000. Seeing that, the sending PLIP uses 0efgh to convey its second nibble of (length) data. Seeing that, the receiving PLIP sends the 00000 idle code again. Seeing that, the sending PLIP uses 1jklm to convey its third nibble. And, so on. At the end of the packet, the sending PLIP returns to sending the 00000 idle code again. I wanted to choose a new bid arrangement that wouldn't necessitate introducing complication(s) into that packet data transfer procedure. I decided to provide a command line option to change PLIP's bid code to a fairly rapidly alternating sequence of 01100 and 00100. This sequence will quickly produce an interrupt in the intended receive machine, whatever input level it senses to trigger its IRQ. The constant 1 bit in the new sequence will allow an interrupt awakened PLIP to quickly verify that a bid is being presented. At the same time, an interrupt awakened PLIP also will be able to honor the old bid code by recognizing any of the three 0xy00 codes containing a non-zero xy. I've designated the new command line option: -a to suggest the idea of an antique hardware hack. The new -a command line option may be used freely where PLIP v11.2 is being used at both ends of a parallel ports connection. It has to be used in a PC opposite one with an inverted input level sensing IRQ. Unless timer interrupt driven receiving is configured in the PC with the inverted IRQ. The timer interrupt driven receiving arrangement that I've also provided is introduced near the end of the section headed: DOS-Windows 9x Parallel Ports Connection, Part 1. The -a command line option probably has to be avoided for DOS PLIP to remain compatible with the Linux kernel's plip module (and DOS PLIP version 11.1), until it can recognize the new bid codes. I resumed testing with updated PLIPs in place on Zeke and Digerydo, and with -a specified on PLIP's command line on Digerydo. The good news was that the connection then seemed to be "solid". PING tests no longer showed lost pings or real long response times. I was using TRMPING a lot at this point. The bad news was that my file transfer tests, for both directions, obtained an average transfer rate of (only) about 3 K bytes/second. That's comparable to the maximum download (but not upload) transfer rate obtained with EPPPD on a 56 K modem and a faster machine (Bashful). I attribute this poor throughput to Zeke's slowness. (I estimate that Bashful's processor is about forty times faster than Zeke's.) In contrast, COPY commands for transfers in both directions yielded an average file transfer rate of about 13 K bytes/second over a parallel port INTERLNK/INTERSVR connection between Zeke and Digerydo. At this point, Zeke was able to contact the Internet via Digerydo running YAPCBR, my ethernet LAN, and Bashful running NAPT with a 56 K modem and EPPPD. Web surfing with DosLynx was noticeably faster than it has been with Zeke's 19.2 K baud dial modem and EPPPD. Of course Digerydo, running YAPCBR, had to be dedicated to this exercise. DOS-Linux Parallel Ports Connection I decided that I would be leaving Zeke connected to Digerydo. So, I got another LapLink parallel cable for more Booker to Sailboard testing! I wanted to verify that the changes I was making in PLIP v11.2 weren't disrupting its compatibility with the Linux kernel's plip module. (With the -a command line option not specified.) I did my testing with Booker running DOS and PLIP v11.2. And, Sailboard running Linux kernel versions 2.0.30 (from Slackware Linux v3.4) or 2.2.14-5.0 (from Red Hat Linux v6.2). The Linux PLIP mini How To instructions guided me through the arrangements I needed to make, with the version 2.0.30 kernel, pretty well. lp.o gets loaded while Linux is booting. And, both of Sailboard's parallel ports are strapped for IRQ 7. So, I used the following sequence to load plip.o: rmmod lp insmod plip io=0x278 irq=7 However, that wouldn't work with the 2.2.14-5.0 kernel. From parport.txt, I learned that a sequence like the following is needed with the newer kernels: rmmod lp rmmod parport_probe rmmod parport_pc rmmod parport insmod parport insmod parport_pc io=0x278,0x378 irq=7,none insmod plip (The first part of that sequence is only to undo module loading that my Linux system performed while booting. The rmmod parport insmod parport commands aren't necessary in that case. I've included them to make it clear that parport.o is needed for parport_pc.o and plip.o. Also, note that the port(s) configuration specification has moved from plip.o to parport_pc.o.) If you aren't sure how your modules are structured, you can command: modinfo -adp to check them out. The use of arp in ifconfig commands is one other area that may be found troublesome in establishing DOS-Linux or Linux-Linux parallel port TCP/IP connections. The rule is: For a DOS-Linux connection specify arp in your ifconfig up command. For a Linux-Linux connection, don't specify arp in your ifconfig up command. Note that when you use ifconfig to report on the setup you've achieved, NOARP will be reported if arp hasn't been instated. But, with the Slackware v3.4 ifconfig at least, there won't be any mention of arp if it has been instated! I performed my final timing trials for this arrangement after making the big discoveries reported in the section below headed: Digression on TRMPING, do_timeout, and TELBIN. And, after finalizing PLIP v11.2. At that time, I had Booker running DOS, PLIP v11.2, and TELBIN, as an FTP server. Sailboard was running Linux kernel v2.0.30, its plip module, and the Slackware v3.4 ftp client. With TELBIN "primed" by TRMPING, my standard file transfer test averaged about 24.6 K bytes/second, for both directions. Wow! That's the fastest parallel port TCP/IP connection transfer rate I've obtained. I repeated this test with Booker unchanged and Sailboard running Linux kernel v2.2.14-5.0, its parport, parport_pc, and plip modules, and the Slackware v3.4 ftp client. The transfer rate obtained in the Sailboard to Booker direction was almost the same as with kernel v2.0.30. However, the transfer rate in the Booker to Sailboard direction was then a lot slower. The average for both directions was (only) about 5.2 K bytes/second. This wasn't a complete surprise because my Linux system feels sluggish when running the version 2.2.14-50 kernel. And, because the parallel port modules were still relatively fresh from their restructuring in that version. I can only hope that the version 2.4+ kernels have now returned to a performance level more like that of the trusty old version 2.0.30! DOS-Windows 9x Parallel Ports Connection, Part 1 Mike Leonhard has provided pretty thorough instructions, in his DOSPLIP package, for using PLIP in Windows 9x. The essence of his setup is that LSL.COM and PDETHER.EXE are used together with PLIP.COM to provide the appearance of an ODI Driver. If you add this trio of TSRs to your AUTOEXEC.BAT, or provide any other way to run them from DOS before starting Windows 9x, then an "Existing ODI Driver" will appear in your Control Panel's Network applet! To be sure, I am using LSL.COM and PDETHER.EXE, from Mike's package, along with the version 11.2 PLIP.COM that I'm releasing. Mike's procedure goes on to add the Windows 9x IPX/SPX compatible protocol to bind with the PLIP based ODI Driver. I have found that the Windows 9x TCP/IP protocol may be bound with this ODI Driver, instead or as well. When this is done, Windows adds ODIHLP.EXE to the trio of PLIP, LSL, and PDETHER, in your AUTOEXEC.BAT. ODIHLP.EXE comes from your Windows installation media. The stack of "wedge" components LSL, PDETHER, and ODIHLP fit PLIP to the role of a "Real Mode NDIS 3 Driver"! Well, I guess I'm a little slow about Windows. Because as soon as I tried this arrangement out, on Digerydo, I ran into a bit of a problem that Mike's paper hadn't prepared me for. The tables were turned. Now it was Digerydo that couldn't receive packets from Zeke. Having seen this problem the other way around, the symptoms were unmistakable. I learned that, as Windows 9x runs in the i386's protected mode, parallel port IRQs will have to be "handed down to the real mode or virtual 86 mode IRQ handler". In this case, that's to PLIP. That wasn't happening and I couldn't figure out, right away, how to tell Windows to do that. At one point, I tried removing the existing Windows parallel port "device", lpt.vxd, from my configuration. But, Windows reinstalled it, all by itself, at the next boot! Then, I renamed it lpt.vx$. But, PLIP still received no interrupt(s). I had visions of having to write a Windows .vxd to convey the parallel port's IRQs to PLIP. While stuck on the issue of getting Windows to give PLIP its interrupts, I noticed that LSL hooks the timer interrupt vector (INT 008h for IRQ 0). And, Windows does hand the timer interrupts down to the real mode TSRs. So, I decided to augment PLIP with a timer interrupt driven receiver routine. This also might come in handy for a DOS-Linux connection in need of an -a option setting that the Linux plip module can't provide. As it stood in version 11.1, PLIP provided no receiver routine when a value of 0 was specified on the command line. So, in version 11.2, I have revised PLIP to provide the new timer interrupt driven receiver routine in that case. Well, the new timer interrupt driven receiver routine eventually did provide an error free, but slow, DOS-Windows 98 SE parallel port TCP/IP connection between Zeke and Digerydo. Before this arrangement worked for TRMPING on Zeke, however, I also had to deal with a problem, in PLIP's do_timeout routine, that turned out to be caused by TRMPING! Eventually, I figured out how to get Windows to hand the parallel port's IRQs down to PLIP. As parallel port interrupt driven receiving is much faster and more efficient than timer interrupt driven receiving, I'll return to configuring Windows for that after the following digression: Digression on TRMPING, do_timeout, and TELBIN TRMPING was unable to send its pings from Zeke to Digerydo the first time I tried to use a timer interrupt driven receiving routine in PLIP on Digerydo. That was puzzling because WATPING and TELBIN didn't seem to be having any trouble sending from Zeke! The trouble turned out to be due to a timeout in the send_pkt_1 loop in send_pkt in PLIP.ASM. This loop is where a PLIP bidding to send a packet waits for the other PLIP to respond to its bid. The loop contains a call, to do_timeout, which checks to see if an initially specified timeout period has elapsed. I tried increasing the loop's initial timeout specification temporarily, to avoid the timeout that was occurring, and found that it had to be increased from 18 to about 90. do_timeout's arrangements are such that this increase is expected to increase the loop's timeout from about half a second to about 2.5 seconds. Why should a 2.5 second timeout have to be specified to accommodate a 1/18th second timer interrupt driven receiver response time at the other end? Well, note that 2.5 * 18 is 45. I realized that TRMPING must have loaded the system timer's count latches with data that would yield a one millisecond timer period, for measuring round trip ping time! The system timer must be cycling at about 56 times its normal rate when TRMPING is running. As it stood, do_timeout couldn't help but reflect the system timer's speed up in its timeout determination. do_timeout is defined in TIMEOUT.ASM, which is include(d) in PLIP.ASM. It assumed the system timer's count latches contain zero, which specifys a timer cycle length of 65,536. (Anything else would specify a timer cycle length shorter than 65,536.) It tracked the system timer's cycles by subtracting the timer's present count from its previous count on each call it received. As the system timer is counting down, those differences normally were the call-to-call elapses in counts of 1.19 mhz reference clock cycles. do_timeout doubled those call-to-call elapse counts and added them up, in a 16 bit word, to get a value that cycled at twice the system timer's cycle rate. do_timeout's sum of elapses continued to cycle at twice the system timer's increased cycle rate when TRMPING's tampering shortened that cycle. So, do_timeout then declared a timeout in about a 56th of the intended time. There was nothing wrong with do_timeout's assumption. TRMPING appears to be altering a PC resource that is intended to be left alone. But, I wanted to see if I could find a way for do_timeout to tolerate that tampering. After all, do_timeout's determination doesn't have to be very precise. It just needs to roughly track the 1.19 mhz reference clock. Through observations of the system timer's counts that don't depend so much on an assumption about its cycle length. In short, do_timeout needs to be able to more-or-less ignore the one big elapse observed in each system timer cycle, just after the system timer's counter has been reloaded with a shortened count. I realized that the one big elapse per shortened system timer cycle came from the borrows made by the elapse calculating SUB instruction that do_timeout used. Get rid of those borrows, and do_timeout's elapse calculations get a little noisey. But, they then no longer include that big once per cycle error pulse. So, I've changed do_timeout's SUB instruction to an XOR instruction! To see how that works, suppose PLIP is running on a very fast processor. A processor so fast that PLIP's wait loops can make a do_timeout call often enough for it to sample every system timer count. Then, the XOR instruction will get 1 in the least significant bit every time the system timer count is found changed. For a full timer cycle, those 1s add up to 65,536. The next (more significant) bit will be seen to be 1 every other time the system timer count is found changed. Those 1s have a weight of 2 and, for a full timer cycle, add up to 65,536, as well. And, so on. So, for a full timer cycle, the XOR instruction's elapses may be seen to add up to sixteen times what the SUB instruction's elapses added up to. If the system timer's count latch contents should be changed from zero, the XOR instruction's elapses won't accumulate as fast as they did with a full timer cycle. Because some of the most significant bits in the XOR's elapses may always be zero. With tampering like TRMPING's, this slow down might be expected to only be about 38 percent. That's much more stable than the 56 times speed up that the SUB instruction's elapses produced in this case. Well, what if the processor isn't so fast, you wonder? In that case, the XOR instruction's elapses will tend to be missing 1s in the least significant bit positions. (The SUB instruction's borrows make up for those missing 1s and keep its elapses accurate in this case.) Again, the XOR instruction's elapses will accumulate at a slower pace. Again, the resulting slow down is expected to be relatively mild. On the basis of this analysis, I have also changed do_timeout's elapse doubling SHL instruction to a halving SHR instruction. This brings the revised do_timeout's timeouts to perhaps a little less than about a quarter of what they were. If the effects discussed just above lengthen these timeouts, they have a way to go before they get longer than they were. With do_timeout's sequence of SUB and SHL instructions changed to XOR and SHR, TRMPING worked as well as the other TCP/IP tools and utilities on the DOS-Windows 98 SE connection, with timer interrupt driven receiving in Windows 98's PLIP. This connection was solid, but slow. Using PLIP's -d command line option on Digerydo, to get PLIP hooked into the timer interrupt chain ahead of LSL, didn't seem to help its speed. Windows 98's DOS window PING command, working against TELBIN on Zeke, reported an average round trip time of about 51 milliseconds. While doing this work, I slowly came to realize that the effect of TRMPING's tampering wasn't confined to the period of its own run. I found that after running TRMPING, and ending it with the Esc key, TELBIN tends to yield faster transfers than it would otherwise! I suppose TRMPING leaves the system timer running a shortened cycle. And, I suppose TELBIN has some system timer based procedure(s) that get speeded up as a result. Since changing do_timeout, TRMPING's apparent effect on TELBIN isn't as pronounced as it was. However, that effect remains observable. Since making this discovery, I have been careful to always use a "priming" TRMPING run ahead of each TELBIN run. So, I'm reporting TELBIN transfer rates favorably influenced by TRMPING's tampering. TRMPING doesn't seem to have any effect on subsequent WATPING or FTP runs. DOS-Windows 9x Parallel Ports Connection, Part 2 Fortunately, I have learned how to get Windows 9x to hand the parallel port's IRQs down to PLIP. This is accomplished by first "Reserving" the needed IRQ "Resource". To do this, work through Windows' screens as follows: Start Settings Control Panel System Device Manager * View Devices by Connection Computer Properties Reserve Resources * Interrupt Request Add Enter parallel port's IRQ number. Ok Ok Ok Next, remove any software "devices" already claiming the parallel port's resources. Once the parallel port's IRQ has been "Reserved", it won't get reclaimed if Windows reinstalls these "devices" later. Don't forget to remove any Parallel Port Zip Drive device driver software you might have installed in CONFIG.SYS or Windows! After a reboot, you should find Windows relaying the parallel port's IRQs to PLIP. After changing the specified to Digerydo's PLIP command from 0 to 7, I rechecked the connection's average round trip ping time, with Windows 98's DOS window PING command. The reported average has improved from 51 milliseconds to 21 milliseconds. TRMPING is reporting a round trip time of 24 or 25 milliseconds, from Zeke's end of the connection. My standard file transfer test, conducted with Windows 98's DOS window FTP client on Digerydo and TRMPING primed TELBIN, as an FTP server on Zeke, has an average transfer rate, for both directions, of about 4 K bytes/second. That's about 25 percent faster than what I obtained with a DOS-DOS parallel port TCP/IP connection between these machines. Using the ROUTE ADD . . . command, to make couple of additions to Digerydo's route table, enabled Zeke to contact all of the systems on my LAN. And, all the systems on my LAN are able to contact Zeke. I found that these additions persist across boots and don't have to be provided from a start up batch file. I am able to surf the Web via DosLynx running on Zeke and my Internet gateway on Bashful. This works better than ever and Digerydo no longer has to be dedicated to this activity. My main goal has been fully attained! Clean Display Command Line Option The colored digits between 0 and 7, that I found appearing at the right end of the bottom line of the display, turned out to be the result of a debug feature left in recv_real, in PLIP.ASM. Each new debug digit displayed signals that a bid has been recognized and that a packet receive operation is starting. I became somewhat attached to seeing these once I understood what they represent. However, as PLIP started working better and better, they seemed less and less appropriate. I wondered if I wanted to see debug digits like these from the packet drivers for my ethernet cards? Well, I guess not. As a finishing touch for my revision of PLIP, I've added a -c command line option to keep recv_real's debug digits off the display. You might think of that as the Clean Display option. Unresolved Issues All but two of the unpleasant issues I recognized in my first encounter with PLIP version 11.1, on my DOS-DOS parallel port TCP/IP connection between Booker and Sailboard, have been resolved in PLIP version 11.2. In particular, the connection now seems solid. Its reliability no longer depends on which ends of the connection are running TELBIN and FTP. Or, on whether TRMPING has been run. The remaining issues are: The system timers still loose time. And, the file transfer rates obtained still leave a lot to be desired. They are still poor in comparison with LapLink. Also, the file transfer rates still seem to be a little sensitive to which ends of the connection are running TELBIN and FTP. And, on whether TRMPING has been run ahead of TELBIN. The most consistent (with respect to transfer direction) and fastest average DOS-DOS transfer rate comes with TELBIN running on Sailboard. Before TRMPING has been used, an average transfer rate of just over 10 K bytes/second is obtained for both directions with this setup. After running TRMPING on Sailboard, an average rate of about 11.4 K bytes/second is obtained. Moving TELBIN to Booker brings both the fastest and the slowest DOS-DOS transfer rates obtained. But, the average is significantly depressed by that slow transfer. It is about 5.8 K bytes/second before any use of TRMPING. And, about 6.8 K bytes/second after using TRMPING on Booker. So, these transfer rates range from an eighth to a quarter of the average transfer rate delivered by LapLink version 3. My observations are all from watch based transfer timings, to avoid inflation due to the system timer losses. The system timer losses are probably attributable to PLIP's keeping all maskable interrupts disabled during each packet's transmission. As it was, PLIP was leaving interrupts enabled while receiving each packet. This meant that the transmitter's masked periods were being extended by the receiver's timer and other interrupt(s) processing! In PLIP version 11.2, I've added maskable interrupts disabling during each packet's reception. This minimizes the maximum duration of interrupts disabling and may have reduced the system timer losses a little. This may have also improved PLIP's reliablity for connections between PCs of widely differing speeds. fcm