• Please review our updated Terms and Rules here

Need help with accessing packet drivers in QB...

MattHacker

New Member
Joined
Aug 1, 2008
Messages
5
According to the Packet Driver Specification (available at http://www.crynwr.com/packet_driver.html), there is no function to receive packets. Instead, when you call the access_type function, you provide a segment and offset of a subroutine (in ES:DI) that is executed every time a packet is received.

This is in contrast to Trumpet TCP, which I have been using. I got fed up with its instability, so I want to write my own TCP/IP implementation.

With Trumpet TCP, you provide the segment and offset of a buffer (which is easy in QuickBASIC: use VARSEG() and VARPTR() on a fixed-length string) as well as some other stuff, then call a function to move data into that buffer.

I'm pretty sure I'll have to put some code into a string and provide the segment and offset of that string to the packet driver in ES:DI when I call the access_type function.

This assembler program is the main thing I'm asking for help with... I'm not sure what to do or where to start, and I don't really have much (any?) x86 assembler programming experience...

If anyone is willing to help me out with this, I would appreciate it. :)

(PS: I'm not asking about the practicality of implementing a TCP/IP stack in QB or how I should really use <insert other language here> instead. I know it will be a quite a challenge and a tight fit. I'm here to ask for help with this one issue so I can get started on the rest of the stuff.)

(PSS: I'm not asking about whether I am capable of implementing a TCP/IP stack, either. I know it's tough, TCP in particular is a real pain. IIRC, Mike Brutman (mbbrutman) took two and a half years to finally get his implementation just right. Don't tell me it's hard. I already know what I'm getting into with this.)
 
Welcome to the world of interrupt driven communications.

As you have found out, you need to provide a function for the packet driver to call when a new packet arrives. The packet driver calls your new function twice:
  1. Once to get the address of a buffer to drop the bytes into
  2. Once to let you know that it did the copy to your buffer

You never know when you are going to be interrupted. Speed is critical because if one packet just arrived, more might be coming in shortly. I would have a set of buffers ready to go in a 'free list' and just hand out pointers from that list each time a buffer is requested. After a buffer is filled it gets removed from the free list and put in a 'to process' list.

Then you process the packet. When you are finally done processing, you return it to the free list.

You have to do this with proper locking mechanisms. You never know when the packet driver is going to hit you with a packet, so if you get caught managing the free list at the wrong time you will corrupt it. Make this code as small as possible and use the STI and CLI x86 commands to enable/disable interrupts while doing it.

Good luck structuring this with QB - I don't know anything about embedding a function in a string to have it called in this manner. I'm sure it can be done, it's just going to be gross. Did I mention that now would be a good time to learn C or Pascal? ;-0
 
(PSS: I'm not asking about whether I am capable of implementing a TCP/IP stack, either. I know it's tough, TCP in particular is a real pain. IIRC, Mike Brutman (mbbrutman) took two and a half years to finally get his implementation just right. Don't tell me it's hard. I already know what I'm getting into with this.)

It's not done yet. And you haven't been bitten by anything inside of it yet - have faith. :sly:
 
i'll be glad to help if you want. i'd been looking at it a bit recently myself, and you'll need to feed access_type a lot of info you already should have gotten from driver_info

you should not need any ASM code to handle this, to make a get data call it should look similar to this: (btw, you'll probably want to copy the MakeReg function from my TCPDRV routines.

pktdrvCall.ax = MakeReg(&H2, classvaluefromdriverinfo)
pktdrvCall.bx = iftypefromdriverinfo
pktdrvCall.dx = MakeReg(0, ifnumberfromdriverinfo)
pktdrvCall.ds = VARSEG(typebuffer)
pktdrvCall.si = VARPTR(typebuffer)
pktdrvCall.cx = typelen (i need to look into this, not sure what it is exactly)
pktdrvCall.es = VARSEG(receivebufferstring)
pktdrvCall.di = VARPTR(receivebufferstring)
CALL InterruptX(&H60, pktdrvCall, pktdrvReturn)

and obviously pktdrvCall and pktdrvReturn should be dimmed as Registers type like i wrote in the TCPDRV code.

i have an appointment to get to but i'm going to sit down and take a close look at it when i get back later.
 
pktdrvCall.ax = MakeReg(&H2, classvaluefromdriverinfo)
pktdrvCall.bx = iftypefromdriverinfo
pktdrvCall.dx = MakeReg(0, ifnumberfromdriverinfo)
pktdrvCall.ds = VARSEG(typebuffer)
pktdrvCall.si = VARPTR(typebuffer)
pktdrvCall.cx = typelen (i need to look into this, not sure what it is exactly)
pktdrvCall.es = VARSEG(receivebufferstring)
pktdrvCall.di = VARPTR(receivebufferstring)

CALL InterruptX(&H60, pktdrvCall, pktdrvReturn)

and obviously pktdrvCall and pktdrvReturn should be dimmed as Registers type like i wrote in the TCPDRV code.

That won't work because the packet driver expects code, not a buffer, in es:di.
 
Back
Top