Category : Alternate Operating Systems - Quarterdeck DesqView, CP/M, etc
Archive   : PCCAPP.ZIP
Filename : ETHER.CC

 
Output of file : ETHER.CC contained in archive : PCCAPP.ZIP
// ether.cc: Print the first 14 bytes of all packets received. Stops
// when 100 packets have been received.
#include "OutputStream.h"
#include "NameServer.h"
#include "VirtualPCInterface.h"
#include "VirtualPCArgs.h"
#include "VirtualPCRegisters.h"
#include "VirtualPCRegisterQueue.h"
#include "VirtualPCRegisterQueueStar.h"
#include "Byte.h"
#include "Assert.h"

const int bufferSize = 20480;

void processPackets (int packetDriverInt, int packetBufferInt);
void getAddress (int packetDriverInt, int handle, char *addr);
int beginAccess (int packetBufferInt, unsigned short bufferSegment,
int bufferSize);
void endAccess (int packetBufferInt);
unsigned short allocateLowMemory (int size);
void deallocateLowMemory (unsigned short bufferSegment);
int findPacketDriverInterface ();
int findPacketBufferInterface ();
int findPacketReadyInterrupt ();

VirtualPCInterface *virtualPC;
VirtualPCRegisterQueue *queue;
VirtualPCArgs args;

main ()
{
// Fetch the virtualPCInterface.
virtualPC = (VirtualPCInterface *) StandardNameServer -> lookup
("virtualPCInterface", "VirtualPCInterface");
Assert (virtualPC != 0);
queue = new VirtualPCRegisterQueue (100);

// Locate the packet driver and packet driver buffer vectors.
int packetDriverInt = findPacketDriverInterface ();
int packetBufferInt = findPacketBufferInterface ();
int packetReadyInt = findPacketReadyInterrupt ();
Assert (packetDriverInt != 0);
Assert (packetBufferInt != 0);
Assert (packetReadyInt != 0);
// Allocate some packet buffer space for the packet driver buffer.
unsigned short bufferSegment = allocateLowMemory (bufferSize);
Assert (bufferSegment != 0);

// Intercept the packetReady vector and start up the packet driver.
virtualPC -> interceptVector (packetReadyInt, queue);
int handle = beginAccess (packetBufferInt, bufferSegment, bufferSize);

// Print my Ethernet address.
unsigned char etherAddr [6];
getAddress (packetDriverInt, handle, (char *) etherAddr);
*StandardOutput << "My Ethernet address is ";
for (int i = 0; i <= 5; i++)
{
if (i > 0) *StandardOutput << ":";
*StandardOutput << asHex (etherAddr [i]);
}
*StandardOutput << "\n" << eor;

// Work with the packets.
processPackets (packetDriverInt, packetBufferInt);
// Shut down the packet driver.
endAccess (packetBufferInt);
virtualPC -> restoreVector (packetReadyInt);
deallocateLowMemory (bufferSegment);
}

void processPackets (int packetDriverInt, int packetBufferInt)
{
VirtualPCRegisters regs;
for (int i = 1; i <= 100; i++)
{
// Block for a packet.
queue -> dequeue (®s);
unsigned short packetSegment = regs.ds, packetOffset = regs.si;
*StandardOutput << asHex (regs.ds) << "," << asHex (regs.si) << "\n"
<< eor;

// Print the packet.
unsigned char *s = (unsigned char *) (regs.ds * 16 + regs.si);
*StandardOutput << " ";
for (int j = 1; j <= 14; j++)
*StandardOutput << asHex (*(s++)) << " ";
*StandardOutput << "\n" << eor;

// Deallocate the packet.
args.reset ();
args.set (rAX, 0x400); // "Deallocate packet" function.
args.set (rDS, packetSegment);
args.set (rSI, packetOffset); // DS:SI point to the packet.
int err = virtualPC -> executeVector (packetBufferInt, &args);
Assert (!err);
}
}

void getAddress (int packetDriverInt, int handle, char *addr)
{
// Write the Ethernet card's Ethernet address into addr, a 6-byte
// array.
args.reset ();
args.set (rAX, 0x600); // Select get_address() function.
args.set (rBX, (unsigned short) handle); // Handle number.
args.setUninitBuffer (rES, rDI, addr, 6); // ES:DI is for the result.
args.set (rCX, 6); // Expect 6-byte address.
int err = virtualPC -> executeVector (packetDriverInt, &args);
Assert (!err);
}

