changeset 104:c4c33ac02b93

First try at splitting the type nightmare and the refactoring
author Louis Opter <louis@lse.epita.fr>
date Fri, 22 Mar 2013 00:06:00 -0700
parents d9af98faac8a
children fb20f01ea997
files rathaxes_change_the_abstract_type_notation_in_the_e1000_sample.patch rathaxes_e1000_move_the_interrupt_init_and_cleanup_into_ethernet.patch rathaxes_trying_to_fix_the_abstract_type_nightmare_in_e1000.patch series
diffstat 4 files changed, 1030 insertions(+), 960 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rathaxes_change_the_abstract_type_notation_in_the_e1000_sample.patch	Fri Mar 22 00:06:00 2013 -0700
@@ -0,0 +1,762 @@
+# HG changeset patch
+# Parent 6603911e89e5f98231c90bccf4f4cb9d5534e000
+rathaxes: change the abstract type notation in the e1000 sample
+
+Starting with ra24db32bf134 Rathaxes types are generated differently: you
+don't define entire structures anymore, but only the fields. And the
+compiler generate a typedef'ed structure on top of it.
+
+This works fine, except for "abstract types" (the types defined by —and
+used to interact with— the kernel). We need to define these types as
+Rathaxes types to interact with them, in Rathaxes, but with
+ra24db32bf134 it means that we loose (hide) the original type from the
+kernel, making it very difficult to use "abstract types" with the
+kernels APIs.
+
+For example, here the hypothetical generated struct for the abstract
+type "struct net_device" from Linux would be:
+
+typedef struct {
+    struct net_device   data;
+} rtx_GeneratedType;
+
+And here is how we have to use it:
+
+rtx_GeneratedType *my_struct;
+kernel_api_function(&my_struct->data);
+
+This &my_struct->data is actually always a nop, but it's confusing and
+hard to understand.
+
+This changeset changes the notation to:
+
+rtx_GeneratedType *my_struct;
+kernel_api_function((struct net_device *)my_struct);
+
+Which is, I believe, more intuitive and coherent with how you would
+initialize the my_struct pointer here with a return value from the
+kernel (i.e: with a cast into rtx_GeneratedType *).
+
+
+diff --git a/rathaxes/samples/e1000/device.blt b/rathaxes/samples/e1000/device.blt
+--- a/rathaxes/samples/e1000/device.blt
++++ b/rathaxes/samples/e1000/device.blt
+@@ -18,7 +18,7 @@
+ 
+         map
+         {
+-            data:   ${self}->data;
++            k_device: ((struct device *)${self});
+         }
+     }
+ }
+diff --git a/rathaxes/samples/e1000/device.rti b/rathaxes/samples/e1000/device.rti
+--- a/rathaxes/samples/e1000/device.rti
++++ b/rathaxes/samples/e1000/device.rti
+@@ -5,6 +5,6 @@
+         decl        data_types();
+         chunk       LKM::includes();
+         method      init();
+-        attribute   Builtin::symbol data;
++        attribute   Builtin::symbol k_device;
+     }
+ }
+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
+@@ -171,13 +171,17 @@
+ 
+             static int          rtx_e1000_tx_ring_tso_cksum_offload(${e1000::TxRing} *self, ${Socket::SKBuff} *skb)
+             {
+-                ${Socket::AbstractSKBuff} *abs_skb = skb->skbuff;
+-                ${cast local.abs_skb as Socket::AbstractSKBuff};
+-                return skb_is_gso(&${local.abs_skb.data}) || ${local.abs_skb.data}.ip_summed == CHECKSUM_PARTIAL;
++                /* XXX We can't use ${skb} here because it's a pointer */
++                ${Socket::AbstractSKBuff} *k_skb = skb->skbuff;
++                ${cast local.k_skb as Socket::AbstractSKBuff};
++                return skb_is_gso(${local.k_skb.k_sk_buff}) || ${local.k_skb.k_sk_buff}->ip_summed == CHECKSUM_PARTIAL;
+             }
+ 
+             static void         rtx_e1000_tx_ring_put(${e1000::TxRing} *self, ${Socket::SKBuff} *skb)
+             {
++                /* XXX We can't use ${skb} here because it's a pointer */
++                ${Socket::AbstractSKBuff} *k_skb = skb->skbuff;
++                ${cast local.k_skb as Socket::AbstractSKBuff};
+                 WARN_ON(!skb);
+ 
+                 /*
+@@ -188,17 +192,15 @@
+                  * code shouldn't be aware of it and use something more
+                  * abstract.
+                  */
+-                ${Socket::AbstractSKBuff} *abs_skb = skb->skbuff;
+-                ${cast local.abs_skb as Socket::AbstractSKBuff};
+                 ${e1000::TxDescriptor} *tx_desc = &self->base[self->tail];
+                 tx_desc->lower.data = cpu_to_le32(
+                         E1000_TXD_CMD_EOP  |
+                         E1000_TXD_CMD_IFCS |
+                         E1000_TXD_CMD_RS   |
+-                        skb_headlen(&${local.abs_skb.data}));
++                        skb_headlen(${local.k_skb.k_sk_buff}));
+                 tx_desc->upper.data = 0;
+                 tx_desc->buff_addr = cpu_to_le64(skb->dma_handle);
+-                memcpy(&self->skbuffs[self->tail], skb, sizeof(*skb));
++                memcpy(&self->skbuffs[self->tail], ${local.k_skb.k_sk_buff}, sizeof(*${local.k_skb.k_sk_buff}));
+                 self->tail = (self->tail + 1) % ${config.tx_ring_size};
+             }
+ 
+@@ -733,7 +735,7 @@
+             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(
+-                    &${rtx_ether_ctx.device},
++                    ${rtx_ether_ctx.device},
+                     hw_ctx->rx_ring.size,
+                     &hw_ctx->rx_ring.dma_base,
+                     GFP_KERNEL);
+@@ -751,12 +753,10 @@
+              * Allocate the skbuffs, map them for DMA, and write their address
+              * in the corresponding descriptor.
+              */
+-            ${Ethernet::AbstractDevice} *rtx_ether_dev = ${rtx_ether_ctx.net_device};
+-            ${cast local.rtx_ether_dev as Ethernet::AbstractDevice};
+             for (i = 0; i != ${config.rx_ring_size}; ++i)
+             {
+-                hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff}*)  netdev_alloc_skb(
+-                        &${rtx_ether_dev.netdev},
++                hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff}*)netdev_alloc_skb(
++                        ${rtx_ether_ctx.net_device.k_net_dev}, /* XXX: .k_net_dev isn't expanded here */
+                         ${config.rx_buffer_len});
+                 if (!hw_ctx->rx_ring.skbuffs[i].skbuff)
+                 {
+@@ -764,11 +764,11 @@
+                     goto err_skbuffs_alloc;
+                 }
+                 hw_ctx->rx_ring.skbuffs[i].dma_handle = dma_map_single(
+-                        &${rtx_ether_ctx.device},
+-                        &hw_ctx->rx_ring.skbuffs[i].skbuff->data,
++                        ${rtx_ether_ctx.device},
++                        (struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff, /* XXX leaking cast */
+                         ${config.rx_buffer_len},
+                         DMA_FROM_DEVICE);
+-                int dma_error = dma_mapping_error(&${rtx_ether_ctx.device},
++                int dma_error = dma_mapping_error(${rtx_ether_ctx.device},
+                         hw_ctx->rx_ring.skbuffs[i].dma_handle);
+                 if (dma_error)
+                 {
+@@ -820,7 +820,7 @@
+             hw_ctx->tx_ring.size = ${config.tx_ring_size} * sizeof(*hw_ctx->tx_ring.base);
+             hw_ctx->tx_ring.size = ALIGN(hw_ctx->tx_ring.size, 4096);
+             hw_ctx->tx_ring.base = dma_alloc_coherent(
+-                    &${rtx_ether_ctx.device},
++                    ${rtx_ether_ctx.device},
+                     hw_ctx->tx_ring.size,
+                     &hw_ctx->tx_ring.dma_base,
+                     GFP_KERNEL);
+@@ -863,15 +863,16 @@
+             while (i--)
+             {
+                 dma_unmap_single(
+-                        &${rtx_ether_ctx.device},
++                        ${rtx_ether_ctx.device},
+                         hw_ctx->rx_ring.skbuffs[i].dma_handle,
+                         ${config.rx_buffer_len},
+                         DMA_FROM_DEVICE);
+         err_skbuffs_map:
+-                dev_kfree_skb(&hw_ctx->rx_ring.skbuffs[i].skbuff->data);
++                /* XXX leaking cast: */
++                dev_kfree_skb((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff);
+             }
+ 
+-            dma_free_coherent(&${rtx_ether_ctx.device}, hw_ctx->rx_ring.size,
++            dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx->rx_ring.size,
+                     hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base);
+         err_rx_ring_alloc:
+             return -ENOMEM;
+@@ -889,8 +890,13 @@
+     {
+         chunk   ::CALL()
+         {
+-            ${e1000::Context} *hw_ctx;
+-            hw_ctx = &${rtx_ether_ctx}->hw_ctx;
++            /*
++             * XXX: Not generated if named "hw_ctx" (which is funny because
++             * it's used and works in the template right above this one):
++             */
++            ${e1000::Context} *hw_ctx_;
++            ${cast local.hw_ctx_ as e1000::Context};
++            hw_ctx_ = &${rtx_ether_ctx}->hw_ctx;
+ 
+             /*
+              * Free the rx ring:
+@@ -900,22 +906,23 @@
+             for (int i = 0; i != ${config.rx_ring_size}; ++i)
+             {
+                 dma_unmap_single(
+-                        &${rtx_ether_ctx.device},
+-                        (dma_addr_t)hw_ctx->rx_ring.skbuffs[i].dma_handle,
++                        ${rtx_ether_ctx.device},
++                        (dma_addr_t)hw_ctx_->rx_ring.skbuffs[i].dma_handle,
+                         ${config.rx_buffer_len},
+                         DMA_FROM_DEVICE);
+-                dev_kfree_skb(&hw_ctx->rx_ring.skbuffs[i].skbuff->data);
++                /* XXX Go through the rtx types (Socket::SKBuff, AbstractSKBuff) */
++                dev_kfree_skb(hw_ctx_->rx_ring.skbuffs[i].skbuff);
+             }
+-            dma_free_coherent(&${rtx_ether_ctx.device}, hw_ctx->rx_ring.size,
+-                    hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base);
++            dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx_->rx_ring.size,
++                    hw_ctx_->rx_ring.base, hw_ctx_->rx_ring.dma_base);
+             ${Log::info("free_rx_tx: rx ring free'ed")};
+ 
+             /*
+              * Free the tx ring:
+              * - Free the descriptors array.
+              */
+-            dma_free_coherent(&${rtx_ether_ctx.device}, hw_ctx->tx_ring.size,
+-                    hw_ctx->tx_ring.base, hw_ctx->tx_ring.dma_base);
++            dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx_->tx_ring.size,
++                    hw_ctx_->tx_ring.base, hw_ctx_->tx_ring.dma_base);
+             ${Log::info("free_rx_tx: tx ring free'ed")};
+         }
+     }
+@@ -973,13 +980,13 @@
+             ${local.skb.init(kernel_skb)};
+             hw_ctx = &${rtx_ether_ctx}->hw_ctx;
+             tx_ring = &hw_ctx->tx_ring;
+-            devp = (${Device::AbstractDevice}*) &${rtx_ether_ctx.device};
++            devp = (${Device::AbstractDevice}*)${rtx_ether_ctx.device};
+ 
+             ${Log::info("xmit: skbuff details:")};
+             /*
+-             * skb is not expand on the bound C variable (should be rtx_skbuff),
+-             * which is funny because it works for the sequence template call
+-             * right after.
++             * skb does not expand on the bound C variable (should be
++             * rtx_skbuff), which is funny because it works for the
++             * sequence template call right after.
+              */
+             /*
+              * XXX: doesn't work (I tried to pass self explicitely too):
+@@ -1012,8 +1019,8 @@
+ 
+             /* 2. Map the data */
+ 
+-            /* XXX: ${local.skb.map_to(local.devp)}; */
+-            if (rtx_socket_skbuff_map(&skb, &${devp.data}, DMA_TO_DEVICE))
++            /* XXX: ${local.skb.map_to(devp.k_device)}; */
++            if (rtx_socket_skbuff_map(&skb, ${devp.k_device}, DMA_TO_DEVICE))
+             {
+                 ${Log::info("xmit: can't DMA map a SKbuff")};
+                 goto err_skb_map_to;
+@@ -1032,7 +1039,7 @@
+         err_offload:
+         err_skb_map_to:
+             /* XXX: ${local.skb.unmap_to_and_free(local.dev)}; */
+-            rtx_socket_skbuff_unmap_and_free(&skb, &${devp.data}, DMA_TO_DEVICE);
++            rtx_socket_skbuff_unmap_and_free(&skb, ${devp.k_device}, DMA_TO_DEVICE);
+             return NETDEV_TX_OK;
+         }
+     }
+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
+@@ -51,7 +51,7 @@
+     {
+         decl  data_types()
+         {
+-            struct net_device ndev;
++            struct net_device   data;
+         }
+ 
+         chunk LKM::includes()
+@@ -59,9 +59,15 @@
+             #include <linux/netdevice.h>
+         }
+ 
++        method  init(Builtin::symbol dev)
++        {
++            ${self} = (${Ethernet::AbstractDevice} *)${dev};
++        }
++
+         map
+         {
+-            netdev:   ${self}->ndev;
++            k_net_dev: ((struct net_device *)${self});
++            rtx_ether_ctx: netdev_priv((struct net_device *)${self});
+         }
+     }
+ 
+@@ -88,24 +94,33 @@
+             #include <linux/etherdevice.h>
+         }
+ 
+-        method init(Ethernet::AbstractDevice net_dev, PCI::AbstractDevice pci_dev)
++        /* XXX: if the first arg is not called rtx_net_dev, it breaks. */
++        method init(Ethernet::AbstractDevice rtx_net_dev, PCI::AbstractDevice pci_dev)
+         {
+-            ${self} = netdev_priv(&${net_dev.netdev});
++            ${self} = ${rtx_net_dev.rtx_ether_ctx}; 
+             /*
+              * We can use -> because we know that ${self} will be always a
+              * pointer, but the ambiguity sucks.
+              */
+             ${self}->pci_dev = ${pci_dev};
+-            ${self}->net_dev = ${net_dev};
++            ${self}->net_dev = ${rtx_net_dev};
+         }
+ 
+         map
+         {
+-            device: ${self}->pci_dev->data.dev;
++            /*
++             * XXX: I'd like to be able to do things like:
++             * device: ${self.pci_dev.k_pci_dev}->dev;
++             *
++             * Also, using ${PCI::AbstractDevice} instead of directly struct
++             * pci_dev doesn't work.
++             */
++            device: (&((struct pci_dev *)(${self})->pci_dev)->dev);
+             pci_device: ${self}->pci_dev;
+             net_device: ${self}->net_dev;
+-            perm_addr: ${self}->net_dev->ndev.perm_addr;
+-            dev_addr: ${self}->net_dev->ndev.dev_addr;
++            perm_addr: ((struct net_device *)(${self})->net_dev)->perm_addr;
++            dev_addr: ((struct net_device *)(${self})->net_dev)->dev_addr;
++            irq: ((struct pci_dev *)(${self})->pci_dev)->irq;
+         }
+     }
+ 
+@@ -125,8 +140,17 @@
+         {
+             static int  rtx_ethernet_open(struct net_device *dev)
+             {
+-                ${Ethernet::Device} *rtx_ether_ctx = netdev_priv(dev);
++                /*
++                 * XXX The casts are here because the compiler doesn't resolve
++                 * "enclosed" type (e.g: local.var.enclosed) correctly.
++                 */
++                ${Ethernet::AbstractDevice} *rtx_net_dev;
++                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
++                { /* XXX: I end up with a placeholder if I don't open a scope */
++                    ${local.rtx_net_dev.init(local.dev)};
++                }
+ 
++                ${Ethernet::Device} *rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
+                 ${cast local.rtx_ether_ctx as Ethernet::Device};
+ 
+                 int error;
+@@ -186,8 +210,13 @@
+         {
+             static int  rtx_ethernet_close(struct net_device *dev)
+             {
+-                ${Ethernet::Device} *rtx_ether_ctx = netdev_priv(dev);
++                ${Ethernet::AbstractDevice} *rtx_net_dev;
++                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
++                { /* XXX: I end up with a placeholder if I don't open a scope */
++                    ${local.rtx_net_dev.init(local.dev)};
++                }
+ 
++                ${Ethernet::Device} *rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
+                 ${cast local.rtx_ether_ctx as Ethernet::Device};
+ 
+                 /* TODO: change this pointcut into a pointcut/adapter/callback: */
+@@ -220,9 +249,13 @@
+         {
+             static enum irqreturn   rtx_ethernet_interrupt_handler(int irq, void *dev_id)
+             {
+-                ${Ethernet::Device} *rtx_ether_ctx = dev_id;
++                ${Ethernet::AbstractDevice} *rtx_net_dev = dev_id;
++                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
+ 
++                ${Ethernet::Device} *rtx_ether_ctx;
+                 ${cast local.rtx_ether_ctx as Ethernet::Device};
++                rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
++
+                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
+ 
+                 return IRQ_NONE;
+@@ -252,23 +285,26 @@
+          */
+         chunk PCI::pci_probe_hook(PCI::Device rtx_pci_dev)
+         {
++            ${Ethernet::AbstractDevice} *rtx_net_dev;
+             ${Ethernet::Device} *rtx_ether_ctx;
+-            ${Ethernet::AbstractDevice} *net_dev;
+-            ${cast local.net_dev as Ethernet::AbstractDevice};
++            ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
+ 
+-            net_dev = (${Ethernet::AbstractDevice}*) alloc_etherdev(sizeof(*rtx_ether_ctx));
+-            if (!net_dev)
++            /* Cast the result back into our "transparent wrapper" type */
++            rtx_net_dev = (${Ethernet::AbstractDevice}*)alloc_etherdev(sizeof(*rtx_ether_ctx));
++            if (!rtx_net_dev)
+             {
+                 ${Log::info("cannot allocate the ethernet device context")};
+                 error = -ENOMEM;
+                 goto fail;
+             }
+-            SET_NETDEV_DEV(&${local.net_dev.netdev}, ${rtx_pci_dev.device});
+-            strlcpy(${local.net_dev.netdev}.name, ${config.ifname}, sizeof(${local.net_dev.netdev}.name));
+-            ${local.net_dev.netdev}.irq = ${rtx_pci_dev.irq};
+-            ${local.net_dev.netdev}.netdev_ops = &rtx_ether_ops;
++            SET_NETDEV_DEV(${local.rtx_net_dev.k_net_dev}, ${rtx_pci_dev.device});
++            strlcpy(${local.rtx_net_dev.k_net_dev}->name,
++                    ${config.ifname},
++                    sizeof(${local.rtx_net_dev.k_net_dev}->name));
++            ${local.rtx_net_dev.k_net_dev}->irq = ${rtx_pci_dev.irq};
++            ${local.rtx_net_dev.k_net_dev}->netdev_ops = &rtx_ether_ops;
+ 
+-            error = register_netdev(&${local.net_dev.netdev});
++            error = register_netdev(${local.rtx_net_dev.k_net_dev});
+             if (error)
+             {
+                 ${Log::info("cannot register the driver in the net subsystem")};
+@@ -280,14 +316,11 @@
+              * XXX: the cast is here because the compiler resolve the
+              * type of rtx_pci_dev.pci_device to the type of
+              * rtx_pci_dev instead of the type of rtx_pci_dev.pci_device.
+-             *
+-             * Also, I'm getting placeholder in the generated code if
+-             * I don't open a scope here.
+              */
+-            {
+-                ${PCI::AbstractDevice} *rtx_pdev = ${rtx_pci_dev.pci_device};
+-                ${cast local.rtx_pdev as PCI::AbstractDevice};
+-                ${local.rtx_ether_ctx.init(local.net_dev, local.rtx_pdev)};
++            ${PCI::AbstractDevice} *workaround = ${rtx_pci_dev.pci_device};
++            ${cast local.workaround as PCI::AbstractDevice};
++            { /* XXX: I end up with a placeholder if I don't open a scope */
++                ${local.rtx_ether_ctx.init(local.rtx_net_dev, local.workaround)};
+             }
+ 
+             /* Register ourselves in the parent context: */
+@@ -309,7 +342,7 @@
+             ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)};
+             memcpy(${local.rtx_ether_ctx.perm_addr},
+                    ${local.rtx_ether_ctx.dev_addr},
+-                   ${local.net_dev.netdev}.addr_len);
++                   ${local.rtx_net_dev.k_net_dev}->addr_len);
+         }
+ 
+         /* This chunk should be removed (see #26) */
+@@ -326,15 +359,15 @@
+          */
+         chunk   PCI::pci_remove_hook(PCI::Device rtx_pci_dev)
+         {
+-            ${Ethernet::Device} *rtx_ether_ctx = ${rtx_pci_dev.context};
+-            ${Ethernet::AbstractDevice} *rtx_ether_dev = (${Ethernet::AbstractDevice}*) ${local.rtx_ether_ctx.net_device};
+-
++            ${Ethernet::Device} *rtx_ether_ctx = ${rtx_pci_dev.rtx_drv_context};
++            ${cast local.rtx_ether_ctx as Ethernet::Device}; /* XXX */
+             BUG_ON(!rtx_ether_ctx);
+ 
+-            ${cast local.rtx_ether_ctx as Ethernet::Device};
+-            ${cast local.rtx_ether_dev as Ethernet::AbstractDevice};
+-            unregister_netdev(&${local.rtx_ether_dev.netdev});
+-            free_netdev(&${local.rtx_ether_dev.netdev});
++            ${Ethernet::AbstractDevice} *rtx_net_dev = ${local.rtx_ether_ctx.net_device};
++            ${cast local.rtx_net_dev as Ethernet::AbstractDevice}; /* XXX */
++
++            unregister_netdev(${local.rtx_net_dev.k_net_dev});
++            free_netdev(${local.rtx_net_dev.k_net_dev});
+         }
+ 
+         /* This chunk should be removed (see #26) */
+diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti
+--- a/rathaxes/samples/e1000/ethernet.rti
++++ b/rathaxes/samples/e1000/ethernet.rti
+@@ -16,8 +16,15 @@
+     provided type   AbstractDevice
+     {
+         chunk       LKM::includes();
++        method      init(Builtin::symbol);
+         decl        data_types();
+-        attribute   Builtin::symbol netdev;
++
++        attribute   Builtin::symbol k_net_dev;
++        /*
++         * XXX: should be a Ethernet::Device, but that causes a circular
++         * dependency.
++         */
++        attribute   Builtin::symbol rtx_ether_ctx;
+     }
+ 
+     provided type   Device
+@@ -34,8 +41,9 @@
+          * I'd like to use better names here, but I'd like to understand the
+          * difference between the two first:
+          */
+-        attribute   Builtin::symbol             perm_addr;
+-        attribute   Builtin::symbol             dev_addr;
++        attribute   Builtin::symbol perm_addr;
++        attribute   Builtin::symbol dev_addr;
++        attribute   Builtin::symbol irq;
+     }
+ 
+     required sequence   open(Ethernet::Device)
+diff --git a/rathaxes/samples/e1000/pci.blt b/rathaxes/samples/e1000/pci.blt
+--- a/rathaxes/samples/e1000/pci.blt
++++ b/rathaxes/samples/e1000/pci.blt
+@@ -16,15 +16,15 @@
+         {
+         }
+ 
+-        method  set_context(Builtin::symbol ctx)
++        method  set_rtx_context(Builtin::symbol ctx)
+         {
+-            pci_set_drvdata(&${self}->data, ${ctx});
++            pci_set_drvdata(${self.k_pci_dev}, ${ctx});
+         }
+ 
+         map
+         {
+-            data: ${self}->data;
+-            drv_data: pci_get_drvdata(&${self}->data);
++            k_pci_dev: ((struct pci_dev *)${self});
++            rtx_pci_ctx: pci_get_drvdata((struct pci_dev *)${self});
+         }
+     }
+ 
+@@ -52,13 +52,13 @@
+                 int error;
+                 ${PCI::AbstractDevice}  *enable_pdev = self->pdev;
+                 ${cast local.enable_pdev as PCI::AbstractDevice};
+-                error = pci_enable_device(&${local.enable_pdev.data});
++                error = pci_enable_device(${local.enable_pdev.k_pci_dev});
+                 if (error)
+                     return error;
+-                error = pci_request_selected_regions(&${local.enable_pdev.data}, self->bars, ${config.name});
++                error = pci_request_selected_regions(${local.enable_pdev.k_pci_dev}, self->bars, ${config.name});
+                 if (error)
+                     return error;
+-                pci_set_master(&${local.enable_pdev.data});
++                pci_set_master(${local.enable_pdev.k_pci_dev});
+                 return 0;
+             }
+ 
+@@ -68,8 +68,8 @@
+                 ${cast local.disable_pdev as PCI::AbstractDevice};
+                 if (self->ioaddr)
+                     iounmap(self->ioaddr);
+-                pci_release_selected_regions(&${local.disable_pdev.data}, self->bars);
+-                pci_disable_device(&${local.disable_pdev.data});
++                pci_release_selected_regions(${local.disable_pdev.k_pci_dev}, self->bars);
++                pci_disable_device(${local.disable_pdev.k_pci_dev});
+             }
+         }
+ 
+@@ -78,7 +78,7 @@
+             ${PCI::AbstractDevice} * workaround = (${PCI::AbstractDevice}*)pdev;
+             ${cast local.workaround as PCI::AbstractDevice};
+             ${self}->pdev = ${pdev};
+-            ${self}->bars = pci_select_bars(&${local.workaround.data}, IORESOURCE_MEM);
++            ${self}->bars = pci_select_bars(${local.workaround.k_pci_dev}, IORESOURCE_MEM);
+             ${self}->ioaddr = NULL;
+             ${self}->context = NULL;
+         }
+@@ -97,20 +97,20 @@
+         {
+             ${PCI::AbstractDevice} *select_ioaddr_pdev = ${self}->pdev;
+             ${cast local.select_ioaddr_pdev as PCI::AbstractDevice};
+-            ${self}->ioaddr = pci_ioremap_bar(&${local.select_ioaddr_pdev.data}, ${bar});
++            ${self}->ioaddr = pci_ioremap_bar(${local.select_ioaddr_pdev.k_pci_dev}, ${bar});
+         }
+ 
+-        method  set_context(Builtin::symbol ctx)
++        method  set_rtx_drv_context(Builtin::symbol ctx)
+         {
+             ${self}->context = ctx;
+         }
+ 
+         map
+         {
+-            context: ${self}->context;
+-            device: &${self}->pdev->data.dev;
++            rtx_drv_context: ${self}->context;
++            device: &((struct pci_dev *)(${self})->pdev)->dev;
+             pci_device: ${self}->pdev;
+-            irq: ${self}->pdev->data.irq;
++            irq: ((struct pci_dev *)(${self})->pdev)->irq;
+             bars: ${self}->bars;
+             ioaddr: ${self}->ioaddr;
+             BAR_0: 0;
+@@ -151,7 +151,7 @@
+                     ${local.rtx_pci_dev.init(local.rtx_pdev)};
+                 }
+ 
+-                /* ${local.pdev.set_context(local.rtx_pci_dev)}; */
++                /* ${local.pdev.set_rtx_context(local.rtx_pci_dev)}; */
+                 pci_set_drvdata(pdev, rtx_pci_dev);
+ 
+                 /* ${local.rtx_pci_dev.enable()}; */
+@@ -184,7 +184,7 @@
+                 return 0;
+ 
+             fail:
+-                /* ${local.pdev.set_context(NULL)}; */
++                /* ${local.pdev.set_rtx_drv_context(NULL)}; */
+                 pci_set_drvdata(pdev, NULL);
+                 kfree(rtx_pci_dev);
+                 return error;
+@@ -210,7 +210,7 @@
+             {
+                 ${PCI::AbstractDevice}  *rtx_pdev = (${PCI::AbstractDevice}*)pdev;
+                 ${cast local.rtx_pdev as PCI::AbstractDevice};
+-                ${PCI::Device} *rtx_pci_dev = ${rtx_pdev.drv_data};
++                ${PCI::Device} *rtx_pci_dev = ${rtx_pdev.rtx_pci_ctx};
+ 
+                 BUG_ON(!rtx_pci_dev);
+ 
+diff --git a/rathaxes/samples/e1000/pci.rti b/rathaxes/samples/e1000/pci.rti
+--- a/rathaxes/samples/e1000/pci.rti
++++ b/rathaxes/samples/e1000/pci.rti
+@@ -10,10 +10,15 @@
+ 
+         chunk       LKM::includes();
+         method      init(PCI::AbstractDevice);
+-        method      set_context(Builtin::symbol);
++        /*
++         * XXX: the argument should be a PCI::Device but that causes a circular
++         * dependency:
++         */
++        method      set_rtx_context(Builtin::symbol);
+ 
+-        attribute   Builtin::symbol data;
+-        attribute   Builtin::symbol drv_data;
++        attribute   Builtin::symbol k_pci_dev;
++        /* XXX: should be PCI::Device (see above point) */
++        attribute   Builtin::symbol rtx_pci_ctx;
+     }
+ 
+     provided type   PCI::Device
+@@ -27,9 +32,9 @@
+         method      enable();
+         method      disable();
+         method      select_ioaddr(Builtin::number);
+-        method      set_context(Builtin::symbol);
++        method      set_rtx_drv_context(Builtin::symbol);
+ 
+-        attribute   Builtin::symbol         context;
++        attribute   Builtin::symbol         rtx_drv_context;
+         attribute   Device::AbstractDevice  device;
+         attribute   PCI::AbstractDevice     pci_device;
+         attribute   Builtin::symbol         ioaddr;
+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
+@@ -14,7 +14,7 @@
+ 
+         map
+         {
+-            data: ${self}->data;
++            k_sk_buff: ((struct sk_buff *)${self});
+         }
+     }
+ 
+@@ -46,11 +46,12 @@
+                  */
+                 ${Socket::AbstractSKBuff}   *skb = self->skbuff;
+                 ${cast local.skb as Socket::AbstractSKBuff};
+-                ${Ethernet::ProtocolId} ethernet_proto = { .id = be16_to_cpu(${local.skb.data}.protocol) };
++                ${Ethernet::ProtocolId} ethernet_proto = { .id = be16_to_cpu(${local.skb.k_sk_buff}->protocol) };
++
+                 static const char * const ip_summed_values[] = {
+                     "none", "unnecessary", "complete", "partial"
+                 };
+-                struct skb_shared_info *shinfo = skb_shinfo(&${local.skb.data});
++                struct skb_shared_info *shinfo = skb_shinfo(${local.skb.k_sk_buff});
+ 
+                 pr_info(
+                         "\t protocol = %#-5x (%s) ip_summed = %d (%s)\n"
+@@ -59,8 +60,8 @@
+                         "\t gso_size = %-5u gso_segs = %-5u gso_type = %-5u",
+                         /* XXX: can't use ${local.ethernet_proto.id} here (issue #52): */
+                         ethernet_proto.id, ${local.ethernet_proto.str},
+-                        ${local.skb.data}.ip_summed, ip_summed_values[${local.skb.data}.ip_summed],
+-                        ${local.skb.data}.len, ${local.skb.data}.data_len, skb_headlen(&${local.skb.data}),
++                        ${local.skb.k_sk_buff}->ip_summed, ip_summed_values[${local.skb.k_sk_buff}->ip_summed],
++                        ${local.skb.k_sk_buff}->len, ${local.skb.k_sk_buff}->data_len, skb_headlen(${local.skb.k_sk_buff}),
+                         shinfo->nr_frags, shinfo->gso_size, shinfo->gso_segs, shinfo->gso_type
+                 );
+             }
+@@ -72,14 +73,13 @@
+                 ${Socket::AbstractSKBuff}   *skb = self->skbuff;
+                 ${cast local.skb as Socket::AbstractSKBuff};
+ 
+-                WARN_ON(!skb);
+-                WARN_ON(!${local.skb.data}.data);
++                WARN_ON(!${local.skb.k_sk_buff});
+                 WARN_ON(self->dma_handle);
+ 
+                 self->dma_handle = dma_map_single(
+                         dev,
+-                        &${local.skb.data}.data,
+-                        skb_headlen(&${local.skb.data}),
++                        ${local.skb.k_sk_buff},
++                        skb_headlen(${local.skb.k_sk_buff}),
+                         direction);
+                 int err = dma_mapping_error(dev, self->dma_handle);
+                 if (err)
+@@ -97,18 +97,17 @@
+                 ${Socket::AbstractSKBuff}   *skb = self->skbuff;
+                 ${cast local.skb as Socket::AbstractSKBuff};
+ 
+-                WARN_ON(!${local.skb});
+-                WARN_ON(!${local.skb.data}.data);
++                WARN_ON(!${local.skb.k_sk_buff});
+ 
+                 if (self->dma_handle)
+                 {
+                     dma_unmap_single(dev,
+                             self->dma_handle,
+-                            skb_headlen(&${local.skb.data}),
++                            skb_headlen(${local.skb.k_sk_buff}),
+                             direction);
+                     self->dma_handle = 0;
+                 }
+-                dev_kfree_skb_any(&${local.skb.data});
++                dev_kfree_skb_any(${local.skb.k_sk_buff});
+                 self->skbuff = 0;
+             }
+         }
+@@ -131,22 +130,22 @@
+ 
+         method   map_to(Device::AbstractDevice dev)
+         {
+-            rtx_socket_skbuff_map(${self}, &${dev.data}, DMA_TO_DEVICE);
++            rtx_socket_skbuff_map(${self}, ${dev.k_device}, DMA_TO_DEVICE);
+         }
+ 
+         method   map_from(Device::AbstractDevice dev)
+         {
+-            rtx_socket_skbuff_map(${self}, &${dev.data}, DMA_FROM_DEVICE);
++            rtx_socket_skbuff_map(${self}, ${dev.k_device}, DMA_FROM_DEVICE);
+         }
+ 
+         method   unmap_to_and_free(Device::AbstractDevice dev)
+         {
+-            rtx_socket_skbuff_unmap_and_free(${self}, &${dev.data}, DMA_TO_DEVICE);
++            rtx_socket_skbuff_unmap_and_free(${self}, ${dev.k_device}, DMA_TO_DEVICE);
+         }
+ 
+         method   unmap_from_and_free(Device::AbstractDevice dev)
+         {
+-            rtx_socket_skbuff_unmap_and_free(${self}, &${dev.data}, DMA_FROM_DEVICE);
++            rtx_socket_skbuff_unmap_and_free(${self}, ${dev.k_device}, DMA_FROM_DEVICE);
+         }
+ 
+         map
+diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti
+--- a/rathaxes/samples/e1000/socket.rti
++++ b/rathaxes/samples/e1000/socket.rti
+@@ -5,7 +5,8 @@
+     {
+         chunk       LKM::includes();
+         decl        data_types();
+-        attribute   Builtin::symbol data;
++
++        attribute   Builtin::symbol k_sk_buff;
+     }
+ 
+     provided type   SKBuff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rathaxes_e1000_move_the_interrupt_init_and_cleanup_into_ethernet.patch	Fri Mar 22 00:06:00 2013 -0700
@@ -0,0 +1,266 @@
+# HG changeset patch
+# Parent 68c4f142af579e558314cdeebd091fc5abd62014
+
+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,6 @@
+         {
+             int                         bars;
+             unsigned char /* __iomem */ *ioaddr;
+-            int                         irq;
+ 
+             ${e1000::RxRing}    rx_ring;
+             ${e1000::TxRing}    tx_ring;
+@@ -267,14 +266,12 @@
+ 
+         chunk   Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx,
+                                                Builtin::number bars,
+-                                               Builtin::symbol ioaddr,
+-                                               Builtin::number irq)
++                                               Builtin::symbol ioaddr)
+         {
+             {
+                 ${e1000::Context} *hw_ctx = &${rtx_ether_ctx}->hw_ctx;
+                 hw_ctx->bars = ${bars};
+                 hw_ctx->ioaddr = ${ioaddr};
+-                hw_ctx->irq = ${irq};
+             }
+         }
+ 
+@@ -606,68 +603,6 @@
+         }
+     }
+ 
+-    template sequence   e1000::setup_interrupt_handler(Ethernet::Device rtx_ether_ctx)
+-    {
+-        chunk   LKM::includes()
+-        {
+-            #include <linux/interrupt.h>
+-        }
+-
+-        chunk   LKM::prototypes()
+-        {
+-            static int e1000_setup_interrupt_handler(${Ethernet::Device} *);
+-        }
+-
+-        chunk   LKM::code()
+-        {
+-            static int e1000_setup_interrupt_handler(${Ethernet::Device} *rtx_ether_ctx)
+-            {
+-                int error;
+-
+-                error = request_irq(rtx_ether_ctx->hw_ctx.irq,
+-                        rtx_ethernet_interrupt_handler,
+-                        IRQF_SHARED,
+-                        ${config.name},
+-                        rtx_ether_ctx);
+-
+-                if (error)
+-                    ${Log::info("cannot register the interrupt handler")};
+-
+-                return error;
+-            }
+-        }
+-
+-        chunk   ::CALL()
+-        {
+-                int error = e1000_setup_interrupt_handler(${rtx_ether_ctx});
+-                if (error)
+-                {
+-                        return error;
+-                }
+-        }
+-    }
+-
+-    template sequence   free_interrupt_handler(Ethernet::Device rtx_ether_ctx)
+-    {
+-        chunk   prototypes()
+-        {
+-            static void e1000_free_interrupt_handler(${Ethernet::Device} *rtx_ether_ctx);
+-        }
+-
+-        chunk code()
+-        {
+-            static void e1000_free_interrupt_handler(${Ethernet::Device} *rtx_ether_ctx)
+-            {
+-                free_irq(rtx_ether_ctx->hw_ctx.irq, rtx_ether_ctx);
+-            }
+-        }
+-
+-        chunk ::CALL()
+-        {
+-            e1000_free_interrupt_handler(${rtx_ether_ctx});
+-        }
+-    }
+-
+     template sequence   activate_device_interruption(Ethernet::Device rtx_ether_ctx)
+     {
+         chunk  ::CALL()
+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
+@@ -13,8 +13,7 @@
+         /* Callbacks/Hooks which should probably be in the front-end: */
+         chunk       Ethernet::adapter_init_context(Ethernet::Device,
+                                                    Builtin::number,
+-                                                   Builtin::symbol,
+-                                                   Builtin::number);
++                                                   Builtin::symbol);
+         chunk       Ethernet::adapter_reset(Ethernet::Device);
+         chunk       Ethernet::adapter_load_mac_address(Ethernet::Device);
+     }
+@@ -85,21 +84,6 @@
+         provided chunk  ::CALL();
+     }
+ 
+-    provided sequence   setup_interrupt_handler(Ethernet::Device)
+-    {
+-        provided chunk  LKM::includes(); // works without this one
+-        provided chunk  LKM::prototypes();
+-        provided chunk  LKM::code();
+-        provided chunk  ::CALL();
+-    }
+-
+-    provided sequence   free_interrupt_handler(Ethernet::Device)
+-    {
+-        provided chunk  LKM::prototypes();
+-        provided chunk  LKM::code();
+-        provided chunk  ::CALL();
+-    }
+-
+     provided sequence   activate_device_interruption(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
+@@ -1,4 +1,4 @@
+-with Ethernet, PCI, LKM, Log
++with Ethernet, PCI, LKM, Log, Builtin
+ {
+     template type   Ethernet::ProtocolId()
+     {
+@@ -111,6 +111,11 @@
+ 
+     template sequence   Ethernet::open(Ethernet::Device dev)
+     {
++        chunk   LKM::includes()
++        {
++            #include <linux/interrupt.h>
++        }
++
+         chunk LKM::prototypes()
+         {
+             static int  rtx_ethernet_open(struct net_device *);
+@@ -123,9 +128,28 @@
+                 ${Ethernet::Device} *rtx_ether_ctx = netdev_priv(dev);
+ 
+                 ${cast local.rtx_ether_ctx as Ethernet::Device};
++
++                int error;
++                {
++                    ${Log::info("installing the interrupt handler")};
++                }
++                error = request_irq(${local.rtx_ether_ctx.irq},
++                                    rtx_ethernet_interrupt_handler,
++                                    IRQF_SHARED,
++                                    ${config.name},
++                                    ${local.rtx_net_dev.k_net_dev});
++                if (error)
++                {
++                    ${Log::info("Cannot register the interrupt handler")};
++                    goto error;
++                }
++
+                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
+ 
+                 return 0;
++
++            error:
++                return error;
+             }
+         }
+     }
+@@ -165,7 +189,16 @@
+                 ${Ethernet::Device} *rtx_ether_ctx = netdev_priv(dev);
+ 
+                 ${cast local.rtx_ether_ctx as Ethernet::Device};
+-                ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
++
++                /* TODO: change this pointcut into a pointcut/adapter/callback: */
++                {
++                    ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
++                }
++
++                free_irq(${local.rtx_ether_ctx.irq}, ${local.rtx_net_dev.k_net_dev});
++                {
++                    ${Log::info("interrupt handler free'ed")};
++                }
+ 
+                 return 0;
+             }
+@@ -267,14 +300,11 @@
+              */
+             int bars = ${rtx_pci_dev.bars};
+             unsigned char /* __iomem */ *ioaddr = ${rtx_pci_dev.ioaddr};
+-            int irq = ${rtx_pci_dev.irq};
+             ${cast local.bars as Builtin::number};
+-            ${cast local.irq as Builtin::number};
+             ${cast local.rtx_ether_ctx as Ethernet::Device};
+             ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx,
+                                                       local.bars,
+-                                                      local.ioaddr,
+-                                                      local.irq)};
++                                                      local.ioaddr)};
+             ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)};
+             ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)};
+             memcpy(${local.rtx_ether_ctx.perm_addr},
+diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti
+--- a/rathaxes/samples/e1000/ethernet.rti
++++ b/rathaxes/samples/e1000/ethernet.rti
+@@ -40,6 +40,7 @@
+ 
+     required sequence   open(Ethernet::Device)
+     {
++        provided chunk  LKM::includes();
+         provided chunk  LKM::prototypes();
+         provided chunk  LKM::code();
+     }
+@@ -69,8 +70,7 @@
+ 
+         provided pointcut   Ethernet::adapter_init_context(Ethernet::Device,
+                                                            Builtin::number,
+-                                                           Builtin::symbol,
+-                                                           Builtin::number);
++                                                           Builtin::symbol);
+         provided pointcut   Ethernet::adapter_reset(Ethernet::Device);
+         provided pointcut   Ethernet::adapter_load_mac_address(Ethernet::Device);
+     }
+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
+@@ -4,13 +4,6 @@
+     {
+         Log::info("opening the device");
+ 
+-        /*
+-         * Maybe e1000::create_device should be called from here, to be
+-         * more coherent.
+-         */
+-
+-        e1000::setup_interrupt_handler(dev);
+-        Log::info("interrupt handler installed");
+ 
+         e1000::set_up_device(dev);
+         Log::info("device activated");
+@@ -32,9 +25,6 @@
+          */
+         e1000::free_rx_tx(dev);
+         Log::info("free'ed up rx/tx resources");
+-
+-        e1000::free_interrupt_handler(dev);
+-        Log::info("interrupt handler free'ed");
+     }
+ 
+     Ethernet::interrupt_handler(Ethernet::Device dev)
--- a/rathaxes_trying_to_fix_the_abstract_type_nightmare_in_e1000.patch	Tue Mar 19 23:16:02 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,959 +0,0 @@
-# HG changeset patch
-# Parent 7a2c9e5880145d2d42cd5bc01dbc2b6e96689934
-
-diff --git a/rathaxes/samples/e1000/device.blt b/rathaxes/samples/e1000/device.blt
---- a/rathaxes/samples/e1000/device.blt
-+++ b/rathaxes/samples/e1000/device.blt
-@@ -18,7 +18,7 @@
- 
-         map
-         {
--            data:   ${self}->data;
-+            k_device: ((struct device *)${self});
-         }
-     }
- }
-diff --git a/rathaxes/samples/e1000/device.rti b/rathaxes/samples/e1000/device.rti
---- a/rathaxes/samples/e1000/device.rti
-+++ b/rathaxes/samples/e1000/device.rti
-@@ -5,6 +5,6 @@
-         decl        data_types();
-         chunk       LKM::includes();
-         method      init();
--        attribute   Builtin::symbol data;
-+        attribute   Builtin::symbol k_device;
-     }
- }
-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
-@@ -171,13 +171,17 @@
- 
-             static int          rtx_e1000_tx_ring_tso_cksum_offload(${e1000::TxRing} *self, ${Socket::SKBuff} *skb)
-             {
--                ${Socket::AbstractSKBuff} *abs_skb = skb->skbuff;
--                ${cast local.abs_skb as Socket::AbstractSKBuff};
--                return skb_is_gso(&${local.abs_skb.data}) || ${local.abs_skb.data}.ip_summed == CHECKSUM_PARTIAL;
-+                /* XXX We can't use ${skb} here because it's a pointer */
-+                ${Socket::AbstractSKBuff} *k_skb = skb->skbuff;
-+                ${cast local.k_skb as Socket::AbstractSKBuff};
-+                return skb_is_gso(${local.k_skb.k_sk_buff}) || ${local.k_skb.k_sk_buff}->ip_summed == CHECKSUM_PARTIAL;
-             }
- 
-             static void         rtx_e1000_tx_ring_put(${e1000::TxRing} *self, ${Socket::SKBuff} *skb)
-             {
-+                /* XXX We can't use ${skb} here because it's a pointer */
-+                ${Socket::AbstractSKBuff} *k_skb = skb->skbuff;
-+                ${cast local.k_skb as Socket::AbstractSKBuff};
-                 WARN_ON(!skb);
- 
-                 /*
-@@ -188,17 +192,15 @@
-                  * code shouldn't be aware of it and use something more
-                  * abstract.
-                  */
--                ${Socket::AbstractSKBuff} *abs_skb = skb->skbuff;
--                ${cast local.abs_skb as Socket::AbstractSKBuff};
-                 ${e1000::TxDescriptor} *tx_desc = &self->base[self->tail];
-                 tx_desc->lower.data = cpu_to_le32(
-                         E1000_TXD_CMD_EOP  |
-                         E1000_TXD_CMD_IFCS |
-                         E1000_TXD_CMD_RS   |
--                        skb_headlen(&${local.abs_skb.data}));
-+                        skb_headlen(${local.k_skb.k_sk_buff}));
-                 tx_desc->upper.data = 0;
-                 tx_desc->buff_addr = cpu_to_le64(skb->dma_handle);
--                memcpy(&self->skbuffs[self->tail], skb, sizeof(*skb));
-+                memcpy(&self->skbuffs[self->tail], ${local.k_skb.k_sk_buff}, sizeof(*${local.k_skb.k_sk_buff}));
-                 self->tail = (self->tail + 1) % ${config.tx_ring_size};
-             }
- 
-@@ -249,7 +251,6 @@
-         {
-             int                         bars;
-             unsigned char /* __iomem */ *ioaddr;
--            int                         irq;
- 
-             ${e1000::RxRing}    rx_ring;
-             ${e1000::TxRing}    tx_ring;
-@@ -267,14 +268,12 @@
- 
-         chunk   Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx,
-                                                Builtin::number bars,
--                                               Builtin::symbol ioaddr,
--                                               Builtin::number irq)
-+                                               Builtin::symbol ioaddr)
-         {
-             {
-                 ${e1000::Context} *hw_ctx = &${rtx_ether_ctx}->hw_ctx;
-                 hw_ctx->bars = ${bars};
-                 hw_ctx->ioaddr = ${ioaddr};
--                hw_ctx->irq = ${irq};
-             }
-         }
- 
-@@ -606,68 +605,6 @@
-         }
-     }
- 
--    template sequence   e1000::setup_interrupt_handler(Ethernet::Device rtx_ether_ctx)
--    {
--        chunk   LKM::includes()
--        {
--            #include <linux/interrupt.h>
--        }
--
--        chunk   LKM::prototypes()
--        {
--            static int e1000_setup_interrupt_handler(${Ethernet::Device} *);
--        }
--
--        chunk   LKM::code()
--        {
--            static int e1000_setup_interrupt_handler(${Ethernet::Device} *rtx_ether_ctx)
--            {
--                int error;
--
--                error = request_irq(rtx_ether_ctx->hw_ctx.irq,
--                        rtx_ethernet_interrupt_handler,
--                        IRQF_SHARED,
--                        ${config.name},
--                        rtx_ether_ctx);
--
--                if (error)
--                    ${Log::info("cannot register the interrupt handler")};
--
--                return error;
--            }
--        }
--
--        chunk   ::CALL()
--        {
--                int error = e1000_setup_interrupt_handler(${rtx_ether_ctx});
--                if (error)
--                {
--                        return error;
--                }
--        }
--    }
--
--    template sequence   free_interrupt_handler(Ethernet::Device rtx_ether_ctx)
--    {
--        chunk   prototypes()
--        {
--            static void e1000_free_interrupt_handler(${Ethernet::Device} *rtx_ether_ctx);
--        }
--
--        chunk code()
--        {
--            static void e1000_free_interrupt_handler(${Ethernet::Device} *rtx_ether_ctx)
--            {
--                free_irq(rtx_ether_ctx->hw_ctx.irq, rtx_ether_ctx);
--            }
--        }
--
--        chunk ::CALL()
--        {
--            e1000_free_interrupt_handler(${rtx_ether_ctx});
--        }
--    }
--
-     template sequence   activate_device_interruption(Ethernet::Device rtx_ether_ctx)
-     {
-         chunk  ::CALL()
-@@ -798,7 +735,7 @@
-             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(
--                    &${rtx_ether_ctx.device},
-+                    ${rtx_ether_ctx.device},
-                     hw_ctx->rx_ring.size,
-                     &hw_ctx->rx_ring.dma_base,
-                     GFP_KERNEL);
-@@ -816,12 +753,10 @@
-              * Allocate the skbuffs, map them for DMA, and write their address
-              * in the corresponding descriptor.
-              */
--            ${Ethernet::AbstractDevice} *rtx_ether_dev = ${rtx_ether_ctx.net_device};
--            ${cast local.rtx_ether_dev as Ethernet::AbstractDevice};
-             for (i = 0; i != ${config.rx_ring_size}; ++i)
-             {
--                hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff}*)  netdev_alloc_skb(
--                        &${rtx_ether_dev.netdev},
-+                hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff}*)netdev_alloc_skb(
-+                        ${rtx_ether_ctx.net_device.k_net_dev}, /* XXX: .k_net_dev isn't expanded here */
-                         ${config.rx_buffer_len});
-                 if (!hw_ctx->rx_ring.skbuffs[i].skbuff)
-                 {
-@@ -829,11 +764,11 @@
-                     goto err_skbuffs_alloc;
-                 }
-                 hw_ctx->rx_ring.skbuffs[i].dma_handle = dma_map_single(
--                        &${rtx_ether_ctx.device},
--                        &hw_ctx->rx_ring.skbuffs[i].skbuff->data,
-+                        ${rtx_ether_ctx.device},
-+                        (struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff, /* XXX leaking cast */
-                         ${config.rx_buffer_len},
-                         DMA_FROM_DEVICE);
--                int dma_error = dma_mapping_error(&${rtx_ether_ctx.device},
-+                int dma_error = dma_mapping_error(${rtx_ether_ctx.device},
-                         hw_ctx->rx_ring.skbuffs[i].dma_handle);
-                 if (dma_error)
-                 {
-@@ -885,7 +820,7 @@
-             hw_ctx->tx_ring.size = ${config.tx_ring_size} * sizeof(*hw_ctx->tx_ring.base);
-             hw_ctx->tx_ring.size = ALIGN(hw_ctx->tx_ring.size, 4096);
-             hw_ctx->tx_ring.base = dma_alloc_coherent(
--                    &${rtx_ether_ctx.device},
-+                    ${rtx_ether_ctx.device},
-                     hw_ctx->tx_ring.size,
-                     &hw_ctx->tx_ring.dma_base,
-                     GFP_KERNEL);
-@@ -928,15 +863,16 @@
-             while (i--)
-             {
-                 dma_unmap_single(
--                        &${rtx_ether_ctx.device},
-+                        ${rtx_ether_ctx.device},
-                         hw_ctx->rx_ring.skbuffs[i].dma_handle,
-                         ${config.rx_buffer_len},
-                         DMA_FROM_DEVICE);
-         err_skbuffs_map:
--                dev_kfree_skb(&hw_ctx->rx_ring.skbuffs[i].skbuff->data);
-+                /* XXX leaking cast: */
-+                dev_kfree_skb((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff);
-             }
- 
--            dma_free_coherent(&${rtx_ether_ctx.device}, hw_ctx->rx_ring.size,
-+            dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx->rx_ring.size,
-                     hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base);
-         err_rx_ring_alloc:
-             return -ENOMEM;
-@@ -954,8 +890,13 @@
-     {
-         chunk   ::CALL()
-         {
--            ${e1000::Context} *hw_ctx;
--            hw_ctx = &${rtx_ether_ctx}->hw_ctx;
-+            /*
-+             * XXX: Not generated if named "hw_ctx" (which is funny because
-+             * it's used and works in the template right above this one):
-+             */
-+            ${e1000::Context} *hw_ctx_;
-+            ${cast local.hw_ctx_ as e1000::Context};
-+            hw_ctx_ = &${rtx_ether_ctx}->hw_ctx;
- 
-             /*
-              * Free the rx ring:
-@@ -965,22 +906,23 @@
-             for (int i = 0; i != ${config.rx_ring_size}; ++i)
-             {
-                 dma_unmap_single(
--                        &${rtx_ether_ctx.device},
--                        (dma_addr_t)hw_ctx->rx_ring.skbuffs[i].dma_handle,
-+                        ${rtx_ether_ctx.device},
-+                        (dma_addr_t)hw_ctx_->rx_ring.skbuffs[i].dma_handle,
-                         ${config.rx_buffer_len},
-                         DMA_FROM_DEVICE);
--                dev_kfree_skb(&hw_ctx->rx_ring.skbuffs[i].skbuff->data);
-+                /* XXX Go through the rtx types (Socket::SKBuff, AbstractSKBuff) */
-+                dev_kfree_skb(hw_ctx_->rx_ring.skbuffs[i].skbuff);
-             }
--            dma_free_coherent(&${rtx_ether_ctx.device}, hw_ctx->rx_ring.size,
--                    hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base);
-+            dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx_->rx_ring.size,
-+                    hw_ctx_->rx_ring.base, hw_ctx_->rx_ring.dma_base);
-             ${Log::info("free_rx_tx: rx ring free'ed")};
- 
-             /*
-              * Free the tx ring:
-              * - Free the descriptors array.
-              */
--            dma_free_coherent(&${rtx_ether_ctx.device}, hw_ctx->tx_ring.size,
--                    hw_ctx->tx_ring.base, hw_ctx->tx_ring.dma_base);
-+            dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx_->tx_ring.size,
-+                    hw_ctx_->tx_ring.base, hw_ctx_->tx_ring.dma_base);
-             ${Log::info("free_rx_tx: tx ring free'ed")};
-         }
-     }
-@@ -1038,13 +980,13 @@
-             ${local.skb.init(kernel_skb)};
-             hw_ctx = &${rtx_ether_ctx}->hw_ctx;
-             tx_ring = &hw_ctx->tx_ring;
--            devp = (${Device::AbstractDevice}*) &${rtx_ether_ctx.device};
-+            devp = (${Device::AbstractDevice}*)${rtx_ether_ctx.device};
- 
-             ${Log::info("xmit: skbuff details:")};
-             /*
--             * skb is not expand on the bound C variable (should be rtx_skbuff),
--             * which is funny because it works for the sequence template call
--             * right after.
-+             * skb does not expand on the bound C variable (should be
-+             * rtx_skbuff), which is funny because it works for the
-+             * sequence template call right after.
-              */
-             /*
-              * XXX: doesn't work (I tried to pass self explicitely too):
-@@ -1077,8 +1019,8 @@
- 
-             /* 2. Map the data */
- 
--            /* XXX: ${local.skb.map_to(local.devp)}; */
--            if (rtx_socket_skbuff_map(&skb, &${devp.data}, DMA_TO_DEVICE))
-+            /* XXX: ${local.skb.map_to(devp.k_device)}; */
-+            if (rtx_socket_skbuff_map(&skb, ${devp.k_device}, DMA_TO_DEVICE))
-             {
-                 ${Log::info("xmit: can't DMA map a SKbuff")};
-                 goto err_skb_map_to;
-@@ -1097,7 +1039,7 @@
-         err_offload:
-         err_skb_map_to:
-             /* XXX: ${local.skb.unmap_to_and_free(local.dev)}; */
--            rtx_socket_skbuff_unmap_and_free(&skb, &${devp.data}, DMA_TO_DEVICE);
-+            rtx_socket_skbuff_unmap_and_free(&skb, ${devp.k_device}, DMA_TO_DEVICE);
-             return NETDEV_TX_OK;
-         }
-     }
-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
-@@ -13,8 +13,7 @@
-         /* Callbacks/Hooks which should probably be in the front-end: */
-         chunk       Ethernet::adapter_init_context(Ethernet::Device,
-                                                    Builtin::number,
--                                                   Builtin::symbol,
--                                                   Builtin::number);
-+                                                   Builtin::symbol);
-         chunk       Ethernet::adapter_reset(Ethernet::Device);
-         chunk       Ethernet::adapter_load_mac_address(Ethernet::Device);
-     }
-@@ -85,21 +84,6 @@
-         provided chunk  ::CALL();
-     }
- 
--    provided sequence   setup_interrupt_handler(Ethernet::Device)
--    {
--        provided chunk  LKM::includes(); // works without this one
--        provided chunk  LKM::prototypes();
--        provided chunk  LKM::code();
--        provided chunk  ::CALL();
--    }
--
--    provided sequence   free_interrupt_handler(Ethernet::Device)
--    {
--        provided chunk  LKM::prototypes();
--        provided chunk  LKM::code();
--        provided chunk  ::CALL();
--    }
--
-     provided sequence   activate_device_interruption(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
-@@ -1,4 +1,4 @@
--with Ethernet, PCI, LKM, Log
-+with Ethernet, PCI, LKM, Log, Builtin
- {
-     template type   Ethernet::ProtocolId()
-     {
-@@ -51,7 +51,7 @@
-     {
-         decl  data_types()
-         {
--            struct net_device ndev;
-+            struct net_device   data;
-         }
- 
-         chunk LKM::includes()
-@@ -59,9 +59,15 @@
-             #include <linux/netdevice.h>
-         }
- 
-+        method  init(Builtin::symbol dev)
-+        {
-+            ${self} = (${Ethernet::AbstractDevice} *)${dev};
-+        }
-+
-         map
-         {
--            netdev:   ${self}->ndev;
-+            k_net_dev: ((struct net_device *)${self});
-+            rtx_ether_ctx: netdev_priv((struct net_device *)${self});
-         }
-     }
- 
-@@ -88,29 +94,43 @@
-             #include <linux/etherdevice.h>
-         }
- 
--        method init(Ethernet::AbstractDevice net_dev, PCI::AbstractDevice pci_dev)
-+        /* XXX: if the first arg is not called rtx_net_dev, it breaks. */
-+        method init(Ethernet::AbstractDevice rtx_net_dev, PCI::AbstractDevice pci_dev)
-         {
--            ${self} = netdev_priv(&${net_dev.netdev});
-+            ${self} = ${rtx_net_dev.rtx_ether_ctx}; 
-             /*
-              * We can use -> because we know that ${self} will be always a
-              * pointer, but the ambiguity sucks.
-              */
-             ${self}->pci_dev = ${pci_dev};
--            ${self}->net_dev = ${net_dev};
-+            ${self}->net_dev = ${rtx_net_dev};
-         }
- 
-         map
-         {
--            device: ${self}->pci_dev->data.dev;
-+            /*
-+             * XXX: I'd like to be able to do things like:
-+             * device: ${self.pci_dev.k_pci_dev}->dev;
-+             *
-+             * Also, using ${PCI::AbstractDevice} instead of directly struct
-+             * pci_dev doesn't work.
-+             */
-+            device: (&((struct pci_dev *)(${self})->pci_dev)->dev);
-             pci_device: ${self}->pci_dev;
-             net_device: ${self}->net_dev;
--            perm_addr: ${self}->net_dev->ndev.perm_addr;
--            dev_addr: ${self}->net_dev->ndev.dev_addr;
-+            perm_addr: ((struct net_device *)(${self})->net_dev)->perm_addr;
-+            dev_addr: ((struct net_device *)(${self})->net_dev)->dev_addr;
-+            irq: ((struct pci_dev *)(${self})->pci_dev)->irq;
-         }
-     }
- 
-     template sequence   Ethernet::open(Ethernet::Device dev)
-     {
-+        chunk   LKM::includes()
-+        {
-+            #include <linux/interrupt.h>
-+        }
-+
-         chunk LKM::prototypes()
-         {
-             static int  rtx_ethernet_open(struct net_device *);
-@@ -120,12 +140,40 @@
-         {
-             static int  rtx_ethernet_open(struct net_device *dev)
-             {
--                ${Ethernet::Device} *rtx_ether_ctx = netdev_priv(dev);
-+                /*
-+                 * XXX The casts are here because the compiler doesn't resolve
-+                 * "enclosed" type (e.g: local.var.enclosed) correctly.
-+                 */
-+                ${Ethernet::AbstractDevice} *rtx_net_dev;
-+                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
-+                { /* XXX: I end up with a placeholder if I don't open a scope */
-+                    ${local.rtx_net_dev.init(local.dev)};
-+                }
- 
-+                ${Ethernet::Device} *rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
-                 ${cast local.rtx_ether_ctx as Ethernet::Device};
-+
-+                int error;
-+                {
-+                    ${Log::info("installing the interrupt handler")};
-+                }
-+                error = request_irq(${local.rtx_ether_ctx.irq},
-+                                    rtx_ethernet_interrupt_handler,
-+                                    IRQF_SHARED,
-+                                    ${config.name},
-+                                    ${local.rtx_net_dev.k_net_dev});
-+                if (error)
-+                {
-+                    ${Log::info("Cannot register the interrupt handler")};
-+                    goto error;
-+                }
-+
-                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
- 
-                 return 0;
-+
-+            error:
-+                return error;
-             }
-         }
-     }
-@@ -162,10 +210,24 @@
-         {
-             static int  rtx_ethernet_close(struct net_device *dev)
-             {
--                ${Ethernet::Device} *rtx_ether_ctx = netdev_priv(dev);
-+                ${Ethernet::AbstractDevice} *rtx_net_dev;
-+                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
-+                { /* XXX: I end up with a placeholder if I don't open a scope */
-+                    ${local.rtx_net_dev.init(local.dev)};
-+                }
- 
-+                ${Ethernet::Device} *rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
-                 ${cast local.rtx_ether_ctx as Ethernet::Device};
--                ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
-+
-+                /* TODO: change this pointcut into a pointcut/adapter/callback: */
-+                {
-+                    ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
-+                }
-+
-+                free_irq(${local.rtx_ether_ctx.irq}, ${local.rtx_net_dev.k_net_dev});
-+                {
-+                    ${Log::info("interrupt handler free'ed")};
-+                }
- 
-                 return 0;
-             }
-@@ -187,9 +249,13 @@
-         {
-             static enum irqreturn   rtx_ethernet_interrupt_handler(int irq, void *dev_id)
-             {
--                ${Ethernet::Device} *rtx_ether_ctx = dev_id;
-+                ${Ethernet::AbstractDevice} *rtx_net_dev = dev_id;
-+                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
- 
-+                ${Ethernet::Device} *rtx_ether_ctx;
-                 ${cast local.rtx_ether_ctx as Ethernet::Device};
-+                rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
-+
-                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
- 
-                 return IRQ_NONE;
-@@ -219,23 +285,26 @@
-          */
-         chunk PCI::pci_probe_hook(PCI::Device rtx_pci_dev)
-         {
-+            ${Ethernet::AbstractDevice} *rtx_net_dev;
-             ${Ethernet::Device} *rtx_ether_ctx;
--            ${Ethernet::AbstractDevice} *net_dev;
--            ${cast local.net_dev as Ethernet::AbstractDevice};
-+            ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
- 
--            net_dev = (${Ethernet::AbstractDevice}*) alloc_etherdev(sizeof(*rtx_ether_ctx));
--            if (!net_dev)
-+            /* Cast the result back into our "transparent wrapper" type */
-+            rtx_net_dev = (${Ethernet::AbstractDevice}*)alloc_etherdev(sizeof(*rtx_ether_ctx));
-+            if (!rtx_net_dev)
-             {
-                 ${Log::info("cannot allocate the ethernet device context")};
-                 error = -ENOMEM;
-                 goto fail;
-             }
--            SET_NETDEV_DEV(&${local.net_dev.netdev}, ${rtx_pci_dev.device});
--            strlcpy(${local.net_dev.netdev}.name, ${config.ifname}, sizeof(${local.net_dev.netdev}.name));
--            ${local.net_dev.netdev}.irq = ${rtx_pci_dev.irq};
--            ${local.net_dev.netdev}.netdev_ops = &rtx_ether_ops;
-+            SET_NETDEV_DEV(${local.rtx_net_dev.k_net_dev}, ${rtx_pci_dev.device});
-+            strlcpy(${local.rtx_net_dev.k_net_dev}->name,
-+                    ${config.ifname},
-+                    sizeof(${local.rtx_net_dev.k_net_dev}->name));
-+            ${local.rtx_net_dev.k_net_dev}->irq = ${rtx_pci_dev.irq};
-+            ${local.rtx_net_dev.k_net_dev}->netdev_ops = &rtx_ether_ops;
- 
--            error = register_netdev(&${local.net_dev.netdev});
-+            error = register_netdev(${local.rtx_net_dev.k_net_dev});
-             if (error)
-             {
-                 ${Log::info("cannot register the driver in the net subsystem")};
-@@ -247,14 +316,11 @@
-              * XXX: the cast is here because the compiler resolve the
-              * type of rtx_pci_dev.pci_device to the type of
-              * rtx_pci_dev instead of the type of rtx_pci_dev.pci_device.
--             *
--             * Also, I'm getting placeholder in the generated code if
--             * I don't open a scope here.
-              */
--            {
--                ${PCI::AbstractDevice} *rtx_pdev = ${rtx_pci_dev.pci_device};
--                ${cast local.rtx_pdev as PCI::AbstractDevice};
--                ${local.rtx_ether_ctx.init(local.net_dev, local.rtx_pdev)};
-+            ${PCI::AbstractDevice} *workaround = ${rtx_pci_dev.pci_device};
-+            ${cast local.workaround as PCI::AbstractDevice};
-+            { /* XXX: I end up with a placeholder if I don't open a scope */
-+                ${local.rtx_ether_ctx.init(local.rtx_net_dev, local.workaround)};
-             }
- 
-             /* Register ourselves in the parent context: */
-@@ -267,19 +333,16 @@
-              */
-             int bars = ${rtx_pci_dev.bars};
-             unsigned char /* __iomem */ *ioaddr = ${rtx_pci_dev.ioaddr};
--            int irq = ${rtx_pci_dev.irq};
-             ${cast local.bars as Builtin::number};
--            ${cast local.irq as Builtin::number};
-             ${cast local.rtx_ether_ctx as Ethernet::Device};
-             ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx,
-                                                       local.bars,
--                                                      local.ioaddr,
--                                                      local.irq)};
-+                                                      local.ioaddr)};
-             ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)};
-             ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)};
-             memcpy(${local.rtx_ether_ctx.perm_addr},
-                    ${local.rtx_ether_ctx.dev_addr},
--                   ${local.net_dev.netdev}.addr_len);
-+                   ${local.rtx_net_dev.k_net_dev}->addr_len);
-         }
- 
-         /* This chunk should be removed (see #26) */
-@@ -296,15 +359,15 @@
-          */
-         chunk   PCI::pci_remove_hook(PCI::Device rtx_pci_dev)
-         {
--            ${Ethernet::Device} *rtx_ether_ctx = ${rtx_pci_dev.context};
--            ${Ethernet::AbstractDevice} *rtx_ether_dev = (${Ethernet::AbstractDevice}*) ${local.rtx_ether_ctx.net_device};
--
-+            ${Ethernet::Device} *rtx_ether_ctx = ${rtx_pci_dev.rtx_drv_context};
-+            ${cast local.rtx_ether_ctx as Ethernet::Device}; /* XXX */
-             BUG_ON(!rtx_ether_ctx);
- 
--            ${cast local.rtx_ether_ctx as Ethernet::Device};
--            ${cast local.rtx_ether_dev as Ethernet::AbstractDevice};
--            unregister_netdev(&${local.rtx_ether_dev.netdev});
--            free_netdev(&${local.rtx_ether_dev.netdev});
-+            ${Ethernet::AbstractDevice} *rtx_net_dev = ${local.rtx_ether_ctx.net_device};
-+            ${cast local.rtx_net_dev as Ethernet::AbstractDevice}; /* XXX */
-+
-+            unregister_netdev(${local.rtx_net_dev.k_net_dev});
-+            free_netdev(${local.rtx_net_dev.k_net_dev});
-         }
- 
-         /* This chunk should be removed (see #26) */
-diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti
---- a/rathaxes/samples/e1000/ethernet.rti
-+++ b/rathaxes/samples/e1000/ethernet.rti
-@@ -16,8 +16,15 @@
-     provided type   AbstractDevice
-     {
-         chunk       LKM::includes();
-+        method      init(Builtin::symbol);
-         decl        data_types();
--        attribute   Builtin::symbol netdev;
-+
-+        attribute   Builtin::symbol k_net_dev;
-+        /*
-+         * XXX: should be a Ethernet::Device, but that causes a circular
-+         * dependency.
-+         */
-+        attribute   Builtin::symbol rtx_ether_ctx;
-     }
- 
-     provided type   Device
-@@ -34,12 +41,14 @@
-          * I'd like to use better names here, but I'd like to understand the
-          * difference between the two first:
-          */
--        attribute   Builtin::symbol             perm_addr;
--        attribute   Builtin::symbol             dev_addr;
-+        attribute   Builtin::symbol perm_addr;
-+        attribute   Builtin::symbol dev_addr;
-+        attribute   Builtin::symbol irq;
-     }
- 
-     required sequence   open(Ethernet::Device)
-     {
-+        provided chunk  LKM::includes();
-         provided chunk  LKM::prototypes();
-         provided chunk  LKM::code();
-     }
-@@ -69,8 +78,7 @@
- 
-         provided pointcut   Ethernet::adapter_init_context(Ethernet::Device,
-                                                            Builtin::number,
--                                                           Builtin::symbol,
--                                                           Builtin::number);
-+                                                           Builtin::symbol);
-         provided pointcut   Ethernet::adapter_reset(Ethernet::Device);
-         provided pointcut   Ethernet::adapter_load_mac_address(Ethernet::Device);
-     }
-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
-@@ -4,13 +4,6 @@
-     {
-         Log::info("opening the device");
- 
--        /*
--         * Maybe e1000::create_device should be called from here, to be
--         * more coherent.
--         */
--
--        e1000::setup_interrupt_handler(dev);
--        Log::info("interrupt handler installed");
- 
-         e1000::set_up_device(dev);
-         Log::info("device activated");
-@@ -32,9 +25,6 @@
-          */
-         e1000::free_rx_tx(dev);
-         Log::info("free'ed up rx/tx resources");
--
--        e1000::free_interrupt_handler(dev);
--        Log::info("interrupt handler free'ed");
-     }
- 
-     Ethernet::interrupt_handler(Ethernet::Device dev)
-diff --git a/rathaxes/samples/e1000/pci.blt b/rathaxes/samples/e1000/pci.blt
---- a/rathaxes/samples/e1000/pci.blt
-+++ b/rathaxes/samples/e1000/pci.blt
-@@ -16,15 +16,15 @@
-         {
-         }
- 
--        method  set_context(Builtin::symbol ctx)
-+        method  set_rtx_context(Builtin::symbol ctx)
-         {
--            pci_set_drvdata(&${self}->data, ${ctx});
-+            pci_set_drvdata(${self.k_pci_dev}, ${ctx});
-         }
- 
-         map
-         {
--            data: ${self}->data;
--            drv_data: pci_get_drvdata(&${self}->data);
-+            k_pci_dev: ((struct pci_dev *)${self});
-+            rtx_pci_ctx: pci_get_drvdata((struct pci_dev *)${self});
-         }
-     }
- 
-@@ -52,13 +52,13 @@
-                 int error;
-                 ${PCI::AbstractDevice}  *enable_pdev = self->pdev;
-                 ${cast local.enable_pdev as PCI::AbstractDevice};
--                error = pci_enable_device(&${local.enable_pdev.data});
-+                error = pci_enable_device(${local.enable_pdev.k_pci_dev});
-                 if (error)
-                     return error;
--                error = pci_request_selected_regions(&${local.enable_pdev.data}, self->bars, ${config.name});
-+                error = pci_request_selected_regions(${local.enable_pdev.k_pci_dev}, self->bars, ${config.name});
-                 if (error)
-                     return error;
--                pci_set_master(&${local.enable_pdev.data});
-+                pci_set_master(${local.enable_pdev.k_pci_dev});
-                 return 0;
-             }
- 
-@@ -68,8 +68,8 @@
-                 ${cast local.disable_pdev as PCI::AbstractDevice};
-                 if (self->ioaddr)
-                     iounmap(self->ioaddr);
--                pci_release_selected_regions(&${local.disable_pdev.data}, self->bars);
--                pci_disable_device(&${local.disable_pdev.data});
-+                pci_release_selected_regions(${local.disable_pdev.k_pci_dev}, self->bars);
-+                pci_disable_device(${local.disable_pdev.k_pci_dev});
-             }
-         }
- 
-@@ -78,7 +78,7 @@
-             ${PCI::AbstractDevice} * workaround = (${PCI::AbstractDevice}*)pdev;
-             ${cast local.workaround as PCI::AbstractDevice};
-             ${self}->pdev = ${pdev};
--            ${self}->bars = pci_select_bars(&${local.workaround.data}, IORESOURCE_MEM);
-+            ${self}->bars = pci_select_bars(${local.workaround.k_pci_dev}, IORESOURCE_MEM);
-             ${self}->ioaddr = NULL;
-             ${self}->context = NULL;
-         }
-@@ -97,20 +97,20 @@
-         {
-             ${PCI::AbstractDevice} *select_ioaddr_pdev = ${self}->pdev;
-             ${cast local.select_ioaddr_pdev as PCI::AbstractDevice};
--            ${self}->ioaddr = pci_ioremap_bar(&${local.select_ioaddr_pdev.data}, ${bar});
-+            ${self}->ioaddr = pci_ioremap_bar(${local.select_ioaddr_pdev.k_pci_dev}, ${bar});
-         }
- 
--        method  set_context(Builtin::symbol ctx)
-+        method  set_rtx_drv_context(Builtin::symbol ctx)
-         {
-             ${self}->context = ctx;
-         }
- 
-         map
-         {
--            context: ${self}->context;
--            device: &${self}->pdev->data.dev;
-+            rtx_drv_context: ${self}->context;
-+            device: &((struct pci_dev *)(${self})->pdev)->dev;
-             pci_device: ${self}->pdev;
--            irq: ${self}->pdev->data.irq;
-+            irq: ((struct pci_dev *)(${self})->pdev)->irq;
-             bars: ${self}->bars;
-             ioaddr: ${self}->ioaddr;
-             BAR_0: 0;
-@@ -151,7 +151,7 @@
-                     ${local.rtx_pci_dev.init(local.rtx_pdev)};
-                 }
- 
--                /* ${local.pdev.set_context(local.rtx_pci_dev)}; */
-+                /* ${local.pdev.set_rtx_context(local.rtx_pci_dev)}; */
-                 pci_set_drvdata(pdev, rtx_pci_dev);
- 
-                 /* ${local.rtx_pci_dev.enable()}; */
-@@ -184,7 +184,7 @@
-                 return 0;
- 
-             fail:
--                /* ${local.pdev.set_context(NULL)}; */
-+                /* ${local.pdev.set_rtx_drv_context(NULL)}; */
-                 pci_set_drvdata(pdev, NULL);
-                 kfree(rtx_pci_dev);
-                 return error;
-@@ -210,7 +210,7 @@
-             {
-                 ${PCI::AbstractDevice}  *rtx_pdev = (${PCI::AbstractDevice}*)pdev;
-                 ${cast local.rtx_pdev as PCI::AbstractDevice};
--                ${PCI::Device} *rtx_pci_dev = ${rtx_pdev.drv_data};
-+                ${PCI::Device} *rtx_pci_dev = ${rtx_pdev.rtx_pci_ctx};
- 
-                 BUG_ON(!rtx_pci_dev);
- 
-diff --git a/rathaxes/samples/e1000/pci.rti b/rathaxes/samples/e1000/pci.rti
---- a/rathaxes/samples/e1000/pci.rti
-+++ b/rathaxes/samples/e1000/pci.rti
-@@ -10,10 +10,15 @@
- 
-         chunk       LKM::includes();
-         method      init(PCI::AbstractDevice);
--        method      set_context(Builtin::symbol);
-+        /*
-+         * XXX: the argument should be a PCI::Device but that causes a circular
-+         * dependency:
-+         */
-+        method      set_rtx_context(Builtin::symbol);
- 
--        attribute   Builtin::symbol data;
--        attribute   Builtin::symbol drv_data;
-+        attribute   Builtin::symbol k_pci_dev;
-+        /* XXX: should be PCI::Device (see above point) */
-+        attribute   Builtin::symbol rtx_pci_ctx;
-     }
- 
-     provided type   PCI::Device
-@@ -27,9 +32,9 @@
-         method      enable();
-         method      disable();
-         method      select_ioaddr(Builtin::number);
--        method      set_context(Builtin::symbol);
-+        method      set_rtx_drv_context(Builtin::symbol);
- 
--        attribute   Builtin::symbol         context;
-+        attribute   Builtin::symbol         rtx_drv_context;
-         attribute   Device::AbstractDevice  device;
-         attribute   PCI::AbstractDevice     pci_device;
-         attribute   Builtin::symbol         ioaddr;
-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
-@@ -14,7 +14,7 @@
- 
-         map
-         {
--            data: ${self}->data;
-+            k_sk_buff: ((struct sk_buff *)${self});
-         }
-     }
- 
-@@ -46,11 +46,12 @@
-                  */
-                 ${Socket::AbstractSKBuff}   *skb = self->skbuff;
-                 ${cast local.skb as Socket::AbstractSKBuff};
--                ${Ethernet::ProtocolId} ethernet_proto = { .id = be16_to_cpu(${local.skb.data}.protocol) };
-+                ${Ethernet::ProtocolId} ethernet_proto = { .id = be16_to_cpu(${local.skb.k_sk_buff}->protocol) };
-+
-                 static const char * const ip_summed_values[] = {
-                     "none", "unnecessary", "complete", "partial"
-                 };
--                struct skb_shared_info *shinfo = skb_shinfo(&${local.skb.data});
-+                struct skb_shared_info *shinfo = skb_shinfo(${local.skb.k_sk_buff});
- 
-                 pr_info(
-                         "\t protocol = %#-5x (%s) ip_summed = %d (%s)\n"
-@@ -59,8 +60,8 @@
-                         "\t gso_size = %-5u gso_segs = %-5u gso_type = %-5u",
-                         /* XXX: can't use ${local.ethernet_proto.id} here (issue #52): */
-                         ethernet_proto.id, ${local.ethernet_proto.str},
--                        ${local.skb.data}.ip_summed, ip_summed_values[${local.skb.data}.ip_summed],
--                        ${local.skb.data}.len, ${local.skb.data}.data_len, skb_headlen(&${local.skb.data}),
-+                        ${local.skb.k_sk_buff}->ip_summed, ip_summed_values[${local.skb.k_sk_buff}->ip_summed],
-+                        ${local.skb.k_sk_buff}->len, ${local.skb.k_sk_buff}->data_len, skb_headlen(${local.skb.k_sk_buff}),
-                         shinfo->nr_frags, shinfo->gso_size, shinfo->gso_segs, shinfo->gso_type
-                 );
-             }
-@@ -72,14 +73,13 @@
-                 ${Socket::AbstractSKBuff}   *skb = self->skbuff;
-                 ${cast local.skb as Socket::AbstractSKBuff};
- 
--                WARN_ON(!skb);
--                WARN_ON(!${local.skb.data}.data);
-+                WARN_ON(!${local.skb.k_sk_buff});
-                 WARN_ON(self->dma_handle);
- 
-                 self->dma_handle = dma_map_single(
-                         dev,
--                        &${local.skb.data}.data,
--                        skb_headlen(&${local.skb.data}),
-+                        ${local.skb.k_sk_buff},
-+                        skb_headlen(${local.skb.k_sk_buff}),
-                         direction);
-                 int err = dma_mapping_error(dev, self->dma_handle);
-                 if (err)
-@@ -97,18 +97,17 @@
-                 ${Socket::AbstractSKBuff}   *skb = self->skbuff;
-                 ${cast local.skb as Socket::AbstractSKBuff};
- 
--                WARN_ON(!${local.skb});
--                WARN_ON(!${local.skb.data}.data);
-+                WARN_ON(!${local.skb.k_sk_buff});
- 
-                 if (self->dma_handle)
-                 {
-                     dma_unmap_single(dev,
-                             self->dma_handle,
--                            skb_headlen(&${local.skb.data}),
-+                            skb_headlen(${local.skb.k_sk_buff}),
-                             direction);
-                     self->dma_handle = 0;
-                 }
--                dev_kfree_skb_any(&${local.skb.data});
-+                dev_kfree_skb_any(${local.skb.k_sk_buff});
-                 self->skbuff = 0;
-             }
-         }
-@@ -131,22 +130,22 @@
- 
-         method   map_to(Device::AbstractDevice dev)
-         {
--            rtx_socket_skbuff_map(${self}, &${dev.data}, DMA_TO_DEVICE);
-+            rtx_socket_skbuff_map(${self}, ${dev.k_device}, DMA_TO_DEVICE);
-         }
- 
-         method   map_from(Device::AbstractDevice dev)
-         {
--            rtx_socket_skbuff_map(${self}, &${dev.data}, DMA_FROM_DEVICE);
-+            rtx_socket_skbuff_map(${self}, ${dev.k_device}, DMA_FROM_DEVICE);
-         }
- 
-         method   unmap_to_and_free(Device::AbstractDevice dev)
-         {
--            rtx_socket_skbuff_unmap_and_free(${self}, &${dev.data}, DMA_TO_DEVICE);
-+            rtx_socket_skbuff_unmap_and_free(${self}, ${dev.k_device}, DMA_TO_DEVICE);
-         }
- 
-         method   unmap_from_and_free(Device::AbstractDevice dev)
-         {
--            rtx_socket_skbuff_unmap_and_free(${self}, &${dev.data}, DMA_FROM_DEVICE);
-+            rtx_socket_skbuff_unmap_and_free(${self}, ${dev.k_device}, DMA_FROM_DEVICE);
-         }
- 
-         map
-diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti
---- a/rathaxes/samples/e1000/socket.rti
-+++ b/rathaxes/samples/e1000/socket.rti
-@@ -5,7 +5,8 @@
-     {
-         chunk       LKM::includes();
-         decl        data_types();
--        attribute   Builtin::symbol data;
-+
-+        attribute   Builtin::symbol k_sk_buff;
-     }
- 
-     provided type   SKBuff
--- a/series	Tue Mar 19 23:16:02 2013 -0700
+++ b/series	Fri Mar 22 00:06:00 2013 -0700
@@ -1,2 +1,3 @@
 maintainers_fix_indentation_in_use_rathaxes.patch
-rathaxes_trying_to_fix_the_abstract_type_nightmare_in_e1000.patch
+rathaxes_e1000_move_the_interrupt_init_and_cleanup_into_ethernet.patch
+rathaxes_change_the_abstract_type_notation_in_the_e1000_sample.patch