Writing network drivers for KolibriOS: Difference between revisions
(Fixes for <asm> tags - replaced with <syntaxhighlight>) |
|||
(2 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
= Intro = | |||
So, you want to write a new network driver for KolibriOS ?<br /> | So, you want to write a new network driver for KolibriOS ?<br /> | ||
Line 12: | Line 12: | ||
* A program can communicate directly with the driver, using system function 68/17 | * A program can communicate directly with the driver, using system function 68/17 | ||
= IOCTL input = | |||
Here is a list of opcodes the network drivers should accept trhough the IOCTL structure: | Here is a list of opcodes the network drivers should accept trhough the IOCTL structure: | ||
Line 22: | Line 22: | ||
= the HOOK procedure = | |||
This is a part of the service proc. | This is a part of the service proc. | ||
Line 29: | Line 29: | ||
IN: (ISA) | IN: (ISA) | ||
<asm> | <syntaxhighlight lang="asm"> | ||
type db 0 ; isa | type db 0 ; isa | ||
io_addr dw ? | io_addr dw ? | ||
irq_line db ? | irq_line db ? | ||
</ | </syntaxhighlight> | ||
IN: (PCI) | IN: (PCI) | ||
<asm> | <syntaxhighlight lang="asm"> | ||
type db 1 ; pci | type db 1 ; pci | ||
pci_bus db ? | pci_bus db ? | ||
pci_dev db ? | pci_dev db ? | ||
</ | </syntaxhighlight> | ||
The driver should do the following: | The driver should do the following: | ||
Line 54: | Line 54: | ||
Then it should return the driver number, or -1 on error, in eax | Then it should return the driver number, or -1 on error, in eax | ||
= The device stucture = | |||
This structure contains all information about the device the driver has. | This structure contains all information about the device the driver has. | ||
Line 62: | Line 62: | ||
The top of the structure must always look like this: (Since it is shared by the driver and the kernel) | The top of the structure must always look like this: (Since it is shared by the driver and the kernel) | ||
<asm> | <syntaxhighlight lang="asm"> | ||
NET_DEVICE: | NET_DEVICE: | ||
.type dd ? ; Type field (ethernet/slip/...) | .type dd ? ; Type field (ethernet/slip/...) | ||
Line 78: | Line 78: | ||
.end: | .end: | ||
</ | </syntaxhighlight> | ||
This is appended by a Type-specific structure, for ethernet this will be: | This is appended by a Type-specific structure, for ethernet this will be: | ||
<asm> | <syntaxhighlight lang="asm"> | ||
.set_mode dd ? | .set_mode dd ? | ||
.get_mode dd ? | .get_mode dd ? | ||
Line 90: | Line 90: | ||
.mode dd ? | .mode dd ? | ||
.mac dp ? | .mac dp ? | ||
</ | </syntaxhighlight> | ||
These structures are defined in netdrv.inc | These structures are defined in netdrv.inc | ||
Line 96: | Line 96: | ||
The place after these two common structs is to be used by the driver, to store store information about the device. | The place after these two common structs is to be used by the driver, to store store information about the device. | ||
= receiving mechanism = | |||
When a packet is received by the driver, the driver copies it into a buffer allocated using 'KernelAlloc'.<br> | When a packet is received by the driver, the driver copies it into a buffer allocated using 'KernelAlloc'.<br> | ||
Line 105: | Line 105: | ||
This kernel function will return with the 2 dwords removed from the stack. | This kernel function will return with the 2 dwords removed from the stack. | ||
= sending mechanism = | |||
When the kernel needs to send a packet, it simple looks up the appropriate driver in it's driver table.<br> | When the kernel needs to send a packet, it simple looks up the appropriate driver in it's driver table.<br> | ||
In the table it will find the pointer to the device structure, so the | In the table it will find the pointer to the device structure, so the kernel can directly call the transmit function listed in the structure. | ||
The kernel will, similary to the driver, when receiving a packet, push the size of packet, and pointer to packet, onto the stack. | The kernel will, similary to the driver, when receiving a packet, push the size of packet, and pointer to packet, onto the stack. |
Latest revision as of 12:42, 22 April 2012
Intro
So, you want to write a new network driver for KolibriOS ?
Or you are just curious about how they work?
Well, since a driver for an ethernet, pci card, such as the rtl8139, actually isnt that hard to understand,
I advice you to read the code of a driver and try to understand it.
Here are some facts, summed op in no-particular order:
- Drivers are designed to handle more then one devices at once.
- All device specific data is stored in a structure called the 'device structure'.
- Network drivers are loaded by a program (NetCfg).
- A program can communicate directly with the driver, using system function 68/17
IOCTL input
Here is a list of opcodes the network drivers should accept trhough the IOCTL structure:
- 0 - Getversion
standard for all drivers, not only network drivers
- 1 - Hook
Attach driver to a device
the HOOK procedure
This is a part of the service proc.
The application calling the hook procedure should give informationa bout the device with one of these structures:
IN: (ISA)
type db 0 ; isa
io_addr dw ?
irq_line db ?
IN: (PCI)
type db 1 ; pci
pci_bus db ?
pci_dev db ?
The driver should do the following:
- check if device is already listed in the drivers list
- allocate a device structure
- fill in io num, irq, device type, pointers to network procedures
- allocate buffers needed for the driver
- probe the device
- reset the device
- register device to kernel using NetRegDev
Then it should return the driver number, or -1 on error, in eax
The device stucture
This structure contains all information about the device the driver has. It is also used to communicate with kernel. It hold the MTU, driver functions to send/reset/.. the mac address,...
The top of the structure must always look like this: (Since it is shared by the driver and the kernel)
NET_DEVICE:
.type dd ? ; Type field (ethernet/slip/...)
.mtu dd ? ; Maximal Transmission Unit (in bytes)
.name dd ? ; Ptr to 0 terminated string
.unload dd ? ; Ptrs to driver functions
.reset dd ? ;
.transmit dd ? ;
.bytes_tx dq ? ; Statistics, updated by the driver
.bytes_rx dq ? ;
.packets_tx dd ? ;
.packets_rx dd ? ;
.end:
This is appended by a Type-specific structure, for ethernet this will be:
.set_mode dd ?
.get_mode dd ?
.set_MAC dd ?
.get_MAC dd ?
.mode dd ?
.mac dp ?
These structures are defined in netdrv.inc
The place after these two common structs is to be used by the driver, to store store information about the device.
receiving mechanism
When a packet is received by the driver, the driver copies it into a buffer allocated using 'KernelAlloc'.
It then pushes a return address on the stack, where kernel should jump to when done handling the packet.
This is followed bye the pushing of the buffer size and the buffer pointer (both are dwords, and must be pushed in this particular order)
Then the driver jumps to 'EthReceiver' (or another procedure for another network device type).
This kernel function will return with the 2 dwords removed from the stack.
sending mechanism
When the kernel needs to send a packet, it simple looks up the appropriate driver in it's driver table.
In the table it will find the pointer to the device structure, so the kernel can directly call the transmit function listed in the structure.
The kernel will, similary to the driver, when receiving a packet, push the size of packet, and pointer to packet, onto the stack. But not in the same order, it first pushes the dwords and then does a call. (so ptr will be at [esp+4] and size at [esp+8])