changeset 81:78f2f1918398

Push the rx init, start a patch for the tx init
author Louis Opter <louis@lse.epitech.net>
date Sun, 20 May 2012 07:51:04 +0200
parents 0354cceee710
children 71f76c0f235f
files e1000_add_register_unset.patch e1000_fix_and_improve_set_up_device.patch e1000_initialize_reception.patch e1000_initialize_transmission.patch e1000_use_log_info_in_card_status.patch series
diffstat 6 files changed, 26 insertions(+), 620 deletions(-) [+]
line wrap: on
line diff
--- a/e1000_add_register_unset.patch	Sun Apr 15 02:53:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-# HG changeset patch
-# Parent eb6bb1687169662741a6bd57191b750b3bcbb6b7
-rathaxes: add the e1000::register_unset32() function
-
-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
-@@ -339,6 +339,27 @@
-         }
-     }
- 
-+    template sequence   e1000::register_unset32(e1000::Context ctx, e1000::Register reg_offset, ::number value)
-+    {
-+        chunk   LKM::prototypes()
-+        {
-+            static void rtx_e1000_register_unset32(struct rtx_e1000_ctx *, unsigned int, unsigned int);
-+        }
-+
-+        chunk   LKM::code()
-+        {
-+            static void rtx_e1000_register_unset32(struct rtx_e1000_ctx *ctx, unsigned int reg_offset, unsigned int value)
-+            {
-+                iowrite32(rtx_e1000_register_read32(ctx, reg_offset) & ~value, ctx->ioaddr + reg_offset);
-+            }
-+        }
-+
-+        chunk   ::CALL()
-+        {
-+            rtx_e1000_register_unset32(${ctx}, ${reg_offset}, ${value});
-+        }
-+    }
-+
-     template sequence   e1000::setup_interrupt_handler(Ethernet::Device ctx)
-     {
-         chunk   LKM::includes()
-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
-@@ -80,4 +80,11 @@
-         provided chunk  LKM::code();
-         provided chunk  ::CALL();
-     }
-+
-+    provided sequence   e1000::register_unset32(e1000::Context, e1000::Register, ::number)
-+    {
-+        provided chunk  LKM::prototypes();
-+        provided chunk  LKM::code();
-+        provided chunk  ::CALL();
-+    }
- }
--- a/e1000_fix_and_improve_set_up_device.patch	Sun Apr 15 02:53:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-# HG changeset patch
-# Parent 0a4c7ad60a68bfd1e797c0779bc035c20780ec9f
-Fix and improve the e1000::set_up_device function:
-
-- The LRST and PHY_RST commands were set instead of *unset* on the
-  control register;
-- Complete the initialization of the device according to the Intel
-  manuals: unset some registers, zero out the control flow registers and
-  the statistics registers.
-
-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
-@@ -58,7 +58,12 @@
-                 E1000_MDIC          = 0x00020, /* MDI Control - RW */
-                 E1000_IMS           = 0x000D0, /* Interrupt Mask Set */
-                 E1000_IMC           = 0x000D8, /* Interrupt Mask Clear */
--                E1000_ICR           = 0x000C0  /* Interrupt Cause Read - R/clr */
-+                E1000_ICR           = 0x000C0, /* Interrupt Cause Read - R/clr */
-+                E1000_FCAL          = 0x00028, /* Flow Control Address Low */
-+                E1000_FCAH          = 0x0002c, /* Flow Control Address High */
-+                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) */
-             };
-         }
- 
-@@ -446,11 +451,43 @@
-     {
-         chunk  ::CALL
-         {
-+            /*
-+             * This is documented in the Intel Gigabit Ethernet Controller
-+             * Software Developper manual.
-+             *
-+             * Since this part is actually completely device specific it should
-+             * not be written here. (but in the front-end).
-+             */
-+
-+            /*
-+             * "General Configuration" (section 14.3):
-+             *
-+             * - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection &
-+             *   negociation;
-+             * - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation;
-+             * - CTRL.PHY_RST: Unset it;
-+             * - CTRL.ILOS: Unset it (ILOS is Invert Loss Of Signal);
-+             * - CTRL.VME: Make sure it's not set to disable VLAN support;
-+             * - Set the control flow registers to 0;
-+	     * - Finally, initialize all the statistic registers from
-+	     *   E1000_CRCERRS to E1000_TSCTFC.
-+             */
-             rtx_e1000_register_set32(&${ctx}->hw_ctx, E1000_CTRL,
-                                      E1000_CMD_ASDE |
--                                     E1000_CMD_SLU  |
--                                     E1000_CMD_LRST |
--                                     E1000_CMD_PHY_RST);
-+                                     E1000_CMD_SLU);
-+            rtx_e1000_register_unset32(&${ctx}->hw_ctx, E1000_CTRL,
-+                                       E1000_CMD_LRST    |
-+                                       E1000_CMD_FRCSPD  |
-+                                       E1000_CMD_PHY_RST |
-+                                       E1000_CMD_ILOS    |
-+                                       E1000_CMD_VME);
-+            rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCAH, 0);
-+            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;
-+            for (i = 0; i != 64; ++i)
-+                rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_CRCERRS + i * 4, 0);
-         }
-     }
- 
--- a/e1000_initialize_reception.patch	Sun Apr 15 02:53:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,459 +0,0 @@
-# HG changeset patch
-# Parent d8fce7ee2b630bf8bd681fa4d66832b82c5e6de2
-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
-@@ -1,5 +1,81 @@
- with e1000, Ethernet, Socket, PCI, LKM, Log
- {
-+    template type   e1000::RxDescriptor()
-+    {
-+        chunk   LKM::includes()
-+        {
-+            typedef int ${e1000::RxDescriptor};
-+
-+            #include <linux/types.h>
-+
-+            static const ${e1000::RxDescriptor} force_rtx_e1000_rx_descriptor_decl;
-+        }
-+
-+        chunk   ::decl()
-+        {
-+            typedef struct rtx_e1000_rx_descriptor
-+            {
-+                /* actual types are in comments */
-+                unsigned long int   /* __le64 */    buff_addr;
-+                unsigned short      /* __le16 */    length;
-+                unsigned short      /* __le16 */    csum;
-+                unsigned char                       status;
-+                unsigned char                       errors;
-+                unsigned short      /* __le16 */    special;
-+            } *rtx_e1000_rx_descriptor_p;
-+        }
-+
-+        chunk   ::init()
-+        {
-+        }
-+
-+        map
-+        {
-+        }
-+    }
-+
-+    /*
-+     * Ring of e1000::RxDescriptors and their corresponding skbuffs.
-+     *
-+     * - size: total size of the ring in bytes.
-+     * - base: address of the ring (we can't use the typedef here until we get
-+     *   CNorm unstrict);
-+     * - dma_base: (physical) address of the ring where the device can access
-+     *   the different descriptors;
-+     * - skbuffs: array of the skbuffs associated with each descriptor;
-+     * - dma_skbuffs: (physical) address of each skbuff where the device can
-+     *   write the received packets;
-+     */
-+    template type   e1000::RxRing()
-+    {
-+        chunk   LKM::includes()
-+        {
-+            typedef int ${e1000::RxRing};
-+
-+            static const ${e1000::RxRing}   force_rtx_e1000_rx_ring_decl;
-+        }
-+
-+        chunk   ::decl()
-+        {
-+            struct rtx_e1000_rx_ring
-+            {
-+                unsigned int                    size;
-+                struct rtx_e1000_rx_descriptor  *base;
-+                void*   /* dma_addr_t */        dma_base;
-+                struct sk_buff                  *skbuffs[256 /* ${config.rx_ring_size} */];
-+                void*   /* dma_addr_t */        dma_skbuffs[256 /* ${config.rx_ring_size} */];
-+            };
-+        }
-+
-+        chunk   ::init()
-+        {
-+        }
-+
-+        map
-+        {
-+        }
-+    }
-+
-     template type   e1000::Context()
-     {
-         chunk   LKM::includes()
-@@ -21,9 +97,12 @@
-              */
-             typedef struct rtx_e1000_ctx
-             {
--                int                             bars;
--                unsigned char /* __iomem */     *ioaddr;
--                int                             irq;
-+                int                         bars;
-+                unsigned char /* __iomem */ *ioaddr;
-+                int                         irq;
-+
-+                /* we can't use the Rathaxes type here (#8) */
-+                struct rtx_e1000_rx_ring    rx_ring;
-             } *rtx_e1000_ctx_p;
-         }
- 
-@@ -34,6 +113,7 @@
-         map
-         {
-         }
-+
-     }
- 
-     template type   e1000::Register()
-@@ -64,6 +144,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 +215,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 */
-             };
-         }
- 
-@@ -457,15 +541,27 @@
-     {
-         chunk  ::CALL()
-         {
-+            typedef unsigned long int   dma_addr_t;
-+
-             /*
--             * This is documented in the Intel Gigabit Ethernet Controller
--             * Software Developper manual.
-+             * This part is documented in the Intel Gigabit Ethernet Controller
-+             * Software Developper manual. (You can find it in the doc/hardware
-+             * directory).
-              *
-              * Since this part is actually completely device specific it should
-              * not be written here. (but in the front-end).
-              */
- 
-             /*
-+             * shortcut hw_ctx... maybe we should directly take an
-+             * e1000::Context? (but we would need to make it point back to
-+             * the struct net_device)
-+             */
-+            typedef int       ${e1000::Context};
-+            ${e1000::Context} hw_ctx;
-+            hw_ctx = &${ctx}->hw_ctx;
-+
-+            /*
-              * "General Configuration" (section 14.3):
-              *
-              * - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection &
-@@ -478,22 +574,181 @@
-              * - Finally, initialize all the statistic registers from
-              *   E1000_CRCERRS to E1000_TSCTFC.
-              */
--            rtx_e1000_register_set32(&${ctx}->hw_ctx, E1000_CTRL,
-+
-+            rtx_e1000_register_set32(hw_ctx, E1000_CTRL,
-                                      E1000_CMD_ASDE |
-                                      E1000_CMD_SLU);
--            rtx_e1000_register_unset32(&${ctx}->hw_ctx, E1000_CTRL,
-+            rtx_e1000_register_unset32(hw_ctx, E1000_CTRL,
-                                        E1000_CMD_LRST    |
-                                        E1000_CMD_FRCSPD  |
-                                        E1000_CMD_PHY_RST |
-                                        E1000_CMD_ILOS    |
-                                        E1000_CMD_VME);
--            rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_FCAH, 0);
--            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);
-+            rtx_e1000_register_write32(hw_ctx, E1000_FCAH, 0);
-+            rtx_e1000_register_write32(hw_ctx, E1000_FCAL, 0);
-+            rtx_e1000_register_write32(hw_ctx, E1000_FCT, 0);
-+            rtx_e1000_register_write32(hw_ctx, E1000_FCTTV, 0);
-+            int i = 0; /* CNorm workaround, the init part of for isn't generated */
-+            for (i = 0; i != 64; ++i)
-+                rtx_e1000_register_write32(hw_ctx, E1000_CRCERRS + i * 4, 0);
-+
-+            {
-+                ${Log::info("setup_device: general configuration done")};
-+            }
-+
-+            /*
-+             * Receive initialization:
-+             *
-+             * 1. Program the receive address, in RAL/RAH;
-+             * 2. Initialize the Multicast Table Array;
-+             * 3. Program the interrupt mask register (done in
-+             *    e1000::activate_device_interruption);
-+             * 4. Allocate the receive descriptor ring and map it to make it
-+             *    accessible by the device.
-+             *
-+             * The ugly casts in here are caused by the lack of CNorm unstrict.
-+             */
-+
-+            /* 1. Program the receive address */
-+
-+            /* (We should use uint{32,16}_t but CNorm doesn't know them yet) */
-+            rtx_e1000_register_write32(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(hw_ctx, E1000_RAH,
-+                    *(unsigned short *)(&${ctx}->net_dev->dev_addr[4]));
-+            rtx_e1000_register_set32(hw_ctx, E1000_RAH, E1000_RAH_AV);
-+
-+            {
-+                ${Log::info("setup_device: program receieve address done")};
-+            }
-+
-+            /* 2. Initialize the MTA */
-+
-+            i = 0; /* CNorm workaround, the init part of for isn't generated */
-+            for (i = 0; i != 128; ++i)
-+                rtx_e1000_register_write32(hw_ctx, E1000_MTA + i * 4, 0);
-+
-+            {
-+                ${Log::info("setup_device: MTA init done")};
-+            }
-+
-+            /* 4. Setup the receive descriptor ring */
-+
-+            /* Allocate the descriptors */
-+            hw_ctx->rx_ring.size = ${config.rx_ring_size} * sizeof(*hw_ctx->rx_ring.base);
-+            hw_ctx->rx_ring.size = ALIGN(hw_ctx->rx_ring.size, 4096);
-+            hw_ctx->rx_ring.base = dma_alloc_coherent(
-+                    &${ctx}->pci_dev->dev,
-+                    hw_ctx->rx_ring.size,
-+                    (dma_addr_t *)&hw_ctx->rx_ring.dma_base,
-+                    GFP_KERNEL);
-+            if (!hw_ctx->rx_ring.base)
-+            {
-+                ${Log::info("cannot allocate the descriptors for the rx ring")};
-+                goto err_rx_ring_alloc;
-+            }
-+
-+            {
-+                ${Log::info("setup_device: descriptors allocated")};
-+            }
-+
-+            /*
-+             * Allocate the skbuffs, map them for DMA, and write their address
-+             * in the corresponding descriptor.
-+             */
-+            i = 0;
-+            for (i = 0; i != ${config.rx_ring_size}; ++i)
-+            {
-+                hw_ctx->rx_ring.skbuffs[i] = netdev_alloc_skb(
-+                        ${ctx}->net_dev,
-+                        ${config.rx_buffer_len});
-+                if (!hw_ctx->rx_ring.skbuffs[i])
-+                {
-+                    ${Log::info("cannot allocate a skbuff for the rx ring")};
-+                    goto err_skbuffs_alloc;
-+                }
-+                hw_ctx->rx_ring.dma_skbuffs[i] = (void *)dma_map_single(
-+                        &${ctx}->pci_dev->dev,
-+                        hw_ctx->rx_ring.skbuffs[i]->data,
-+                        ${config.rx_buffer_len},
-+                        DMA_FROM_DEVICE);
-+                /*
-+                 * Either this fails because, when compiling with gcc because
-+                 * the last argument is not of the correct type (dma_addr_t).
-+                 * Or it fails because of the lack of CNorm Unstrict.
-+                 */
-+                if (dma_mapping_error(&${ctx}->pci_dev->dev, (dma_addr_t)hw_ctx->rx_ring.dma_skbuffs[i]))
-+                {
-+                    ${Log::info("cannot dma-map a skbuff for the rx ring")};
-+                    goto err_skbuffs_map;
-+                }
-+                hw_ctx->rx_ring.base[i].buff_addr = (unsigned long int)cpu_to_le64(
-+                        hw_ctx->rx_ring.dma_skbuffs[i]);
-+            }
-+
-+            {
-+                ${Log::info("setup_device: skbuffs allocated")};
-+            }
-+
-+            /*
-+             * XXX: We can't return here since we are not in a function but in
-+             * a chunk of code (injected in a function).
-+             */
-+            goto ok;
-+
-+            /*
-+             * Likewise, always the same problem with error handling, we don't
-+             * know where we are at in the "parent context":
-+             */
-+        err_skbuffs_alloc:
-+            while (i--)
-+            {
-+                dma_unmap_single(
-+                        &${ctx}->pci_dev->dev,
-+                        (dma_addr_t)hw_ctx->rx_ring.dma_skbuffs[i],
-+                        ${config.rx_buffer_len},
-+                        DMA_FROM_DEVICE);
-+        err_skbuffs_map:
-+                dev_kfree_skb(hw_ctx->rx_ring.skbuffs[i]);
-+            }
-+
-+            dma_free_coherent(&${ctx}->pci_dev->dev, hw_ctx->rx_ring.size,
-+                    hw_ctx->rx_ring.base, (dma_addr_t)hw_ctx->rx_ring.dma_base);
-+        err_rx_ring_alloc:
-+            return -ENOMEM;
-+
-+        ok:
-+        }
-+    }
-+
-+    template sequence   e1000::free_rx_tx(Ethernet::Device ctx)
-+    {
-+        chunk   ::CALL()
-+        {
-+            typedef unsigned long int   dma_addr_t;
-+
-+            typedef int       ${e1000::Context};
-+            ${e1000::Context} hw_ctx;
-+            hw_ctx = &${ctx}->hw_ctx;
-+
-+            /* Free the rx ring: */
-             int i = 0;
--            for (i = 0; i != 64; ++i)
--                rtx_e1000_register_write32(&${ctx}->hw_ctx, E1000_CRCERRS + i * 4, 0);
-+            for (i = 0; i != ${config.rx_ring_size}; ++i)
-+            {
-+                dma_unmap_single(
-+                        &${ctx}->pci_dev->dev,
-+                        (dma_addr_t)hw_ctx->rx_ring.dma_skbuffs[i],
-+                        ${config.rx_buffer_len},
-+                        DMA_FROM_DEVICE);
-+                dev_kfree_skb(hw_ctx->rx_ring.skbuffs[i]);
-+            }
-+            dma_free_coherent(&${ctx}->pci_dev->dev, hw_ctx->rx_ring.size,
-+                    hw_ctx->rx_ring.base, (dma_addr_t)hw_ctx->rx_ring.dma_base);
-+
-         }
-     }
- 
-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,9 @@
- interface e1000 : Socket, Ethernet, PCI, LKM
- {
-     provided type   e1000::Context;
-+    provided type   e1000::RxDescriptor;
-+    provided type   e1000::RxRing;
-+
-     /*
-      * These two types should actually be registers definitions in the frontend:
-      */
-@@ -55,6 +58,11 @@
-         provided chunk  ::CALL();
-     }
- 
-+    provided sequence   e1000::free_rx_tx(Ethernet::Device dev)
-+    {
-+        provided chunk  ::CALL();
-+    }
-+
-     provided sequence   e1000::handle_interrupt(Ethernet::Device)
-     {
-         provided chunk  ::CALL();
-diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt
---- a/rathaxes/samples/e1000/ethernet.blt
-+++ b/rathaxes/samples/e1000/ethernet.blt
-@@ -64,7 +64,6 @@
-             static int  rtx_ethernet_open(struct net_device *dev)
-             {
-                 struct rtx_ethernet_dev* rtx_ether_dev = netdev_priv(dev);
--                struct rtx_e1000_ctx* ctx = &rtx_ether_dev->hw_ctx;
- 
-                 ${cast local.rtx_ether_dev as Ethernet::Device};
-                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_dev)};
-@@ -105,8 +104,7 @@
-         {
-             static int  rtx_ethernet_close(struct net_device *dev)
-             {
--                struct rtx_ethernet_dev* rtx_ether_dev =  netdev_priv(dev);
--                struct rtx_e1000_ctx* ctx = &rtx_ether_dev->hw_ctx;
-+                struct rtx_ethernet_dev* rtx_ether_dev = netdev_priv(dev);
- 
-                 ${cast local.rtx_ether_dev as Ethernet::Device};
-                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_dev)};
-diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx
---- a/rathaxes/samples/e1000/lkm.rtx
-+++ b/rathaxes/samples/e1000/lkm.rtx
-@@ -24,7 +24,17 @@
-     Ethernet::close(Ethernet::Device dev)
-     {
-         Log::info("closing the device");
-+
-+        /*
-+         * Note: some calls to release resources must be done when IRQs are
-+         * enabled (dma_free_coherent() for example). So we have to cleanup our
-+         * stuff before free_interrupt_handler().
-+         */
-+        e1000::free_rx_tx(dev);
-+        Log::info("free'ed up skbuffs");
-+
-         e1000::free_interrupt_handler(dev);
-+        Log::info("interrupt handler free'ed");
-     }
- 
-     Ethernet::interrupt_handler(Ethernet::Device dev)
-@@ -61,4 +71,11 @@
-     PCI::set_master = true;
- 
-     Ethernet::ifname = "rtx%d";
-+
-+    e1000::rx_ring_size = 256; /* Number of incoming packets we can buffer */
-+    /*
-+     * The e1000 supports seven receive buffer sizes: 256, 512, 1024, 2048,
-+     * 4096, 8192 and 16384 bytes:
-+     */
-+    e1000::rx_buffer_len = 2048;
- }
-diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt
---- a/rathaxes/samples/e1000/socket.blt
-+++ b/rathaxes/samples/e1000/socket.blt
-@@ -4,7 +4,11 @@
-     {
-         chunk LKM::includes()
-         {
-+            typedef int ${Socket::SKBuff};
-+
-             #include <linux/skbuff.h>
-+
-+            static const ${Socket::SKBuff} force_rtx_lnux_skbuf_decl;
-         }
- 
-         chunk ::decl()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e1000_initialize_transmission.patch	Sun May 20 07:51:04 2012 +0200
@@ -0,0 +1,25 @@
+# HG changeset patch
+# Parent 675aa6c230476368c195b739218a4f18c2028325
+rathaxes: initialize transmission on the e1000 sample:
+
+- This is documented in details in the sections 14.5 and 3.3 of the
+  Intel Gigabit Controller Software Developer manual.
+
+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
+@@ -731,6 +731,14 @@
+             }
+ 
+             /*
++             * Transmission initialization (section 14.5):
++             *
++             * 1. Allocate the transmit descript ring and map it to make it
++             *    accessible by the device;
++             * 2.
++             */
++
++            /*
+              * XXX: We can't return here since we are not in a function but in
+              * a chunk of code (injected in a function).
+              */
--- a/e1000_use_log_info_in_card_status.patch	Sun Apr 15 02:53:38 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-# HG changeset patch
-# Parent cc24d4f527d5ebe52a1880e393717c30b39ab0e3
-rathaxes: use  in e1000::print_status()
-
-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
-@@ -249,7 +249,13 @@
-             static void rtx_e1000_print_status(struct rtx_e1000_ctx *ctx)
-             {
-                 unsigned int status = rtx_e1000_register_read32(ctx, E1000_STATUS);
--                pr_info("card status: \n");
-+                { /* < workaround issue #10 */
-+                    ${Log::info("card status:")};
-+                }
-+                /*
-+                 * we can't use Log::info below because it just accept a string
-+                 * (as opposed to a format string with its parameters).
-+                 */
-                 pr_info("\tRegister value: 0x%x\n", status);
-                 pr_info("\tMode: %s\n", (status & 1) ? "Full": "Half");
-                 pr_info("\tLink: %s\n", (status & 2) ? "Up" : "Down");
-@@ -469,8 +475,8 @@
-              * - CTRL.ILOS: Unset it (ILOS is Invert Loss Of Signal);
-              * - CTRL.VME: Make sure it's not set to disable VLAN support;
-              * - Set the control flow registers to 0;
--	     * - Finally, initialize all the statistic registers from
--	     *   E1000_CRCERRS to E1000_TSCTFC.
-+             * - Finally, initialize all the statistic registers from
-+             *   E1000_CRCERRS to E1000_TSCTFC.
-              */
-             rtx_e1000_register_set32(&${ctx}->hw_ctx, E1000_CTRL,
-                                      E1000_CMD_ASDE |
--- a/series	Sun Apr 15 02:53:38 2012 +0200
+++ b/series	Sun May 20 07:51:04 2012 +0200
@@ -1,4 +1,1 @@
-e1000_add_register_unset.patch
-e1000_fix_and_improve_set_up_device.patch
-e1000_use_log_info_in_card_status.patch
-e1000_initialize_reception.patch
+e1000_initialize_transmission.patch