Repository: vinc/moros (language: rust)

Issue:
Network card error in VirtualBox
A successfully transmitted `DHCPDISCOVER` message in QEMU looks like this:

```
> dhcp
DHCP Discover transmitted
------------------------------------------------------------------
[11.543242] NET PCNET Transmitting:
CSR0: 0000000110110011
00000000: FFFF FFFF FFFF 5254 0012 3456 0800 4500 ......RT..4V..E.
00000010: 011D 0000 4000 4011 39D1 0000 0000 FFFF ....@.@.9.......
00000020: FFFF 0044 0043 0109 B92C 0101 0600 0000 ...D.C. .,......
00000030: 0002 0000 0001 0000 0000 0000 0000 0000 ................
00000040: 0000 0000 0000 5254 0012 3456 0000 0000 ......RT..4V....
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000A0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000B0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000C0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000D0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000E0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000F0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000110: 0000 0000 0000 6382 5363 3501 013D 0701 ......c.Sc5..=..
00000120: 5254 0012 3456 3902 0384                RT..4V9...
CSR0: 0000011110110011
```

And it will look the same in a virtual machine configured with a PCnet-PCI II card in VirtualBox, although with a different MAC address, except the value of `CSR0` is not the same after the transmission:

```
CSR0: 1010001110110011
```

Bit 13 corresponds to `CERR` with the following meaning:

> Collision Error indicates that the collision inputs to the AUI port failed to activate within 20 network bit times after the chip terminated transmission (SQE Test). This feature is a transceiver test feature. In 10BASE-T mode, CERR will be set after a transmission if the T-MAU is in link fail state. CERR assertion will not result in an interrupt being generated. CERR assertion will set the ERR


Discussion / hints:
VirtualBox have the following error in the logs:
```
00:00:21.361916 PCnet#0: pcnetAsyncTransmit: illegal 4kb frame -> signalling error
```
See https://www.virtualbox.org/svn/vbox/trunk/src/VBox/Devices/Network/DevPCNet.cpp

Fix patch:
diff --git a/src/kernel/net/pcnet.rs b/src/kernel/net/pcnet.rs
index c8dbdbdf..fff23760 100644
--- a/src/kernel/net/pcnet.rs
+++ b/src/kernel/net/pcnet.rs
@@ -179,7 +179,7 @@ impl PCNET {
         des[DE_LEN * i + 3] = addr[3];
 
         // Set buffer byte count (0..12 BCNT + 12..16 ONES)
-        let bcnt = ((((MTU as u16).reverse_bits() + 1) & 0x0FFF) | 0xF000).to_le_bytes();
+        let bcnt = (0xF000 | (0x0FFF & (1 + !(MTU as u16)))).to_le_bytes();
         des[DE_LEN * i + 4] = bcnt[0];
         des[DE_LEN * i + 5] = bcnt[1];
 
@@ -413,7 +413,7 @@ impl phy::TxToken for TxToken {
             self.device.tx_des[tx_id * DE_LEN + 7].set_bit(DE_ENP, true); // Set end of packet
 
             // Set buffer byte count (0..12 BCNT + 12..16 ONES)
-            let bcnt = ((((len as u16).reverse_bits() + 1) & 0x0FFF) | 0xF000).to_le_bytes();
+            let bcnt = (0xF000 | (0x0FFF & (1 + !(len as u16)))).to_le_bytes();
             self.device.tx_des[tx_id * DE_LEN + 4] = bcnt[0];
             self.device.tx_des[tx_id * DE_LEN + 5] = bcnt[1];
 


Test patch: