diff E1000_UpdateToScalarRef @ 106:976a4b87803f

Fix the resolution and the e1000 sample with the new scalar ref feature
author David Pineau <dav.pineau@gmail.com>
date Mon, 25 Mar 2013 01:17:56 +0100
parents
children 7efe3212db3a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/E1000_UpdateToScalarRef	Mon Mar 25 01:17:56 2013 +0100
@@ -0,0 +1,600 @@
+# HG changeset patch
+# Parent 9e6d855c6c477852924e13d354686f18d2036a0e
+Update the e1000 sample with the new features
+
+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
+@@ -87,7 +87,7 @@
+         decl    data_types()
+         {
+             unsigned int                    size;
+-            ${e1000::RxDescriptor}          *base;
++            ${e1000::RxDescriptor.ref}      base;
+             dma_addr_t                      dma_base;
+             ${Socket::SKBuff}               skbuffs[${config.rx_ring_size}];
+         }
+@@ -124,7 +124,7 @@
+         {
+             unsigned int                    size;
+             /* XXX: can't use ${e1000::TxDescriptor} here: */
+-            ${e1000::TxDescriptor}          *base; /* rename to descs */
++            ${e1000::TxDescriptor.ref}      base; /* rename to descs */
+             dma_addr_t                      dma_base;
+             ${Socket::SKBuff}               skbuffs[${config.tx_ring_size}];
+             unsigned short                  head;
+@@ -133,20 +133,20 @@
+ 
+         chunk   LKM::prototypes()
+         {
+-            static void         rtx_e1000_tx_ring_clean(${e1000::TxRing} *);
+-            static unsigned int rtx_e1000_tx_ring_descriptors_remaining(${e1000::TxRing} *);
+-            static int          rtx_e1000_tx_ring_tso_cksum_offload(${e1000::TxRing} *, ${Socket::SKBuff} *);
+-            static void         rtx_e1000_tx_ring_put(${e1000::TxRing} *, ${Socket::SKBuff} *);
++            static void         rtx_e1000_tx_ring_clean(${e1000::TxRing.ref});
++            static unsigned int rtx_e1000_tx_ring_descriptors_remaining(${e1000::TxRing.ref});
++            static int          rtx_e1000_tx_ring_tso_cksum_offload(${e1000::TxRing.ref}, ${Socket::SKBuff.ref});
++            static void         rtx_e1000_tx_ring_put(${e1000::TxRing.ref}, ${Socket::SKBuff.ref});
+             /* FIXME: See issue #54 */
+-            static void         rtx_e1000_tx_ring_start_xmit(${e1000::TxRing} *, /*const*/ ${e1000::Context} *);
++            static void         rtx_e1000_tx_ring_start_xmit(${e1000::TxRing.ref}, /*const*/ ${e1000::Context.ref});
+         }
+ 
+         chunk   LKM::code()
+         {
+-            static void         rtx_e1000_tx_ring_clean(${e1000::TxRing} *self)
++            static void         rtx_e1000_tx_ring_clean(${e1000::TxRing.ref} self)
+             {
+-                ${e1000::TxDescriptor}  *tx_desc;
+-                bool                    done;
++                ${e1000::TxDescriptor.ref}  tx_desc;
++                bool                        done;
+ 
+                 for (; self->head != self->tail; self->head++)
+                 {
+@@ -159,7 +159,7 @@
+                 pr_info("%s: tx_ring_clean: moving head to %d/%d", ${config.name}, self->head, ${config.tx_ring_size});
+             }
+ 
+-            static unsigned int rtx_e1000_tx_ring_descriptors_remaining(${e1000::TxRing} *self)
++            static unsigned int rtx_e1000_tx_ring_descriptors_remaining(${e1000::TxRing.ref} self)
+             {
+                 if (self->tail == self->head) /* ring is empty */
+                     return 256; /* XXX: ${config.tx_ring_size}; */
+@@ -169,19 +169,17 @@
+                 return self->head - self->tail;
+             }
+ 
+-            static int          rtx_e1000_tx_ring_tso_cksum_offload(${e1000::TxRing} *self, ${Socket::SKBuff} *skb)
++            static int          rtx_e1000_tx_ring_tso_cksum_offload(${e1000::TxRing.ref} self, ${Socket::SKBuff.ref} 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};
++                ${Socket::AbstractSKBuff.ref} k_skb = skb->skbuff;
+                 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)
++            static void         rtx_e1000_tx_ring_put(${e1000::TxRing.ref} self, ${Socket::SKBuff.ref} 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};
++                ${Socket::AbstractSKBuff.ref} k_skb = skb->skbuff;
+                 WARN_ON(!skb);
+ 
+                 /*
+@@ -192,7 +190,7 @@
+                  * code shouldn't be aware of it and use something more
+                  * abstract.
+                  */
+-                ${e1000::TxDescriptor} *tx_desc = &self->base[self->tail];
++                ${e1000::TxDescriptor.ref} tx_desc = &self->base[self->tail];
+                 tx_desc->lower.data = cpu_to_le32(
+                         E1000_TXD_CMD_EOP  |
+                         E1000_TXD_CMD_IFCS |
+@@ -205,7 +203,7 @@
+             }
+ 
+             /* FIXME: See issue #54 */
+-            static void         rtx_e1000_tx_ring_start_xmit(${e1000::TxRing} *self, /*const*/ ${e1000::Context} *hw_ctx)
++            static void         rtx_e1000_tx_ring_start_xmit(${e1000::TxRing.ref} self, /*const*/ ${e1000::Context.ref} hw_ctx)
+             {
+                 pr_info("%s: start_xmit: moving tail to %d/%d", ${config.name}, self->tail, ${config.tx_ring_size});
+                 rtx_e1000_register_write32(hw_ctx, E1000_TDT, self->tail);
+@@ -271,7 +269,7 @@
+                                                Builtin::symbol ioaddr)
+         {
+             {
+-                ${e1000::Context} *hw_ctx = &${rtx_ether_ctx}->hw_ctx;
++                ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx;
+                 hw_ctx->bars = ${bars};
+                 hw_ctx->ioaddr = ${ioaddr};
+             }
+@@ -280,8 +278,9 @@
+         chunk   Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx)
+         {
+             {
+-                ${e1000::Context} *hw_ctx = &${rtx_ether_ctx}->hw_ctx;
+-                rtx_e1000_register_write32(hw_ctx, E1000_CTRL, E1000_CMD_RST);
++                /* XXX Naming this variable 'hw_ctx' kicks the decl out of the generated code */
++                ${e1000::Context.ref} tmp_hw_ctx = &${rtx_ether_ctx}->hw_ctx;
++                rtx_e1000_register_write32(tmp_hw_ctx, E1000_CTRL, E1000_CMD_RST);
+                 udelay(10);
+             }
+         }
+@@ -289,7 +288,7 @@
+         chunk   Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx)
+         {
+             {
+-                ${e1000::Context} *hw_ctx = &${rtx_ether_ctx}->hw_ctx;
++                ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx;
+                 /* Shamelessly borrowed from Minix */
+                 for (int i = 0; i < 3; ++i)
+                 {
+@@ -468,12 +467,12 @@
+     {
+         chunk   LKM::prototypes()
+         {
+-            static void rtx_e1000_print_status(${e1000::Context} *);
++            static void rtx_e1000_print_status(${e1000::Context.ref});
+         }
+ 
+         chunk   LKM::code()
+         {
+-            static void rtx_e1000_print_status(${e1000::Context} *hw_ctx)
++            static void rtx_e1000_print_status(${e1000::Context.ref} hw_ctx)
+             {
+                 unsigned int status = rtx_e1000_register_read32(hw_ctx, E1000_STATUS);
+                     ${Log::info("card status:")};
+@@ -518,13 +517,13 @@
+         chunk   LKM::prototypes()
+         {
+             /* FIXME: See issue #54 */
+-            static unsigned int    rtx_e1000_register_read32(/*const*/ ${e1000::Context} *, unsigned int);
++            static unsigned int    rtx_e1000_register_read32(/*const*/ ${e1000::Context.ref}, unsigned int);
+         }
+ 
+         chunk   LKM::code()
+         {
+             /* FIXME: See issue #54 */
+-            static unsigned int    rtx_e1000_register_read32(/*const*/ ${e1000::Context} *ctx, unsigned int reg_offset)
++            static unsigned int    rtx_e1000_register_read32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset)
+             {
+                 return ioread32(ctx->ioaddr + reg_offset);
+             }
+@@ -541,13 +540,13 @@
+         chunk   LKM::prototypes()
+         {
+             /* FIXME: See issue #54 */
+-            static void rtx_e1000_register_write32(/*const*/ ${e1000::Context} *, unsigned int, unsigned int);
++            static void rtx_e1000_register_write32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int);
+         }
+ 
+         chunk   LKM::code()
+         {
+             /* FIXME: See issue #54 */
+-            static void rtx_e1000_register_write32(/*const*/ ${e1000::Context} *ctx, unsigned int reg_offset, unsigned int value)
++            static void rtx_e1000_register_write32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value)
+             {
+                 iowrite32(value, ctx->ioaddr + reg_offset);
+             }
+@@ -564,13 +563,13 @@
+         chunk   LKM::prototypes()
+         {
+             /* FIXME: See issue #54 */
+-            static void rtx_e1000_register_set32(/*const*/ ${e1000::Context} *, unsigned int, unsigned int);
++            static void rtx_e1000_register_set32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int);
+         }
+ 
+         chunk   LKM::code()
+         {
+             /* FIXME: See issue #54 */
+-            static void rtx_e1000_register_set32(/*const*/ ${e1000::Context} *ctx, unsigned int reg_offset, unsigned int value)
++            static void rtx_e1000_register_set32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value)
+             {
+                 iowrite32(rtx_e1000_register_read32(ctx, reg_offset) | value, ctx->ioaddr + reg_offset);
+             }
+@@ -587,13 +586,13 @@
+         chunk   LKM::prototypes()
+         {
+             /* FIXME: See issue #54 */
+-            static void rtx_e1000_register_unset32(/*const*/ ${e1000::Context} *, unsigned int, unsigned int);
++            static void rtx_e1000_register_unset32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int);
+         }
+ 
+         chunk   LKM::code()
+         {
+             /* FIXME: See issue #54 */
+-            static void rtx_e1000_register_unset32(/*const*/ ${e1000::Context} *ctx, unsigned int reg_offset, unsigned int value)
++            static void rtx_e1000_register_unset32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value)
+             {
+                 iowrite32(rtx_e1000_register_read32(ctx, reg_offset) & ~value, ctx->ioaddr + reg_offset);
+             }
+@@ -644,7 +643,7 @@
+              * e1000::Context? (but we would need to make it point back to
+              * the struct net_device)
+              */
+-            ${e1000::Context} *hw_ctx;
++            ${e1000::Context.ref} hw_ctx;
+             hw_ctx = &${rtx_ether_ctx}->hw_ctx;
+ 
+             /*
+@@ -755,7 +754,7 @@
+              */
+             for (i = 0; i != ${config.rx_ring_size}; ++i)
+             {
+-                hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff}*)netdev_alloc_skb(
++                hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff.ref})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)
+@@ -894,8 +893,7 @@
+              * 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};
++            ${e1000::Context.ref} hw_ctx_;
+             hw_ctx_ = &${rtx_ether_ctx}->hw_ctx;
+ 
+             /*
+@@ -911,7 +909,7 @@
+                         ${config.rx_buffer_len},
+                         DMA_FROM_DEVICE);
+                 /* XXX Go through the rtx types (Socket::SKBuff, AbstractSKBuff) */
+-                dev_kfree_skb(hw_ctx_->rx_ring.skbuffs[i].skbuff);
++                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,
+                     hw_ctx_->rx_ring.base, hw_ctx_->rx_ring.dma_base);
+@@ -973,14 +971,14 @@
+              */
+ 
+             ${Socket::SKBuff} skb;
+-            ${e1000::Context} *hw_ctx;
+-            ${e1000::TxRing} *tx_ring;
+-            ${Device::AbstractDevice} *devp;
++            ${e1000::Context.ref} hw_ctx;
++            ${e1000::TxRing.ref} tx_ring;
++            ${Device::AbstractDevice.ref} devp;
+ 
+             ${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.ref})${rtx_ether_ctx.device};
+ 
+             ${Log::info("xmit: skbuff details:")};
+             /*
+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
+@@ -61,7 +61,7 @@
+ 
+         method  init(Builtin::symbol dev)
+         {
+-            ${self} = (${Ethernet::AbstractDevice} *)${dev};
++            ${self} = (${Ethernet::AbstractDevice.ref})${dev};
+         }
+ 
+         map
+@@ -79,8 +79,8 @@
+              * I think it's useless to use the ${PCI::AbstractDevice} "abstraction"
+              * here, since we already are in a Linux specific context.
+              */
+-            ${PCI::AbstractDevice}          *pci_dev;
+-            ${Ethernet::AbstractDevice}     *net_dev;
++            ${PCI::AbstractDevice.ref}          pci_dev;
++            ${Ethernet::AbstractDevice.ref}     net_dev;
+ 
+             /*
+              * In the long-term, this may disappear for a new concept allowing
+@@ -144,14 +144,12 @@
+                  * 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};
++                ${Ethernet::AbstractDevice.ref} rtx_net_dev;
+                 { /* 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};
++                ${Ethernet::Device.ref} rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
+ 
+                 int error;
+                 {
+@@ -189,10 +187,8 @@
+         {
+             static int  rtx_ethernet_xmit(struct sk_buff* kernel_skb, struct net_device *net_dev)
+             {
+-                ${Ethernet::Device} *rtx_ether_ctx = netdev_priv(net_dev);
+-                ${Socket::AbstractSKBuff} *rtx_skb = (${Socket::AbstractSKBuff}*) kernel_skb;
+-                ${cast local.rtx_skb as Socket::AbstractSKBuff};
+-                ${cast local.rtx_ether_ctx as Ethernet::Device};
++                ${Ethernet::Device.ref} rtx_ether_ctx = netdev_priv(net_dev);
++                ${Socket::AbstractSKBuff.ref} rtx_skb = (${Socket::AbstractSKBuff.ref}) kernel_skb;
+ 
+                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx, local.rtx_skb)};
+             }
+@@ -210,14 +206,12 @@
+         {
+             static int  rtx_ethernet_close(struct net_device *dev)
+             {
+-                ${Ethernet::AbstractDevice} *rtx_net_dev;
+-                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
++                ${Ethernet::AbstractDevice.ref} rtx_net_dev;
+                 { /* 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};
++                ${Ethernet::Device.ref} rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
+ 
+                 /* TODO: change this pointcut into a pointcut/adapter/callback: */
+                 {
+@@ -249,11 +243,9 @@
+         {
+             static enum irqreturn   rtx_ethernet_interrupt_handler(int irq, void *dev_id)
+             {
+-                ${Ethernet::AbstractDevice} *rtx_net_dev = dev_id;
+-                ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
++                ${Ethernet::AbstractDevice.ref} rtx_net_dev = dev_id;
+ 
+-                ${Ethernet::Device} *rtx_ether_ctx;
+-                ${cast local.rtx_ether_ctx as Ethernet::Device};
++                ${Ethernet::Device.ref} rtx_ether_ctx;
+                 rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
+ 
+                 ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
+@@ -285,12 +277,11 @@
+          */
+         chunk PCI::pci_probe_hook(PCI::Device rtx_pci_dev)
+         {
+-            ${Ethernet::AbstractDevice} *rtx_net_dev;
+-            ${Ethernet::Device} *rtx_ether_ctx;
+-            ${cast local.rtx_net_dev as Ethernet::AbstractDevice};
++            ${Ethernet::AbstractDevice.ref} rtx_net_dev;
++            ${Ethernet::Device.ref} rtx_ether_ctx;
+ 
+             /* Cast the result back into our "transparent wrapper" type */
+-            rtx_net_dev = (${Ethernet::AbstractDevice}*)alloc_etherdev(sizeof(*rtx_ether_ctx));
++            rtx_net_dev = (${Ethernet::AbstractDevice.ref})alloc_etherdev(sizeof(*rtx_ether_ctx));
+             if (!rtx_net_dev)
+             {
+                 ${Log::info("cannot allocate the ethernet device context")};
+@@ -317,8 +308,7 @@
+              * type of rtx_pci_dev.pci_device to the type of
+              * rtx_pci_dev instead of the type of rtx_pci_dev.pci_device.
+              */
+-            ${PCI::AbstractDevice} *workaround = ${rtx_pci_dev.pci_device};
+-            ${cast local.workaround as PCI::AbstractDevice};
++            ${PCI::AbstractDevice.ref} workaround = ${rtx_pci_dev.pci_device};
+             { /* 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)};
+             }
+@@ -333,8 +323,7 @@
+              */
+             int bars = ${rtx_pci_dev.bars};
+             unsigned char /* __iomem */ *ioaddr = ${rtx_pci_dev.ioaddr};
+-            ${cast local.bars as Builtin::number};
+-            ${cast local.rtx_ether_ctx as Ethernet::Device};
++            ${cast local.bars as Builtin::number.scalar};
+             ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx,
+                                                       local.bars,
+                                                       local.ioaddr)};
+@@ -359,12 +348,10 @@
+          */
+         chunk   PCI::pci_remove_hook(PCI::Device rtx_pci_dev)
+         {
+-            ${Ethernet::Device} *rtx_ether_ctx = ${rtx_pci_dev.rtx_drv_context};
+-            ${cast local.rtx_ether_ctx as Ethernet::Device}; /* XXX */
++            ${Ethernet::Device.ref} rtx_ether_ctx = ${rtx_pci_dev.rtx_drv_context};
+             BUG_ON(!rtx_ether_ctx);
+ 
+-            ${Ethernet::AbstractDevice} *rtx_net_dev = ${local.rtx_ether_ctx.net_device};
+-            ${cast local.rtx_net_dev as Ethernet::AbstractDevice}; /* XXX */
++            ${Ethernet::AbstractDevice.ref} rtx_net_dev = ${local.rtx_ether_ctx.net_device};
+ 
+             unregister_netdev(${local.rtx_net_dev.k_net_dev});
+             free_netdev(${local.rtx_net_dev.k_net_dev});
+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
+@@ -41,9 +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.scalar      perm_addr;
+-        attribute   Builtin::symbol.scalar      dev_addr;
+-        attribute   Builtin::symbol.scalar      irq;
++        attribute   Builtin::symbol.ref        perm_addr;
++        attribute   Builtin::symbol.ref        dev_addr;
++        attribute   Builtin::symbol.ref        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
+@@ -32,7 +32,7 @@
+     {
+         decl    data_types()
+         {
+-            ${PCI::AbstractDevice}      *pdev;
++            ${PCI::AbstractDevice.ref}  pdev;
+             int                         bars;
+             /* It could be an array at some point: */
+             unsigned char /* __iomem */ *ioaddr;
+@@ -41,17 +41,16 @@
+ 
+         chunk   LKM::prototypes()
+         {
+-            static int  rtx_pci_device_enable(${PCI::Device} *);
+-            static void rtx_pci_device_disable(${PCI::Device} *);
++            static int  rtx_pci_device_enable(${PCI::Device.ref});
++            static void rtx_pci_device_disable(${PCI::Device.ref});
+         }
+ 
+         chunk   LKM::code()
+         {
+-            static int rtx_pci_device_enable(${PCI::Device} *self)
++            static int rtx_pci_device_enable(${PCI::Device.ref} self)
+             {
+                 int error;
+-                ${PCI::AbstractDevice}  *enable_pdev = self->pdev;
+-                ${cast local.enable_pdev as PCI::AbstractDevice};
++                ${PCI::AbstractDevice.ref}  enable_pdev = self->pdev;
+                 error = pci_enable_device(${local.enable_pdev.k_pci_dev});
+                 if (error)
+                     return error;
+@@ -62,10 +61,9 @@
+                 return 0;
+             }
+ 
+-            static void rtx_pci_device_disable(${PCI::Device} *self)
++            static void rtx_pci_device_disable(${PCI::Device.ref} self)
+             {
+-                ${PCI::AbstractDevice}  *disable_pdev = self->pdev;
+-                ${cast local.disable_pdev as PCI::AbstractDevice};
++                ${PCI::AbstractDevice.ref}  disable_pdev = self->pdev;
+                 if (self->ioaddr)
+                     iounmap(self->ioaddr);
+                 pci_release_selected_regions(${local.disable_pdev.k_pci_dev}, self->bars);
+@@ -75,8 +73,7 @@
+ 
+         method  init(PCI::AbstractDevice pdev)
+         {
+-            ${PCI::AbstractDevice} * workaround = (${PCI::AbstractDevice}*)pdev;
+-            ${cast local.workaround as PCI::AbstractDevice};
++            ${PCI::AbstractDevice.ref} workaround = (${PCI::AbstractDevice.ref})pdev;
+             ${self}->pdev = ${pdev};
+             ${self}->bars = pci_select_bars(${local.workaround.k_pci_dev}, IORESOURCE_MEM);
+             ${self}->ioaddr = NULL;
+@@ -95,8 +92,7 @@
+ 
+         method  select_ioaddr(Builtin::number bar)
+         {
+-            ${PCI::AbstractDevice} *select_ioaddr_pdev = ${self}->pdev;
+-            ${cast local.select_ioaddr_pdev as PCI::AbstractDevice};
++            ${PCI::AbstractDevice.ref} select_ioaddr_pdev = ${self}->pdev;
+             ${self}->ioaddr = pci_ioremap_bar(${local.select_ioaddr_pdev.k_pci_dev}, ${bar});
+         }
+ 
+@@ -131,9 +127,8 @@
+                                                       const struct pci_device_id *pdev_id)
+             {
+                 int error;
+-                ${PCI::Device} *rtx_pci_dev;
+-                ${PCI::AbstractDevice}  *rtx_pdev = (${PCI::AbstractDevice}*)pdev;
+-                ${cast local.rtx_pdev as PCI::AbstractDevice};
++                ${PCI::Device.ref} rtx_pci_dev;
++                ${PCI::AbstractDevice.ref} rtx_pdev = (${PCI::AbstractDevice.ref})pdev;
+ 
+                 rtx_pci_dev = kmalloc(sizeof(*rtx_pci_dev), GFP_KERNEL);
+                 if (!rtx_pci_dev)
+@@ -173,12 +168,6 @@
+                     goto fail;
+                 }
+ 
+-                /*
+-                 * XXX: We have to cast here because the compiler is
+-                 * confused by the fact that rtx_pci_dev is a
+-                 * pointer.
+-                 */
+-                ${cast local.rtx_pci_dev as PCI::Device};
+                 ${pointcut PCI::pci_probe_hook(local.rtx_pci_dev)};
+ 
+                 return 0;
+@@ -208,14 +197,11 @@
+         {
+             static void rtx_pci_remove(struct pci_dev *pdev)
+             {
+-                ${PCI::AbstractDevice}  *rtx_pdev = (${PCI::AbstractDevice}*)pdev;
+-                ${cast local.rtx_pdev as PCI::AbstractDevice};
+-                ${PCI::Device} *rtx_pci_dev = ${rtx_pdev.rtx_pci_ctx};
++                ${PCI::AbstractDevice.ref}  rtx_pdev = (${PCI::AbstractDevice.ref})pdev;
++                ${PCI::Device.ref} rtx_pci_dev = ${rtx_pdev.rtx_pci_ctx};
+ 
+                 BUG_ON(!rtx_pci_dev);
+ 
+-                /* XXX: compiler confused by the pointer type. */
+-                ${cast local.rtx_pci_dev as PCI::Device};
+                 ${pointcut PCI::pci_remove_hook(local.rtx_pci_dev)};
+ 
+                 /* ${local.rtx_pci_dev.disable()}; */
+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
+@@ -22,20 +22,20 @@
+     {
+         decl  data_types()
+         {
+-            ${Socket::AbstractSKBuff}   *skbuff;
+-            dma_addr_t                  dma_handle;
++            ${Socket::AbstractSKBuff.ref}   skbuff;
++            dma_addr_t                      dma_handle;
+         }
+ 
+         chunk   LKM::prototypes()
+         {
+-            static void rtx_socket_skbuff_dump_infos(${Socket::SKBuff} *);
+-            static int  rtx_socket_skbuff_map(${Socket::SKBuff} *, struct device *, enum dma_data_direction);
+-            static void rtx_socket_skbuff_unmap_and_free(${Socket::SKBuff} *, struct device *, enum dma_data_direction);
++            static void rtx_socket_skbuff_dump_infos(${Socket::SKBuff.ref});
++            static int  rtx_socket_skbuff_map(${Socket::SKBuff.ref}, struct device *, enum dma_data_direction);
++            static void rtx_socket_skbuff_unmap_and_free(${Socket::SKBuff.ref}, struct device *, enum dma_data_direction);
+         }
+ 
+         chunk   LKM::code()
+         {
+-            static void rtx_socket_skbuff_dump_infos(${Socket::SKBuff} *self)
++            static void rtx_socket_skbuff_dump_infos(${Socket::SKBuff.ref} self)
+             {
+                 WARN_ON(!self->skbuff);
+ 
+@@ -44,8 +44,7 @@
+                  * but Rathaxes doesn't support functions with a variable number of
+                  * arguments yet.
+                  */
+-                ${Socket::AbstractSKBuff}   *skb = self->skbuff;
+-                ${cast local.skb as Socket::AbstractSKBuff};
++                ${Socket::AbstractSKBuff.ref}   skb = self->skbuff;
+                 ${Ethernet::ProtocolId} ethernet_proto = { .id = be16_to_cpu(${local.skb.k_sk_buff}->protocol) };
+ 
+                 static const char * const ip_summed_values[] = {
+@@ -66,12 +65,11 @@
+                 );
+             }
+ 
+-            static int rtx_socket_skbuff_map(${Socket::SKBuff} *self,
++            static int rtx_socket_skbuff_map(${Socket::SKBuff.ref} self,
+                                              struct device *dev,
+                                              enum dma_data_direction direction)
+             {
+-                ${Socket::AbstractSKBuff}   *skb = self->skbuff;
+-                ${cast local.skb as Socket::AbstractSKBuff};
++                ${Socket::AbstractSKBuff.ref}   skb = self->skbuff;
+ 
+                 WARN_ON(!${local.skb.k_sk_buff});
+                 WARN_ON(self->dma_handle);
+@@ -90,12 +88,11 @@
+                 return 0;
+             }
+ 
+-            static void rtx_socket_skbuff_unmap_and_free(${Socket::SKBuff} *self,
++            static void rtx_socket_skbuff_unmap_and_free(${Socket::SKBuff.ref} self,
+                                                          struct device *dev,
+                                                          enum dma_data_direction direction)
+             {
+-                ${Socket::AbstractSKBuff}   *skb = self->skbuff;
+-                ${cast local.skb as Socket::AbstractSKBuff};
++                ${Socket::AbstractSKBuff.ref}   skb = self->skbuff;
+ 
+                 WARN_ON(!${local.skb.k_sk_buff});
+