changeset 48:7b377e31fea3

Finish the patch the e1000 LKM
author Louis Opter <louis@lse.epitech.net>
date Fri, 13 Jan 2012 13:54:37 +0100
parents cf7d541b9331
children 0c55f24c6b3d
files rathaxes_add_lkm_ethernet_sample.patch series
diffstat 2 files changed, 0 insertions(+), 1269 deletions(-) [+]
line wrap: on
line diff
--- a/rathaxes_add_lkm_ethernet_sample.patch	Fri Jan 13 11:59:42 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1268 +0,0 @@
-# HG changeset patch
-# User Thomas Sanchez <thomas.sanchz@gmail.com>, Louis Opter <louis@lse.epita.fr>
-# Parent 3a7169517431da7a5a9a3c411ff95927c55f214f
-rathaxes: add the beginning of a Linux Intel e1000 network card driver
-
-- With working LKM/PCI/Ethernet parts;
-- Some interruption handling POC;
-- Directly compiles to a .ko object.
-
-diff --git a/maintainers/CMakeScripts/Templates/MakefileLKM.in b/maintainers/CMakeScripts/Templates/MakefileLKM.in
---- a/maintainers/CMakeScripts/Templates/MakefileLKM.in
-+++ b/maintainers/CMakeScripts/Templates/MakefileLKM.in
-@@ -1,5 +1,9 @@
--KDIR	= /lib/modules/$(shell uname -r)/build
--obj-m	:= @LKM_OBJECTS@
-+# Disable this "coding-style" warning (seriously, you have to compile with
-+# -pedantic to get it...)
-+EXTRA_CFLAGS	= -Wno-declaration-after-statement
-+
-+KDIR		= /lib/modules/$(shell uname -r)/build
-+obj-m		:= @LKM_OBJECTS@
- 
- all:
- 	$(MAKE) -C $(KDIR) SUBDIRS=$(shell pwd) modules
-diff --git a/maintainers/CMakeScripts/UseRathaxes.cmake b/maintainers/CMakeScripts/UseRathaxes.cmake
---- a/maintainers/CMakeScripts/UseRathaxes.cmake
-+++ b/maintainers/CMakeScripts/UseRathaxes.cmake
-@@ -193,6 +193,8 @@
- 
-         SET(KERNEL_OBJECT_NAME "${RATHAXES_SOURCE}_${SYSTEM}.ko")
-         ADD_CUSTOM_COMMAND(OUTPUT "${KERNEL_OBJECT_NAME}"
-+                           # …
-+                           COMMAND "sed" "-i" "/TARTE/ d" "${RATHAXES_SOURCE}_${SYSTEM}.c"
-                            # The linux Makefile to build kernel module is quite
-                            # picky about file location and its own name. Let's
-                            # copy our source side by side with the Makefile:
-diff --git a/rathaxes/samples/CMakeLists.txt b/rathaxes/samples/CMakeLists.txt
---- a/rathaxes/samples/CMakeLists.txt
-+++ b/rathaxes/samples/CMakeLists.txt
-@@ -1,2 +1,3 @@
- ADD_SUBDIRECTORY(helloworld)
- ADD_SUBDIRECTORY(syntax)
-+ADD_SUBDIRECTORY(e1000)
-diff --git a/rathaxes/samples/e1000/CMakeLists.txt b/rathaxes/samples/e1000/CMakeLists.txt
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/CMakeLists.txt
-@@ -0,0 +1,7 @@
-+ADD_RATHAXES_SOURCES(e1000_src lkm.rtx
-+                     RTI log.rti lkm.rti pci.rti socket.rti ethernet.rti e1000.rti
-+                     BLT log.blt lkm.blt pci.blt socket.blt ethernet.blt e1000.blt)
-+
-+# We can't name lkm since it's already used as the target name to generate the
-+# source (with ADD_RATHAXES_SOURCES).
-+ADD_RATHAXES_LKM(e1000 e1000_src)
-diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/e1000.blt
-@@ -0,0 +1,435 @@
-+with e1000, Ethernet, Socket, PCI, LKM, Log
-+{
-+    template type   e1000::Context()
-+    {
-+        chunk   LKM::includes()
-+        {
-+            /*
-+             * Force the generation of the structure in the "headers" part, we
-+             * have to do this since we do not use the structure in this blt
-+             * (we hacked a bit and used it in ethernet.blt directly).
-+             */
-+            typedef int ${e1000::Context}; /* CNorm __std__ workaround */
-+            static const ${e1000::Context} force_struct_rtx_10000_ctx_decl;
-+        }
-+
-+        chunk   ::decl()
-+        {
-+            struct rtx_e1000_ctx
-+            {
-+                int                             bars;
-+                unsigned char /* __iomem */     *ioaddr;
-+                int                             irq;
-+            };
-+        }
-+
-+        chunk   ::init(bars, ioaddr)
-+        {
-+            ${self}.bars = ${bars};
-+            ${self}.ioaddr = ${ioaddr};
-+        }
-+
-+        map
-+        {
-+        }
-+    }
-+
-+    template type   e1000::Register()
-+    {
-+        chunk   LKM::includes()
-+        {
-+            typedef int ${e1000::Register};
-+            static const ${e1000::Register}  force_enum_rtx_e1000_registers_decl;
-+        }
-+
-+        chunk   ::decl()
-+        {
-+            enum rtx_e1000_registers
-+            {
-+                E1000_CTRL          = 0x00000, /* Device Control - RW */
-+                E1000_CTRL_DUP      = 0x00004, /* Device Control Duplicate (Shadow) - RW */
-+                E1000_STATUS        = 0x00008, /* Device Status - RO */
-+                E1000_EEPROM_FLASH  = 0x00010, /* EEPROM/Flash Control - RW */
-+                E1000_EEPROM_READ   = 0x00014, /* EEPROM Read - RW */
-+                E1000_CTRL_EXT      = 0x00018, /* Extended Device Control - RW */
-+                E1000_FLA           = 0x0001C, /* Flash Access - RW */
-+                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 */
-+            };
-+        }
-+
-+        chunk   ::init(value)
-+        {
-+            ${self} = ${value};
-+        }
-+
-+        map
-+        {
-+        }
-+    }
-+
-+    template type   e1000::Commands()
-+    {
-+        chunk   LKM::includes()
-+        {
-+            typedef int ${e1000::Commands};
-+            static const ${e1000::Commands} force_enum_rtx_e1000_commands_decls;
-+        }
-+
-+        chunk   ::decl()
-+        {
-+            enum rtx_e1000_commands
-+            {
-+                E1000_CMD_FD                    = 0x00000001, /* Full duplex.0=half; 1=full */
-+                E1000_CMD_BEM                   = 0x00000002, /* Endian Mode.0=little,1=big */
-+                E1000_CMD_PRIOR                 = 0x00000004, /* Priority on PCI. 0=rx,1=fair */
-+                E1000_CMD_GIO_MASTER_DISABLE    = 0x00000004, /* Blocks new Master requests */
-+                E1000_CMD_LRST                  = 0x00000008, /* Link reset. 0=normal,1=reset */
-+                E1000_CMD_TME                   = 0x00000010, /* Test mode. 0=normal,1=test */
-+                E1000_CMD_SLE                   = 0x00000020, /* Serial Link on 0=dis,1=en */
-+                E1000_CMD_ASDE                  = 0x00000020, /* Auto-speed detect enable */
-+                E1000_CMD_SLU                   = 0x00000040, /* Set link up (Force Link) */
-+                E1000_CMD_ILOS                  = 0x00000080, /* Invert Loss-Of Signal */
-+                E1000_CMD_SPD_SEL               = 0x00000300, /* Speed Select Mask */
-+                E1000_CMD_SPD_10                = 0x00000000, /* Force 10Mb */
-+                E1000_CMD_SPD_100               = 0x00000100, /* Force 100Mb */
-+                E1000_CMD_SPD_1000              = 0x00000200, /* Force 1Gb */
-+                E1000_CMD_BEM32                 = 0x00000400, /* Big Endian 32 mode */
-+                E1000_CMD_FRCSPD                = 0x00000800, /* Force Speed */
-+                E1000_CMD_FRCDPX                = 0x00001000, /* Force Duplex */
-+                E1000_CMD_D_UD_EN               = 0x00002000, /* Dock/Undock enable */
-+                E1000_CMD_D_UD_POLARITY         = 0x00004000, /* Defined polarity of Dock/Undock indication in SDP[0] */
-+                E1000_CMD_FORCE_PHY_RESET       = 0x00008000, /* Reset both PHY ports, through PHYRST_N pin */
-+                E1000_CMD_EXT_LINK_EN           = 0x00010000, /* enable link status from external LINK_0 and LINK_1 pins */
-+                E1000_CMD_SWDPIN0               = 0x00040000, /* SWDPIN 0 value */
-+                E1000_CMD_SWDPIN1               = 0x00080000, /* SWDPIN 1 value */
-+                E1000_CMD_SWDPIN2               = 0x00100000, /* SWDPIN 2 value */
-+                E1000_CMD_SWDPIN3               = 0x00200000, /* SWDPIN 3 value */
-+                E1000_CMD_SWDPIO0               = 0x00400000, /* SWDPIN 0 Input or output */
-+                E1000_CMD_SWDPIO1               = 0x00800000, /* SWDPIN 1 input or output */
-+                E1000_CMD_SWDPIO2               = 0x01000000, /* SWDPIN 2 input or output */
-+                E1000_CMD_SWDPIO3               = 0x02000000, /* SWDPIN 3 input or output */
-+                E1000_CMD_RST                   = 0x04000000, /* Global reset */
-+                E1000_CMD_RFCE                  = 0x08000000, /* Receive Flow Control enable */
-+                E1000_CMD_TFCE                  = 0x10000000, /* Transmit flow control enable */
-+                E1000_CMD_RTE                   = 0x20000000, /* Routing tag enable */
-+                E1000_CMD_VME                   = 0x40000000, /* IEEE VLAN mode enable */
-+                E1000_CMD_PHY_RST               = 0x80000000, /* PHY Reset */
-+                E1000_CMD_SW2FW_INT             = 0x02000000, /* Initiate an interrupt to manageability engine */
-+                E1000_INTR_TXDW                 = 0x00000001, /* Transmit desc written back */
-+                E1000_INTR_TXQE                 = 0x00000002, /* Transmit Queue empty */
-+                E1000_INTR_LSC                  = 0x00000004, /* Link Status Change */
-+                E1000_INTR_RXSEQ                = 0x00000008, /* rx sequence error */
-+                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 */
-+            };
-+        }
-+
-+        map
-+        {
-+        }
-+    }
-+
-+    template sequence   e1000::create_device()
-+    {
-+        chunk Ethernet::create_device()
-+        {
-+            rtx_ether_ctx->hw_ctx.irq = pdev->irq;
-+            rtx_ether_ctx->hw_ctx.bars = pci_select_bars(pdev, IORESOURCE_MEM);
-+            if (pci_enable_device_mem(pdev))
-+            {
-+                ${Log::info("e1000::create: pci_enable_device_mem failed")};
-+            }
-+
-+            if (pci_request_selected_regions(pdev, rtx_ether_ctx->hw_ctx.bars, ${config.name}))
-+            {
-+                ${Log::info("e1000::create: pci_request_selected_regions failed")};
-+            }
-+
-+            if (${config.set_master})
-+            {
-+                pci_set_master(pdev);
-+            }
-+
-+            /* 0 here is for BAR_0: */
-+            rtx_ether_ctx->hw_ctx.ioaddr = pci_ioremap_bar(pdev, 0);
-+            if (!rtx_ether_ctx->hw_ctx.ioaddr)
-+            {
-+                ${Log::info("e1000::create: pci_ioremap_bar failed")};
-+            }
-+
-+            /* Reset the card */
-+            rtx_e1000_register_write32(&rtx_ether_ctx->hw_ctx, E1000_CTRL, E1000_CMD_RST);
-+            udelay(10);
-+
-+            /* Now we can load its mac address */
-+            int i = 0;
-+            for (i = 0 /* < this is not generated! */; i < 3; ++i)
-+            {
-+                rtx_e1000_register_write32(&rtx_ether_ctx->hw_ctx, E1000_EEPROM_READ, (i << 8) | 1);
-+
-+                int value;
-+                /* Should be a do { } while(); but the compiler doesn't do { } while(); yet. */
-+                value = rtx_e1000_register_read32(&rtx_ether_ctx->hw_ctx, E1000_EEPROM_READ);
-+                while ((value & (1 << 4)) == 0)
-+                    value = rtx_e1000_register_read32(&rtx_ether_ctx->hw_ctx, E1000_EEPROM_READ);
-+                value >>= 16;
-+
-+                rtx_ether_ctx->net_dev->dev_addr[i * 2] = value & 0xff;
-+                rtx_ether_ctx->net_dev->dev_addr[i * 2 + 1] = (value >> 8) & 0xff;
-+            }
-+
-+            memcpy(rtx_ether_ctx->net_dev->perm_addr,
-+                   rtx_ether_ctx->net_dev->dev_addr,
-+                   rtx_ether_ctx->net_dev->addr_len);
-+
-+            { /* < mais lol. */
-+                ${Log::info("e1000::create: mac address loaded from the EEPROM")};
-+            }
-+        }
-+
-+        chunk ::CALL
-+        {
-+        }
-+    }
-+
-+    template sequence   e1000::destroy_device()
-+    {
-+        chunk   Ethernet::destroy_device
-+        {
-+            /*
-+             * Here, we should have some checks to avoid to free resources that
-+             * haven't been allocated. (e.g: in case of previous errors).
-+             */
-+            struct rtx_ethernet_dev* rtx_ether_ctx = netdev_priv(net_dev);
-+            iounmap(rtx_ether_ctx->hw_ctx.ioaddr);
-+            pci_release_selected_regions(pdev, rtx_ether_ctx->hw_ctx.bars);
-+        }
-+
-+        chunk   ::CALL
-+        {
-+        }
-+    }
-+
-+    template sequence   e1000::print_status()
-+    {
-+        chunk   LKM::prototypes()
-+        {
-+            static void rtx_e1000_print_status(struct rtx_e1000_ctx *);
-+        }
-+
-+        chunk   LKM::code()
-+        {
-+            static void rtx_e1000_print_status(struct rtx_e1000_ctx *ctx)
-+            {
-+                unsigned int status = rtx_e1000_register_read32(ctx, E1000_STATUS);
-+                pr_info("rtx_e1000 status: \n");
-+                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");
-+                pr_info("\tTransmission: %s\n", (status & 4) ? "Paused" : "Ok");
-+                pr_info("\tInterface: %s\n", (status & 3) == 3 ? "Up" : "Down");
-+            }
-+        }
-+
-+        chunk   ::CALL
-+        {
-+        }
-+    }
-+
-+    /*
-+     * We should have been able to do something along those lines, but
-+     * it didn't work so we made the call manually.
-+     *
-+     * Ideally:
-+     * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, E1000_STATUS)};
-+     *
-+     * Ideally2, not sure about the syntax on the register parameter:
-+     * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, ${e1000::Register.E1000_STATUS})};
-+     *
-+     * "Acceptable":
-+     * typedef int ${e1000::Register}; // cnorm __std__ workaround
-+     * ${e1000::Register} reg_status;
-+     * ${e1000.init(E1000_STATUS); // didn't work, so we used the next line
-+     * reg_status = E1000_STATUS;
-+     * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, reg_status)};
-+     */
-+    template sequence   e1000::register_read32(e1000::Context ctx, e1000::Register reg_offset)
-+    {
-+        chunk   LKM::prototypes()
-+        {
-+            static unsigned int    rtx_e1000_register_read32(struct rtx_e1000_ctx *, unsigned int);
-+        }
-+
-+        chunk   LKM::code()
-+        {
-+            static unsigned int    rtx_e1000_register_read32(struct rtx_e1000_ctx *ctx, unsigned int reg_offset)
-+            {
-+                return ioread32(ctx->ioaddr + reg_offset);
-+            }
-+        }
-+
-+        chunk   ::CALL()
-+        {
-+            rtx_e1000_register_read32(&${ctx}, ${reg_offset});
-+        }
-+    }
-+
-+    template sequence   e1000::register_write32(e1000::Context ctx, e1000::Register reg_offset, ::number value)
-+    {
-+        chunk   LKM::prototypes()
-+        {
-+            static void rtx_e1000_register_write32(struct rtx_e1000_ctx *, unsigned int, unsigned int);
-+        }
-+
-+        chunk   LKM::code()
-+        {
-+            static void rtx_e1000_register_write32(struct rtx_e1000_ctx *ctx, unsigned int reg_offset, unsigned int value)
-+            {
-+                iowrite32(value, ctx->ioaddr + reg_offset);
-+            }
-+        }
-+
-+        chunk   ::CALL()
-+        {
-+            rtx_e1000_register_write32(&${ctx}, ${reg_offset});
-+        }
-+    }
-+
-+    template sequence   e1000::register_set32(e1000::Context ctx, e1000::Register reg_offset, ::number value)
-+    {
-+        chunk   LKM::prototypes()
-+        {
-+            static void rtx_e1000_register_set32(struct rtx_e1000_ctx *, unsigned int, unsigned int);
-+        }
-+
-+        chunk   LKM::code()
-+        {
-+            static void rtx_e1000_register_set32(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()
-+        {
-+        }
-+    }
-+
-+    template sequence   e1000::setup_interrupt_handler()
-+    {
-+        chunk   LKM::includes()
-+        {
-+            #include <linux/interrupt.h>
-+        }
-+        chunk   LKM::prototypes()
-+        {
-+            static int e1000_setup_interrupt_handler(struct rtx_ethernet_dev *);
-+        }
-+
-+        chunk   LKM::code()
-+        {
-+            static int e1000_setup_interrupt_handler(struct rtx_ethernet_dev *ethernet_ctx)
-+            {
-+                int error;
-+
-+                error = request_irq(ethernet_ctx->hw_ctx.irq,
-+                        rtx_ethernet_interrupt_handler,
-+                        IRQF_SHARED,
-+                        ${config.name},
-+                        ethernet_ctx);
-+
-+                if (error)
-+                {
-+                    ${Log::info("Cannot register the interruption")};
-+                }
-+
-+                return error;
-+            }
-+        }
-+
-+        chunk   ::CALL()
-+        {
-+            // this is an hack for the scope
-+            (void)1;
-+            {
-+                int error;
-+                error = e1000_setup_interrupt_handler(rtx_ether_dev);
-+                if (error)
-+                {
-+                    return error;
-+                }
-+            }
-+        }
-+    }
-+
-+    template sequence   e1000::free_interrupt_handler()
-+    {
-+        chunk   LKM::prototypes()
-+        {
-+            static void e1000_free_interrupt_handler(struct rtx_ethernet_dev *ethernet_ctx);
-+        }
-+
-+        chunk LKM::code()
-+        {
-+            static void e1000_free_interrupt_handler(struct rtx_ethernet_dev *ethernet_ctx)
-+            {
-+
-+                free_irq(ethernet_ctx->hw_ctx.irq, ethernet_ctx);
-+            }
-+        }
-+
-+        chunk ::CALL()
-+        {
-+            e1000_free_interrupt_handler(rtx_ether_dev);
-+        }
-+    }
-+
-+    template sequence   e1000::activate_device_interruption()
-+    {
-+        chunk  ::CALL()
-+        {
-+            rtx_e1000_register_write32(ctx, E1000_IMS,
-+                                       E1000_INTR_TXDW |
-+                                       E1000_INTR_TXQE |
-+                                       E1000_INTR_LSC  |
-+                                       E1000_INTR_RXO  |
-+                                       E1000_INTR_RXT0);
-+        }
-+    }
-+
-+    template sequence   e1000::set_up_device()
-+    {
-+        chunk  ::CALL()
-+        {
-+            rtx_e1000_register_set32(ctx, E1000_CTRL,
-+                                     E1000_CMD_ASDE |
-+                                     E1000_CMD_SLU  |
-+                                     E1000_CMD_LRST |
-+                                     E1000_CMD_PHY_RST);
-+        }
-+    }
-+
-+    template sequence   e1000::handle_intr()
-+    {
-+        chunk   ::CALL()
-+        {
-+            int intr;
-+
-+            intr = rtx_e1000_register_read32(ctx, E1000_ICR);
-+            if (intr & E1000_INTR_LSC)
-+            {
-+                ${Log::info("Link status changed")};
-+            }
-+
-+            if (intr)
-+            {
-+                return IRQ_HANDLED;
-+            }
-+        }
-+    }
-+}
-diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/e1000.rti
-@@ -0,0 +1,89 @@
-+interface e1000 : Socket, Ethernet, PCI, LKM
-+{
-+    provided type   e1000::Context;
-+    provided type   e1000::Register;
-+    provided type   e1000::Commands;
-+
-+    /*
-+     * This sequence should receive an argument like Ethernet::Device, but it is
-+     * unclear about how this argument should be bound to a variable/argument in
-+     * the instrumented C code.
-+     *
-+     * Here again, we rely on the fact that *we* wrote the parent context and
-+     * named the C variables we need/use with the same name everywhere.
-+     */
-+    provided sequence   e1000::create_device()
-+    {
-+        provided chunk  Ethernet::create_device;
-+        provided chunk  ::CALL;
-+    }
-+
-+    provided sequence   e1000::destroy_device()
-+    {
-+        provided chunk  Ethernet::destroy_device;
-+        provided chunk  ::CALL;
-+    }
-+
-+    /*
-+     * This should take an e1000::Context as the first argument but this was
-+     * not working as wished.
-+     */
-+    provided sequence   e1000::print_status()
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+        provided chunk  ::CALL;
-+    }
-+
-+    provided sequence   e1000::setup_interrupt_handler()
-+    {
-+        provided chunk  LKM::includes; // work without this one
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+        provided chunk  ::CALL;
-+    }
-+
-+    provided sequence   e1000::free_interrupt_handler()
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+        provided chunk  ::CALL;
-+    }
-+
-+    provided sequence   e1000::activate_device_interruption()
-+    {
-+        provided chunk  ::CALL;
-+    }
-+
-+    provided sequence   e1000::set_up_device()
-+    {
-+        provided chunk  ::CALL;
-+    }
-+
-+    provided sequence   e1000::handle_intr()
-+    {
-+        provided chunk  ::CALL;
-+    }
-+
-+
-+    provided sequence   e1000::register_read32(e1000::Context, e1000::Register)
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+        provided chunk  ::CALL;
-+    }
-+
-+    provided sequence   e1000::register_write32(e1000::Context, e1000::Register, ::number)
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+        provided chunk  ::CALL;
-+    }
-+
-+    provided sequence   e1000::register_set32(e1000::Context, e1000::Register, ::number)
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+        provided chunk  ::CALL;
-+    }
-+}
-diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/ethernet.blt
-@@ -0,0 +1,218 @@
-+with Ethernet, PCI, LKM, Log
-+{
-+    template type   Ethernet::Device()
-+    {
-+        chunk LKM::includes()
-+        {
-+            #include <linux/netdevice.h>
-+            #include <linux/etherdevice.h>
-+        }
-+
-+        chunk ::decl()
-+        {
-+            struct rtx_ethernet_dev
-+            {
-+                /*
-+                 * I think it's useless to use the ${PCI::Device} "abstraction"
-+                 * here, since we are already in a Linux specific context here.
-+                 */
-+                struct pci_dev          *pci_dev;
-+                struct net_device       *net_dev;
-+
-+                /* while waiting on issue #8 */
-+                struct rtx_e1000_ctx    hw_ctx;
-+            };
-+        }
-+
-+        chunk ::init(net_dev)
-+        {
-+            ${self} = ${net_dev};
-+        }
-+
-+        map
-+        {
-+        }
-+    }
-+
-+    template sequence   Ethernet::open(Ethernet::Device dev)
-+    {
-+        chunk LKM::prototypes()
-+        {
-+            static int  rtx_ethernet_open(struct net_device *);
-+        }
-+
-+        chunk LKM::code()
-+        {
-+            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;
-+
-+                ${pointcut ::IMPLEMENTATION};
-+
-+                return 0;
-+            }
-+        }
-+    }
-+
-+    template sequence   Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb)
-+    {
-+        chunk LKM::prototypes()
-+        {
-+            static int  rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev);
-+        }
-+
-+        chunk LKM::code()
-+        {
-+            static int  rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev)
-+            {
-+                ${pointcut ::IMPLEMENTATION};
-+
-+                return 0;
-+            }
-+        }
-+    }
-+
-+    template sequence   Ethernet::close(Ethernet::Device dev)
-+    {
-+        chunk LKM::prototypes()
-+        {
-+            static int  rtx_ethernet_close(struct net_device *);
-+        }
-+
-+        chunk LKM::code()
-+        {
-+            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;
-+
-+                ${pointcut ::IMPLEMENTATION};
-+
-+                return 0;
-+            }
-+        }
-+    }
-+
-+    template sequence   Ethernet::interrupt_handler(Ethernet::Device dev)
-+    {
-+        /*
-+         * We can't use the irqreturn_t type here because CNornm doesn't know
-+         * it.
-+         */
-+        chunk LKM::prototypes()
-+        {
-+            static enum irqreturn   rtx_ethernet_interrupt_handler(int, void *);
-+        }
-+
-+        chunk LKM::code()
-+        {
-+            static enum irqreturn   rtx_ethernet_interrupt_handler(int irq, void *dev_id)
-+            {
-+                struct rtx_ethernet_dev* rtx_ether_dev;
-+                struct rtx_e1000_ctx* ctx;
-+
-+                rtx_ether_dev = dev_id;
-+                ctx = &rtx_ether_dev->hw_ctx;
-+                ${pointcut ::IMPLEMENTATION};
-+
-+                return IRQ_NONE;
-+            }
-+        }
-+    }
-+
-+    template sequence   Ethernet::init(PCI::Device pdev)
-+    {
-+        chunk LKM::data()
-+        {
-+            static const struct net_device_ops  rtx_ether_ops =
-+            {
-+                .ndo_open = rtx_ethernet_open,
-+                .ndo_stop = rtx_ethernet_close,
-+                .ndo_start_xmit = rtx_ethernet_xmit,
-+            };
-+        }
-+
-+        chunk PCI::pci_probe_hook()
-+        {
-+            /*
-+             * This typedef is needed to workaround a bug in CNorm __std__
-+             * dialect.
-+             */
-+            typedef int ${Ethernet::Device};
-+            ${Ethernet::Device} *rtx_ether_ctx;
-+            struct net_device   *net_dev;
-+            int error;
-+
-+            error = 0;
-+            net_dev = alloc_etherdev(sizeof(*rtx_ether_ctx));
-+            if (net_dev == 0)
-+            {
-+                ${Log::info("Cannot allocate memory")};
-+                /*
-+                 * Again, the error should be "raised" in the parent context.
-+                 *
-+                 * Here we know that we should return ENOMEM because *we* wrote
-+                 * the parent context.
-+                 */
-+                return -ENOMEM;
-+            }
-+            strlcpy(net_dev->name, ${config.ifname}, sizeof(net_dev->name));
-+            net_dev->irq = pdev->irq;
-+            // Maybe we should try ${rtx_ether_ctx.init()} here:
-+            rtx_ether_ctx = netdev_priv(net_dev);
-+            //rtx_ether_ctx->pci_dev = ${pdev};
-+            rtx_ether_ctx->pci_dev = pdev; // In the meantime do it directly
-+            rtx_ether_ctx->net_dev = net_dev;
-+
-+            /*
-+             * The substitution of ${pdev} fails here. I also tried to add a
-+             * "substitute method" to the PCI::Device that was just doing
-+             * "${self}" but it didn't work either (it was subsituted by a
-+             * placeholder, e.g: _1).
-+             *
-+             * That's why we cheated a bit and named all the arguments pdev.
-+             */
-+            //SET_NETDEV_DEV(net_dev, &${pdev}->dev);
-+            SET_NETDEV_DEV(net_dev, &pdev->dev);
-+            net_dev->netdev_ops = &rtx_ether_ops;
-+            if ((error = register_netdev(net_dev)))
-+            {
-+                ${Log::info("Cannot register the driver")};
-+                return error;
-+            }
-+
-+            /* same problem as above with ${pdev} */
-+            //pci_set_drvdata(${pdev}, net_dev);
-+            pci_set_drvdata(pdev, net_dev);
-+
-+            ${pointcut Ethernet::create_device};
-+        }
-+
-+        chunk   ::CALL
-+        {
-+        }
-+    }
-+
-+    template sequence   Ethernet::exit(PCI::Device pdev)
-+    {
-+        chunk   PCI::pci_remove_hook()
-+        {
-+            struct net_device *net_dev = pci_get_drvdata(pdev);
-+
-+            ${pointcut Ethernet::destroy_device};
-+
-+            unregister_netdev(net_dev);
-+            /*
-+             * If we had some cleanup todo with struct rtx_ether_ctx we would
-+             * do a netdev_priv(net_dev) here and do it.
-+             */
-+            free_netdev(net_dev);
-+        }
-+
-+        chunk ::CALL
-+        {
-+        }
-+    }
-+}
-+
-diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/ethernet.rti
-@@ -0,0 +1,47 @@
-+interface Ethernet : Socket, PCI, LKM
-+{
-+    provided type       Ethernet::Device;
-+
-+    required variable ::string  Ethernet::ifname;
-+
-+    required sequence   Ethernet::open(Ethernet::Device)
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+    }
-+
-+    required sequence   Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb)
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+    }
-+
-+    required sequence   Ethernet::close(Ethernet::Device)
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+    }
-+
-+    required sequence   Ethernet::interrupt_handler(Ethernet::Device)
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+    }
-+
-+    provided sequence   Ethernet::init(PCI::Device)
-+    {
-+        provided chunk  LKM::data;
-+        provided chunk  PCI::pci_probe_hook;
-+        provided chunk  ::CALL;
-+
-+        provided pointcut   Ethernet::create_device;
-+    }
-+
-+    provided sequence   Ethernet::exit(PCI::Device)
-+    {
-+        provided chunk  ::CALL;
-+        provided chunk  PCI::pci_remove_hook;
-+
-+        provided pointcut   Ethernet::destroy_device;
-+    }
-+}
-diff --git a/rathaxes/samples/e1000/lkm.blt b/rathaxes/samples/e1000/lkm.blt
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/lkm.blt
-@@ -0,0 +1,55 @@
-+with LKM
-+{
-+    /* Skel of the generated C file: */
-+    ${pointcut LKM::includes};
-+    ${pointcut LKM::prototypes};
-+    ${pointcut LKM::data};
-+    ${pointcut LKM::code};
-+
-+    template sequence   LKM::init()
-+    {
-+        chunk   LKM::includes()
-+        {
-+            #include <linux/module.h>
-+            #include <linux/kernel.h>
-+        }
-+
-+        chunk   LKM::data()
-+        {
-+            MODULE_DESCRIPTION(${config.description});
-+            MODULE_AUTHOR(${config.author});
-+            MODULE_LICENSE(${config.license});
-+        }
-+
-+        chunk   LKM::code()
-+        {
-+            /*
-+             * Rathaxes doesn't yet support arbitrary "decorators" like __init
-+             * or __exit.
-+             */
-+            static int __attribute__((__section__(".init.text")))  rtx_module_init(void)
-+            {
-+                ${pointcut ::IMPLEMENTATION};
-+                ${pointcut LKM::init_bus_hook};
-+
-+                return 0;
-+            }
-+
-+            module_init(rtx_module_init);
-+        }
-+    }
-+
-+    template sequence   LKM::exit()
-+    {
-+        chunk   LKM::code()
-+        {
-+            static void __attribute__((__section__(".exit.text")))   rtx_module_exit(void)
-+            {
-+                ${pointcut ::IMPLEMENTATION};
-+                ${pointcut LKM::deinit_bus_hook};
-+            }
-+
-+            module_exit(rtx_module_exit);
-+        }
-+    }
-+}
-diff --git a/rathaxes/samples/e1000/lkm.rti b/rathaxes/samples/e1000/lkm.rti
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/lkm.rti
-@@ -0,0 +1,25 @@
-+interface LKM
-+{
-+    provided pointcut   LKM::includes;
-+    /* maybe it should be possible to use chunk ::decl in sequence templates? */
-+    provided pointcut   LKM::prototypes;
-+    provided pointcut   LKM::data;
-+    provided pointcut   LKM::code;
-+
-+    required variable ::string  LKM::author;
-+    required variable ::string  LKM::description;
-+    required variable ::string  LKM::license;
-+
-+    required sequence   LKM::init()
-+    {
-+        provided chunk      LKM::includes;
-+        provided chunk      LKM::code;
-+        provided pointcut   LKM::init_bus_hook;
-+    }
-+
-+    required sequence   LKM::exit()
-+    {
-+        provided chunk      LKM::code;
-+        provided pointcut   LKM::deinit_bus_hook;
-+    }
-+}
-diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/lkm.rtx
-@@ -0,0 +1,52 @@
-+device LKM use LKM, PCI, Ethernet, Log
-+{
-+    Ethernet::open(Ethernet::Device dev)
-+    {
-+        Log::info("Open the device");
-+        e1000::setup_interrupt_handler();
-+        Log::info("Interrupt handler installed");
-+        e1000::set_up_device();
-+        e1000::activate_device_interruption();
-+    }
-+
-+    Ethernet::close(Ethernet::Device dev)
-+    {
-+        Log::info("Close the device");
-+        e1000::free_interrupt_handler();
-+    }
-+
-+    Ethernet::interrupt_handler(Ethernet::Device dev)
-+    {
-+        Log::info("Got an interruption");
-+        e1000::handle_intr();
-+    }
-+
-+    Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb)
-+    {
-+        Log::info("We have one packet to transmit!");
-+    }
-+
-+    LKM::init()
-+    {
-+        Log::info("Hello this is LKM");
-+    }
-+
-+    LKM::exit()
-+    {
-+        Log::info("Good bye this was LKM");
-+    }
-+}
-+
-+configuration
-+{
-+    LKM::name = "hello";
-+    LKM::author = "Rathaxes";
-+    LKM::description = "Hello World Loadable Kernel Module (LKM)";
-+    LKM::license = "GPL";
-+
-+    PCI::vendor_id = 0x8086;
-+    PCI::product_id = 0x100f;
-+    PCI::set_master = true;
-+
-+    Ethernet::ifname = "rtx%d";
-+}
-diff --git a/rathaxes/samples/e1000/log.blt b/rathaxes/samples/e1000/log.blt
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/log.blt
-@@ -0,0 +1,10 @@
-+with Log
-+{
-+    template sequence   Log::info(::string msg)
-+    {
-+        chunk   ::CALL
-+        {
-+            pr_info("%s\n", ${msg});
-+        }
-+    }
-+}
-diff --git a/rathaxes/samples/e1000/log.rti b/rathaxes/samples/e1000/log.rti
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/log.rti
-@@ -0,0 +1,7 @@
-+interface Log
-+{
-+    provided sequence   Log::info(::string)
-+    {
-+        provided chunk  ::CALL;
-+    }
-+}
-diff --git a/rathaxes/samples/e1000/pci.blt b/rathaxes/samples/e1000/pci.blt
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/pci.blt
-@@ -0,0 +1,143 @@
-+with PCI, LKM, Log
-+{
-+    template type   PCI::Device()
-+    {
-+        chunk   LKM::includes()
-+        {
-+            #include <linux/pci.h>
-+        }
-+
-+        chunk   ::decl()
-+        {
-+            struct pci_dev;
-+        }
-+
-+        chunk   ::init(pci_dev)
-+        {
-+            ${self} = ${pci_dev};
-+        }
-+
-+        map
-+        {
-+        }
-+    }
-+
-+    template sequence   PCI::probe(PCI::Device pdev)
-+    {
-+        chunk LKM::prototypes()
-+        {
-+            static int /* __devinit */  rtx_pci_probe(struct pci_dev *,
-+                                                      const struct pci_device_id *);
-+        }
-+
-+        chunk LKM::code()
-+        {
-+            static int /* __devinit */  rtx_pci_probe(struct pci_dev *pdev,
-+                                                      const struct pci_device_id *pdev_id)
-+            {
-+                int             err;
-+
-+                err = pci_enable_device(pdev);
-+                if (err < 0)
-+                    goto fail;
-+
-+                ${pointcut PCI::pci_probe_hook};
-+
-+                return 0;
-+
-+                fail:
-+                    return err;
-+            }
-+        }
-+
-+        chunk   ::CALL
-+        {
-+        }
-+    }
-+
-+    template sequence   PCI::remove(PCI::Device pdev)
-+    {
-+        chunk LKM::prototypes()
-+        {
-+            static void rtx_pci_remove(struct pci_dev *);
-+        }
-+
-+        chunk LKM::code()
-+        {
-+            static void rtx_pci_remove(struct pci_dev *pdev)
-+            {
-+                ${pointcut PCI::pci_remove_hook};
-+
-+                pci_disable_device(pdev);
-+            }
-+        }
-+
-+        chunk   ::CALL()
-+        {
-+        }
-+    }
-+
-+    template sequence   PCI::register()
-+    {
-+        chunk LKM::data()
-+        {
-+            /*
-+             * CNorm doesn't seem to like "dynamic" arrays (i.e: you always
-+             * have to specify the exact size).
-+             */
-+            static struct pci_device_id rtx_pci_device_table[2] = {
-+                { ${config.vendor_id}, ${config.product_id}, PCI_ANY_ID, PCI_ANY_ID },
-+                { 0, }
-+            };
-+
-+            static struct pci_driver rtx_pci_driver = {
-+                .name = ${config.name},
-+                .id_table = rtx_pci_device_table,
-+                .probe = rtx_pci_probe,
-+                .remove = rtx_pci_remove
-+            };
-+        }
-+
-+        chunk LKM::init_bus_hook()
-+        {
-+            int error;
-+            if ((error = pci_register_driver(&rtx_pci_driver)))
-+            {
-+                 ${Log::info("Cannot register pci driver")};
-+                 /*
-+                  * So we catched the error but how do we return it to the
-+                  * parent context?
-+                  *
-+                  * Here we know that we can just return error, but that's just
-+                  * a coincidence (and, in this case, *we* wrote the parent
-+                  * context).
-+                  */
-+                 return error;
-+            }
-+        }
-+
-+        chunk ::CALL()
-+        {
-+            /*
-+             * The implementation of ::CALL is empty. This template sequence is
-+             * actually not provided nor required.
-+             *
-+             * This sequence is just "intermediate" code that will just inject
-+             * itself in the hook LKM::init_bus_hook for which this sequence
-+             * has a chunk (see above chunk).
-+             */
-+        }
-+    }
-+
-+    template sequence   PCI::unregister()
-+    {
-+        chunk   LKM::deinit_bus_hook()
-+        {
-+            pci_unregister_driver(&rtx_pci_driver);
-+        }
-+
-+        chunk ::CALL
-+        {
-+        }
-+    }
-+}
-diff --git a/rathaxes/samples/e1000/pci.rti b/rathaxes/samples/e1000/pci.rti
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/pci.rti
-@@ -0,0 +1,36 @@
-+interface PCI : LKM
-+{
-+    provided type       PCI::Device;
-+
-+    required variable ::number  PCI::vendor_id;
-+    required variable ::number  PCI::product_id;
-+
-+    provided sequence   PCI::register()
-+    {
-+        provided chunk  ::CALL;
-+        provided chunk  LKM::data;
-+        provided chunk  LKM::init_bus_hook;
-+    }
-+
-+    provided sequence   PCI::unregister()
-+    {
-+        provided chunk  ::CALL;
-+        provided chunk  LKM::deinit_bus_hook;
-+    }
-+
-+    provided sequence   PCI::probe(PCI::Device)
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+
-+        provided pointcut   PCI::pci_probe_hook;
-+    }
-+
-+    provided sequence   PCI::remove(PCI::Device)
-+    {
-+        provided chunk  LKM::prototypes;
-+        provided chunk  LKM::code;
-+
-+        provided pointcut   PCI::pci_remove_hook;
-+    }
-+}
-diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/socket.blt
-@@ -0,0 +1,27 @@
-+with Socket, LKM
-+{
-+    template type Socket::SKBuff()
-+    {
-+        chunk LKM::includes()
-+        {
-+            #include <linux/skbuff.h>
-+        }
-+
-+        chunk ::decl()
-+        {
-+            struct sk_buff;
-+        }
-+
-+        chunk ::init()
-+        {
-+        }
-+
-+        map
-+        {
-+            // some work may have to be done here in order
-+            // to access to some field of the sk_buff.
-+            // We should determine if all the sk_buff management
-+            // can be abstracted from the user.
-+        }
-+    }
-+}
-diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti
-new file mode 100644
---- /dev/null
-+++ b/rathaxes/samples/e1000/socket.rti
-@@ -0,0 +1,4 @@
-+interface Socket : LKM
-+{
-+    provided type Socket::SKBuff;
-+}
--- a/series	Fri Jan 13 11:59:42 2012 +0100
+++ b/series	Fri Jan 13 13:54:37 2012 +0100
@@ -1,2 +1,1 @@
-rathaxes_add_lkm_ethernet_sample.patch
 maintainers_update_the_binaries_installed_with_make_install.patch