int beginAccess (int packetBufferInt, unsigned short bufferSegment,
int bufferSize)
{
// Tell the Ethernet hardware to start reading packets. Return
// a packet driver handler.
args.reset ();
args.set (rAX, 0x200); // "Begin access" function.
args.set (rDS, bufferSegment);
args.set (rSI, 0); // DS:SI point to the allocated buffer.
args.set (rCX, (unsigned short) bufferSize); // Size of buffer.
int err = virtualPC -> executeVector (packetBufferInt, &args);
Assert (!err);
return args.get (rAX);
}

void endAccess (int packetBufferInt)
{
args.reset ();
args.set (rAX, 0x300); // "End access" function.
int err = virtualPC -> executeVector (packetBufferInt, &args);
Assert (!err);
}

unsigned short allocateLowMemory (int size)
{
// Allocate a chunk of low memory of specified size from DOS
// and return the segment address (ie. absolute address of allocated
// memory is (return value) * 16). Return 0 if failure.
args.reset ();
args.set (rAX, 0x4800); // DOS function 0x48.
args.set (rBX, size / 16); // Number of paragraphs (16-byte) to alloc.
int err = virtualPC -> executeVector (DOSVector, &args);
if (err || args.get (rFlags) & 1) return 0; // If error, bail out.
return args.get (rAX);
}

void deallocateLowMemory (unsigned short bufferSegment)
{
// Deallocate the chunk of memory at bufferSegment that was returned
// by allocateLowMemory previously.
args.reset ();
args.set (rAX, 0x4900); // DOS function 0x49.
args.set (rES, bufferSegment);
virtualPC -> executeVector (DOSVector, &args);
}

int findPacketDriverInterface ()
{
// Search for the packet driver interface in the range INT 0x60 to
// 0x80 in the VirtualPC. Return the interrupt vector occupied by
// the interface, or return 0 if not found.
for (int i = 0x60; i < 0x80; i++)
{
unsigned short *p = (unsigned short *) (i * 4);
char *handlerAddr = (char *) (*p + *(p + 1) * 16);
if (handlerAddr == 0) continue;
handlerAddr = handlerAddr + 3;
const char packetDriverID [] = "PKT DRVR";
if (ByteCompare (handlerAddr, (char *) packetDriverID,
strlen ((char *) packetDriverID) + 1) == 0)
return i;
}
return 0;
}

int findPacketBufferInterface ()
{
// Search for the packet driver buffer interface in the range INT 0x60 to
// 0x80 in the VirtualPC. Return the interrupt vector occupied by
// the interface, or return 0 if not found.
for (int i = 0x60; i < 0x80; i++)
{
unsigned short *p = (unsigned short *) (i * 4);
char *handlerAddr = (char *) (*p + *(p + 1) * 16);
if (handlerAddr == 0) continue;
handlerAddr = handlerAddr + 3;
const char packetBufferID [] = "PDBUF INT";
if (ByteCompare (handlerAddr, (char *) packetBufferID,
strlen ((char *) packetBufferID) + 1) == 0)
return i;
}
return 0;
}

int findPacketReadyInterrupt ()
{
// Search for the packet ready interrupt in the range INT 0x60 to
// 0x80 in the VirtualPC. Return the interrupt vector or return 0 if
// not found.
for (int i = 0x60; i < 0x80; i++)
{
unsigned short *p = (unsigned short *) (i * 4);
char *handlerAddr = (char *) (*p + *(p + 1) * 16);
if (handlerAddr == 0) continue;
handlerAddr = handlerAddr + 3;
const char packetReadyID [] = "PDBUF READY";
if (ByteCompare (handlerAddr, (char *) packetReadyID,
strlen ((char *) packetReadyID) + 1) == 0)
return i;
}
return 0;
}


  3 Responses to “Category : Alternate Operating Systems - Quarterdeck DesqView, CP/M, etc
Archive   : PCCAPP.ZIP
Filename : ETHER.CC

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/