# HG changeset patch
# Parent 40e5b7402e64e301b898fa4da1056a5348522fbb
rathaxes: initialize reception on the e1000 sample:

- This is documented in details in the sections 14.4 and 3.2 of the
  Intel Gigabit Controller Software Developer manual;
- "Address filtering" is set up, address filters just tell the hardware
  which packets they should accept (unicast/multicast/vlan/promisc), we
  simply configure the hardware to accept packet for its own mac
  address (receive address);
- It involves setting up a ring of receive descriptors (their format is
  documented in section 3.2.3) and an internal data structure to keep
  track of the ring;
- Each descriptor of the ring correspond to an skbuff (skbuff are
  allocated individually).

diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt
--- a/rathaxes/samples/e1000/e1000.blt
+++ b/rathaxes/samples/e1000/e1000.blt
@@ -36,6 +36,25 @@
         }
     }
 
+    template type   e1000::RingRx()
+    {
+        chunk   LKM::includes()
+        {
+        }
+
+        chunk   ::decl()
+        {
+        }
+
+        chunk   ::init()
+        {
+        }
+
+        map
+        {
+        }
+    }
+
     template type   e1000::Register()
     {
         chunk   LKM::includes()
@@ -64,6 +83,9 @@
                 E1000_FCT           = 0x00030, /* Flow Control Type */
                 E1000_FCTTV         = 0x00170, /* Flow Control Transmit Timer Value */
                 E1000_CRCERRS       = 0x04000, /* CRC Error Count (base address of the statistic register spaces) */
+                E1000_RAL           = 0x05400, /* Receive Address Low */
+                E1000_RAH           = 0x05404, /* Receive Address High */
+                E1000_MTA           = 0x05200, /* Multicast Table Array */
             };
         }
 
@@ -132,7 +154,8 @@
                 E1000_INTR_RXDMT0               = 0x00000010, /* rx desc min. threshold (0) */
                 E1000_INTR_RXO                  = 0x00000040, /* rx overrun */
                 E1000_INTR_RXT0                 = 0x00000080, /* rx timer intr (ring 0) */
-                E1000_INTR_MDAC                 = 0x00000200  /* MDIO access complete */
+                E1000_INTR_MDAC                 = 0x00000200, /* MDIO access complete */
+                E1000_RAH_AV                    = (1 << 31),  /* Set the MAC Address as Valid */
             };
         }
 
@@ -491,9 +514,32 @@
             rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCAL, 0);
             rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCT, 0);
             rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCTTV, 0);
-            int i = 0;
+            int i = 0; /* CNorm workaround, the init part of for isn't generated */
             for (i = 0; i != 64; ++i)
                 rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_CRCERRS + i * 4, 0);
+
+            /*
+             * Receive initialization
+             *
+             * - Program the receive address, in RAL/RAH;
+             * - Initialize the Multicast Table Array;
+             * - Program the interrupt mask register (done in
+             *   e1000::activate_device_interruption);
+             *
+             * (We should use uint{32,16}_t but CNorm doesn't know them yet)
+             */
+            rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_RAL,
+                    *(unsigned int *)(${ctx}->net_dev->dev_addr));
+            /*
+             * The 16 upper bits of RAH also store the AS bits (which should be
+             * 0) and the AV bit (should be 1 to set the address as valid).
+             */
+            rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_RAH,
+                    *(unsigned short *)(&${ctx}->net_dev->dev_addr[4]));
+            rtx_e1000_register_set32(&${ctx}->hw_ctx, E1000_RAH, E1000_RAH_AV);
+            i = 0; /* CNorm workaround, the init part of for isn't generated */
+            for (i = 0; i != 128; ++i)
+                rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_MTA + i * 4, 0);
         }
     }
 
diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti
--- a/rathaxes/samples/e1000/e1000.rti
+++ b/rathaxes/samples/e1000/e1000.rti
@@ -1,6 +1,8 @@
 interface e1000 : Socket, Ethernet, PCI, LKM
 {
     provided type   e1000::Context;
+    provided type   e1000::RingRx;
+
     /*
      * These two types should actually be registers definitions in the frontend:
      */
