# HG changeset patch # User Louis Opter # Date 1353627466 28800 # Node ID ffdb018893e2e6b57a1519aa2242e48c5ec085d6 # Parent 3e715b3e0ecdcfb4610b80a98cd14c7c874c1c39 Finish the patch on the create/destroy_device rewrite in the e1000 sample and fix Builtin::symbol diff -r 3e715b3e0ecd -r ffdb018893e2 rathaxes_fix_builtin_symbol.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rathaxes_fix_builtin_symbol.patch Thu Nov 22 15:37:46 2012 -0800 @@ -0,0 +1,24 @@ +# HG changeset patch +# User David Pineau , Louis Opter +# Parent 7da6e752991acb1b97f4fe77e940a4368f2cb969 +rathaxes: fix builtin::symbol + +It was builtin::Symbol instead of builtin::symbol in the compiler. + +diff --git a/rathaxes/compiler/passes/back/rtxIntrospect.inc.cws b/rathaxes/compiler/passes/back/rtxIntrospect.inc.cws +--- a/rathaxes/compiler/passes/back/rtxIntrospect.inc.cws ++++ b/rathaxes/compiler/passes/back/rtxIntrospect.inc.cws +@@ -638,11 +638,11 @@ + ref paramType = theChunk.variables[theVar.name].type_node.name; + else + { +- // That's it : It's a Builtin::Symbol, then. ++ // That's it : It's a Builtin::symbol, then. + local id; + local dummy; + // The param type shall be a rtxNodeIdentifier +- rtxNodeIdentifier(paramType, "Symbol", "Builtin"); ++ rtxNodeIdentifier(paramType, "symbol", "Builtin"); + } + } + else diff -r 3e715b3e0ecd -r ffdb018893e2 rathaxes_rewrite_create_and_destroy_device_in_the_e1000_sample.patch --- a/rathaxes_rewrite_create_and_destroy_device_in_the_e1000_sample.patch Sun Nov 18 02:19:07 2012 +0100 +++ b/rathaxes_rewrite_create_and_destroy_device_in_the_e1000_sample.patch Thu Nov 22 15:37:46 2012 -0800 @@ -1,6 +1,16 @@ # HG changeset patch -# Parent a7ba4e6eae2c9086c0b9876494165bf21ad1f405 -rathaxes: rewrite the {create,destroy}_device functions in the e1000 sample +# Parent d65cd0228e5c25692e6f37d0524e61ae26102a33 +rathaxes: rehaul the device initialization/destruction in the e1000 sample + +- Add several chunks on the e1000::Context; these chunks perform + low-level, device-dependant operations and should be move in the + front-end at some point. They weave into pointcuts defined by the + Ethernet subsystem; +- The e1000::{create,destroy}_device sequence templates are entirely + gone; they are replaced by the aforementioned chunks and more generic + code in the PCI and Ethernet subsystems; +- The PCI::{probe,remove} chunks/pointcuts have been rehauled and are + centered on the new PCI::Device type template. diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt --- a/rathaxes/samples/e1000/e1000.blt @@ -11,38 +21,113 @@ { template type e1000::RxDescriptor() { -@@ -288,7 +288,7 @@ - { - int bars; - unsigned char /* __iomem */ *ioaddr; -- int irq; +@@ -268,6 +268,22 @@ + + template type e1000::Context() + { ++ chunk ::decl() ++ { ++ struct rtx_e1000_ctx ++ { ++ int bars; ++ unsigned char /* __iomem */ *ioaddr; + unsigned int irq; ++ ++ /* we can't use the Rathaxes type here (#8) */ ++ //${e1000::RxRing} rx_ring; ++ //${e1000::TxRing} tx_ring; ++ struct rtx_e1000_rx_ring rx_ring; ++ struct rtx_e1000_tx_ring tx_ring; ++ }; ++ } ++ + chunk Ethernet::SubContext() + { + /* +@@ -278,28 +294,58 @@ + ${e1000::Context} hw_ctx; + } - /* we can't use the Rathaxes type here (#8) */ - //${e1000::RxRing} rx_ring; -@@ -298,8 +298,11 @@ - }; +- chunk ::decl() ++ chunk Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx, ++ Builtin::number bars, ++ Builtin::symbol ioaddr, ++ Builtin::number irq) + { +- /* +- * Yes, this typedef looks ugly but read the remark about +- * Ethernet::Device in ethernet.blt. +- */ +- struct rtx_e1000_ctx + { +- int bars; +- unsigned char /* __iomem */ *ioaddr; +- int irq; +- +- /* we can't use the Rathaxes type here (#8) */ +- //${e1000::RxRing} rx_ring; +- //${e1000::TxRing} tx_ring; +- struct rtx_e1000_rx_ring rx_ring; +- struct rtx_e1000_tx_ring tx_ring; +- }; ++ struct rtx_e1000_ctx *hw_ctx = &${rtx_ether_ctx}->hw_ctx; ++ hw_ctx->bars = ${bars}; ++ hw_ctx->ioaddr = ${ioaddr}; ++ hw_ctx->irq = ${irq}; ++ } } - chunk ::init() -+ chunk ::init(Builtin::number bars, Builtin::number ioaddr, Builtin::number irq) ++ chunk Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx) { -+ ${self}->bars = ${bars}; -+ ${self}->ioaddr = ${ioaddr}; -+ ${self}->irq = irq; ++ { ++ struct rtx_e1000_ctx *hw_ctx = &${rtx_ether_ctx}->hw_ctx; ++ rtx_e1000_register_write32(hw_ctx, E1000_CTRL, E1000_CMD_RST); ++ udelay(10); ++ } ++ } ++ ++ chunk Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx) ++ { ++ { ++ struct rtx_e1000_ctx *hw_ctx = &${rtx_ether_ctx}->hw_ctx; ++ /* Shamelessly borrowed from Minix */ ++ for (int i = 0; i < 3; ++i) ++ { ++ rtx_e1000_register_write32(hw_ctx, E1000_EEPROM_READ, (i << 8) | 1); ++ int value; ++ do ++ value = rtx_e1000_register_read32(hw_ctx, E1000_EEPROM_READ); ++ while ((value & (1 << 4)) == 0); ++ value >>= 16; ++ /* ++ * XXX: The net_dev manipulations here should take place in the ++ * ethernet templates: ++ * TODO: recevoir un Builtin::symbol avec le tableau ici pour ++ * pouvoir les remonter directement. ++ */ ++ ${rtx_ether_ctx}->net_dev->dev_addr[i * 2] = value & 0xff; ++ ${rtx_ether_ctx}->net_dev->dev_addr[i * 2 + 1] = (value >> 8) & 0xff; ++ } ++ ++ /* TODO: deplacer ça dans Ethernet (see above point): */ ++ memcpy(${rtx_ether_ctx}->net_dev->perm_addr, ++ ${rtx_ether_ctx}->net_dev->dev_addr, ++ ${rtx_ether_ctx}->net_dev->addr_len); ++ ++ ${Log::info("e1000::create: mac address loaded from the EEPROM")}; ++ } } map -@@ -479,40 +482,16 @@ +@@ -477,91 +523,6 @@ + } + } - template sequence e1000::create_device() - { +- template sequence e1000::create_device() +- { - chunk Ethernet::create_device(PCI::AbstractDevice pdev, Ethernet::Device rtx_ether_ctx) -+ chunk Ethernet::create_device(Ethernet::Device rtx_ether_ctx, -+ Builtin::number bars, -+ Builtin::number ioaddr, -+ Builtin::number irq) - { +- { - /* - * PCI init stuff: - * @@ -50,10 +135,7 @@ - * blts, also at some point maybe we could do that completely - * automatically in the PCI/Ethernet blts. - */ -+ /* XXX: Use the rathaxes type directly here (#51): */ -+ struct rtx_e1000_ctx *hw_ctx = &${rtx_ether_ctx}->hw_ctx; -+ ${cast local.hw_ctx as e1000::Context}; - +- - /* - * We could have used an init function here but since we can't init - * all the fields at once (see, ioaddr) and cannot call a C @@ -78,18 +160,58 @@ - * The really device specific algorithm starts here (so it should - * certainly be written in the frontend): - */ -+ ${local.hw_ctx.init(bars, ioaddr, irq)}; - - /* Reset the card */ - rtx_e1000_register_write32(&${rtx_ether_ctx}->hw_ctx, E1000_CTRL, E1000_CMD_RST); -@@ -533,6 +512,7 @@ - ${rtx_ether_ctx}->net_dev->dev_addr[i * 2 + 1] = (value >> 8) & 0xff; - } - -+ /* XXX: use ${rtx_ether_ctx.set_mac_address()}; : */ - memcpy(${rtx_ether_ctx}->net_dev->perm_addr, - ${rtx_ether_ctx}->net_dev->dev_addr, - ${rtx_ether_ctx}->net_dev->addr_len); +- +- /* Reset the card */ +- rtx_e1000_register_write32(&${rtx_ether_ctx}->hw_ctx, E1000_CTRL, E1000_CMD_RST); +- udelay(10); +- +- /* Now we can load its mac address (thanks minix code) */ +- for (int i = 0; i < 3; ++i) +- { +- rtx_e1000_register_write32(&${rtx_ether_ctx}->hw_ctx, E1000_EEPROM_READ, (i << 8) | 1); +- +- int value; +- do +- value = rtx_e1000_register_read32(&${rtx_ether_ctx}->hw_ctx, E1000_EEPROM_READ); +- while ((value & (1 << 4)) == 0); +- value >>= 16; +- +- ${rtx_ether_ctx}->net_dev->dev_addr[i * 2] = value & 0xff; +- ${rtx_ether_ctx}->net_dev->dev_addr[i * 2 + 1] = (value >> 8) & 0xff; +- } +- +- memcpy(${rtx_ether_ctx}->net_dev->perm_addr, +- ${rtx_ether_ctx}->net_dev->dev_addr, +- ${rtx_ether_ctx}->net_dev->addr_len); +- +- ${Log::info("e1000::create: mac address loaded from the EEPROM")}; +- } +- +- chunk ::CALL() +- { +- } +- } +- +- template sequence e1000::destroy_device() +- { +- chunk Ethernet::destroy_device(PCI::AbstractDevice pdev, Ethernet::Device rtx_ether_ctx) +- { +- /* +- * Here, we should have some checks to avoid to free resources that +- * haven't been allocated. (e.g: in case of previous errors). +- */ +- iounmap(${rtx_ether_ctx}->hw_ctx.ioaddr); +- pci_release_selected_regions(${pdev}, ${rtx_ether_ctx}->hw_ctx.bars); +- } +- +- chunk ::CALL() +- { +- } +- } +- + /* TODO: make that a method of e1000::Context */ + template sequence e1000::print_status(Ethernet::Device ctx) + { 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 @@ -102,92 +224,499 @@ required variable Builtin::number rx_ring_size; required variable Builtin::number tx_ring_size; required variable Builtin::number rx_buffer_len; -@@ -12,7 +9,8 @@ +@@ -10,9 +7,18 @@ + + provided type Context { ++ method decl(); ++ chunk Ethernet::SubContext(); - method decl(); +- method decl(); - method init(); -+ /* XXX: used types: */ -+ method init(Builtin::number, Builtin::number, Builtin::number); ++ ++ /* Callbacks/Hooks which should probably be in the front-end: */ ++ chunk Ethernet::adapter_init_context(Ethernet::Device, ++ Builtin::number, ++ Builtin::symbol, ++ Builtin::number); ++// chunk Ethernet::adapter_init_context(Ethernet::Device); ++ chunk Ethernet::adapter_reset(Ethernet::Device); ++ chunk Ethernet::adapter_load_mac_address(Ethernet::Device); } provided type RxDescriptor +@@ -76,18 +82,6 @@ + chunk ::decl(); + } + +- provided sequence create_device() +- { +- provided chunk Ethernet::create_device(PCI::AbstractDevice, Ethernet::Device); +- provided chunk ::CALL(); +- } +- +- provided sequence destroy_device() +- { +- provided chunk Ethernet::destroy_device(PCI::AbstractDevice, Ethernet::Device); +- provided chunk ::CALL(); +- } +- + /* + * This should take an e1000::Context as the first argument but this was + * not working as wished. 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 -@@ -111,6 +111,13 @@ - ${self}->net_dev = ${net_dev}; - } +@@ -113,6 +113,8 @@ -+ chunk set_mac_address(Builtin::number addr) -+ { -+ memcpy(${self}->net_dev->perm_addr, -+ ${self}->net_dev->dev_addr, -+ ${self}->net_dev->addr_len); -+ } -+ map { ++ pci_device: ${self}->pci_dev; ++ net_device: ${self}->net_dev; } -@@ -249,9 +256,26 @@ + } + +@@ -210,48 +212,72 @@ + }; + } + +- /* For now the type is not handled, so we just omit it (see #17) */ +- chunk PCI::pci_probe_hook(PCI::AbstractDevice pdev) ++ /* ++ * NOTE: for now, the error handling is leaking from PCI::probe(), but ++ * it's better than doing it at all. ++ * ++ * XXX: the chunk argument isn't correctly expanded by the ++ * compiler I have to use the same name as the actual C ++ * variable: ++ */ ++ chunk PCI::pci_probe_hook(PCI::Device rtx_pci_dev) + { +- /* +- * This typedef is needed to workaround a bug in CNorm __std__ +- * dialect. +- */ + ${Ethernet::Device} rtx_ether_ctx; +- struct net_device *net_dev; +- int error; ++ ${Ethernet::AbstractDevice} net_dev; + +- /* Initialize the net_device structure */ + net_dev = alloc_etherdev(sizeof(*rtx_ether_ctx)); +- if (net_dev == 0) ++ if (!net_dev) + { +- ${Log::info("cannot allocate memory")}; +- /* +- * Again, the error should be "raised" in the parent context. +- * +- * Here we know that we can return ENOMEM because *we* wrote +- * the parent context. +- */ +- return -ENOMEM; ++ ${Log::info("cannot allocate the ethernet device context")}; ++ error = -ENOMEM; ++ goto fail; + } +- SET_NETDEV_DEV(net_dev, &${pdev}->dev); ++ SET_NETDEV_DEV(net_dev, ${rtx_pci_dev.device}); + strlcpy(net_dev->name, ${config.ifname}, sizeof(net_dev->name)); +- net_dev->irq = ${pdev}->irq; ++ net_dev->irq = ${rtx_pci_dev.irq}; + net_dev->netdev_ops = &rtx_ether_ops; + + error = register_netdev(net_dev); + if (error) + { + ${Log::info("cannot register the driver in the net subsystem")}; +- return error; ++ goto fail; + } + /* Initialize our context held by the net_device structure */ - ${rtx_ether_ctx.init(local.net_dev, pdev)}; +- ${rtx_ether_ctx.init(local.net_dev, pdev)}; ++ /* ++ * 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. ++ */ ++ { ++ struct pci_dev *pci_device = ${rtx_pci_dev.pci_device}; ++ ${cast local.pci_device as PCI::AbstractDevice}; ++ ${local.rtx_ether_ctx.init(local.net_dev, local.pci_device)}; ++ } -+ /* XXX: The following code should probably part of PCI:: */ -+ - pci_set_drvdata(${pdev}, net_dev); +- pci_set_drvdata(${pdev}, net_dev); ++ /* Register ourselves in the parent context: */ ++ /* ${rtx_pci_dev.set_context(local.rtx_ether_ctx)}; */ ++ ${rtx_pci_dev}->context = rtx_ether_ctx; - ${pointcut Ethernet::create_device(pdev, local.rtx_ether_ctx)}; -+ int bars = pci_select_bars(${pdev}, IORESOURCE_MEM); -+ -+ if (pci_enable_device_mem(${pdev})) -+ ${Log::info("pci_enable_device_mem failed")}; -+ if (pci_request_selected_regions(${pdev}, bars, ${config.name})) -+ ${Log::info("pci_request_selected_regions failed")}; -+ if (${config.set_master}) -+ pci_set_master(${pdev}); -+ -+ /* 0 here is for BAR_0: */ -+ unsigned char /* __iomem */ *ioaddr = pci_ioremap_bar(${pdev}, 0); -+ if (!ioaddr) -+ ${Log::info("pci_ioremap_bar failed")}; -+ -+ unsigned int irq = net_dev->irq; -+ ${pointcut Ethernet::create_device(local.rtx_ether_ctx, local.bars, local.ioaddr, local.irq)}; ++ /* ++ * XXX: the asssignments/casts are here to circumvent ++ * typing issues in the compiler (see previous XXX). ++ */ ++ 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}; ++ ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx, ++ local.bars, ++ local.ioaddr, ++ local.irq)}; ++ ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)}; ++ ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)}; + } + + /* This chunk should be removed (see #26) */ +@@ -262,16 +288,18 @@ + + template sequence Ethernet::exit() + { +- chunk PCI::pci_remove_hook(PCI::AbstractDevice pdev) ++ /* ++ * XXX: We have to use the same name as the C variable for ++ * the chunk argument... ++ */ ++ chunk PCI::pci_remove_hook(PCI::Device rtx_pci_dev) + { +- /* workaround for cnorm unstrict */ +- struct net_device *net_dev = pci_get_drvdata(${pdev}); +- ${Ethernet::Device} rtx_ether_ctx = netdev_priv(net_dev); ++ ${Ethernet::Device} rtx_ether_ctx = ${rtx_pci_dev.context}; + +- ${pointcut Ethernet::destroy_device(pdev, local.rtx_ether_ctx)}; ++ BUG_ON(!rtx_ether_ctx); + +- unregister_netdev(net_dev); +- free_netdev(net_dev); ++ unregister_netdev(${local.rtx_ether_ctx.net_device}); ++ free_netdev(${local.rtx_ether_ctx.net_device}); } /* 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 -@@ -1,5 +1,8 @@ +@@ -1,4 +1,4 @@ -interface Ethernet : Socket, PCI, LKM +interface Ethernet : Socket, PCI, LKM, Builtin { -+ /* XXX: This should be in pci.rti, also maybe we need a bool type */ -+ required variable Builtin::symbol set_master; -+ required variable Builtin::string ifname; - provided type ProtocolId -@@ -22,6 +25,8 @@ - chunk LKM::includes(); +@@ -23,6 +23,9 @@ method decl(); method init(Ethernet::AbstractDevice, PCI::AbstractDevice); -+ method set_mac_address(Builtin::number); + pointcut Ethernet::SubContext(); + - pointcut Ethernet::SubContext(); ++ attribute PCI::AbstractDevice pci_device; ++ attribute Ethernet::AbstractDevice net_device; } -@@ -54,7 +59,10 @@ + required sequence open(Ethernet::Device) +@@ -52,15 +55,18 @@ + provided sequence init() + { provided chunk LKM::data(); - provided chunk PCI::pci_probe_hook(PCI::AbstractDevice); +- provided chunk PCI::pci_probe_hook(PCI::AbstractDevice); ++ provided chunk PCI::pci_probe_hook(PCI::Device); - provided pointcut Ethernet::create_device(PCI::AbstractDevice, Ethernet::Device); -+ provided pointcut Ethernet::create_device(Ethernet::Device, -+ Builtin::number, -+ Builtin::number, -+ Builtin::number); ++ provided pointcut Ethernet::adapter_init_context(Ethernet::Device, ++ Builtin::number, ++ Builtin::symbol, ++ Builtin::number); ++ provided pointcut Ethernet::adapter_reset(Ethernet::Device); ++ provided pointcut Ethernet::adapter_load_mac_address(Ethernet::Device); } provided sequence exit() + { +- provided chunk PCI::pci_remove_hook(PCI::AbstractDevice); +- +- provided pointcut Ethernet::destroy_device(PCI::AbstractDevice, Ethernet::Device); ++ provided chunk PCI::pci_remove_hook(PCI::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 +@@ -74,7 +74,6 @@ + */ + PCI::vendor_id = 0x8086; + PCI::product_id = 0x100e; +- PCI::set_master = true; + + Ethernet::ifname = "rtx%d"; + +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 +@@ -12,12 +12,102 @@ + struct pci_dev; + } + +- chunk ::init(PCI::AbstractDevice) ++ chunk ::init(PCI::AbstractDevice) + { + } + ++ chunk set_context(Builtin::symbol ctx) ++ { ++ pci_set_drvdata(${self}, ${ctx}); ++ } ++ + map + { ++ context: pci_get_drvdata(${self}); ++ } ++ } ++ ++ template type PCI::Device() ++ { ++ chunk ::decl() ++ { ++ struct rtx_pci_dev ++ { ++ struct pci_dev *pdev; ++ int bars; ++ /* It could be an array at some point: */ ++ unsigned char /* __iomem */ *ioaddr; ++ void *context; ++ }; ++ } ++ ++ chunk ::init(PCI::AbstractDevice pdev) ++ { ++ ${self}->pdev = ${pdev}; ++ ${self}->bars = pci_select_bars(${pdev}, IORESOURCE_MEM); ++ ${self}->ioaddr = NULL; ++ ${self}->context = NULL; ++ } ++ ++ chunk LKM::prototypes() ++ { ++ static int rtx_pci_device_enable(struct rtx_pci_dev *); ++ static void rtx_pci_device_disable(struct rtx_pci_dev *); ++ } ++ ++ chunk LKM::code() ++ { ++ static int rtx_pci_device_enable(struct rtx_pci_dev *self) ++ { ++ int error; ++ error = pci_enable_device(self->pdev); ++ if (error) ++ return error; ++ error = pci_request_selected_regions(self->pdev, self->bars, ${config.name}); ++ if (error) ++ return error; ++ pci_set_master(self->pdev); ++ return 0; ++ } ++ ++ static void rtx_pci_device_disable(struct rtx_pci_dev *self) ++ { ++ if (self->ioaddr) ++ iounmap(self->ioaddr); ++ pci_release_selected_regions(self->pdev, self->bars); ++ pci_disable_device(self->pdev); ++ } ++ } ++ ++ chunk enable() ++ { ++ rtx_pci_device_enable(${self}); ++ } ++ ++ chunk disable() ++ { ++ rtx_pci_device_disable(${self}); ++ } ++ ++ chunk select_ioaddr(Builtin::number bar) ++ { ++ ${self}->ioaddr = pci_ioremap_bar(${self}->pdev, ${bar}); ++ } ++ ++ chunk set_context(Builtin::symbol ctx) ++ { ++ ${self}->context = ctx; ++ } ++ ++ map ++ { ++ context: ${self}->context; ++ device: &${self}->pdev->dev; ++ pci_device: ${self}->pdev; ++ irq: ${self}->pdev->irq; ++ bars: ${self}->bars; ++ ioaddr: ${self}->ioaddr; ++ BAR_0: 0; + } + } + +@@ -34,24 +124,67 @@ + static int /* __devinit */ rtx_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *pdev_id) + { +- int err; ++ ${cast local.pdev as PCI::AbstractDevice}; ++ int error; ++ ${PCI::Device} *rtx_pci_dev; + +- err = pci_enable_device(pdev); +- if (err < 0) ++ rtx_pci_dev = kmalloc(sizeof(*rtx_pci_dev), GFP_KERNEL); ++ if (!rtx_pci_dev) ++ { ++ ${Log::info("cannot allocate the pci device context")}; ++ error = -ENOMEM; + goto fail; ++ } + +- /* Use local. to reference a local C variable: */ +- ${cast local.pdev as PCI::AbstractDevice}; +- ${pointcut PCI::pci_probe_hook(local.pdev)}; ++ /* ++ * XXX: I'm getting placeholder in the generated code if I don't ++ * open a scope here: ++ */ ++ { ++ ${local.rtx_pci_dev.init(local.pdev)}; ++ } ++ ++ /* ${local.pdev.set_context(local.rtx_pci_dev)}; */ ++ pci_set_drvdata(pdev, rtx_pci_dev); ++ ++ /* ${local.rtx_pci_dev.enable()}; */ ++ error = rtx_pci_device_enable(rtx_pci_dev); ++ if (error) ++ { ++ ${Log::info("rtx_pci_device_enable failed")}; ++ goto fail; ++ } ++ ++ /* ${local.rtx_pci_dev.select_ioaddr(local.rtx_pci_dev.BAR_0)}; */ ++ rtx_pci_dev->ioaddr = pci_ioremap_bar( ++ rtx_pci_dev->pdev, ${local.rtx_pci_dev.BAR_0} ++ ); ++ if (!${local.rtx_pci_dev.ioaddr}) ++ { ++ ${Log::info("can't map the device address space")}; ++ error = 1; /* XXX anything more approriate? */ ++ 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; + +- fail: +- return err; ++ fail: ++ /* ${local.pdev.set_context(NULL)}; */ ++ pci_set_drvdata(pdev, NULL); ++ kfree(rtx_pci_dev); ++ return error; + } + } + +- /* This chunk should be remove (see #26) */ ++ /* This chunk should be removed (see #26) */ + chunk ::CALL() + { + } +@@ -69,9 +202,16 @@ + static void rtx_pci_remove(struct pci_dev *pdev) + { + ${cast local.pdev as PCI::AbstractDevice}; +- ${pointcut PCI::pci_remove_hook(local.pdev)}; ++ ${PCI::Device} *rtx_pci_dev = ${local.pdev.context}; + +- pci_disable_device(pdev); ++ 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()}; */ ++ rtx_pci_device_disable(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 +@@ -1,14 +1,40 @@ +-interface PCI : LKM ++interface PCI : LKM, Builtin, Device + { ++ required variable Builtin::string LKM::name; ++ required variable Builtin::number PCI::vendor_id; ++ required variable Builtin::number PCI::product_id; ++ + provided type PCI::AbstractDevice + { + chunk LKM::includes(); ++ + method decl(); + method init(PCI::AbstractDevice); ++ method set_context(Builtin::symbol); ++ ++ attribute Builtin::symbol context; + } + +- required variable Builtin::number PCI::vendor_id; +- required variable Builtin::number PCI::product_id; ++ provided type PCI::Device ++ { ++ chunk LKM::prototypes(); ++ chunk LKM::code(); ++ ++ method decl(); ++ method init(PCI::AbstractDevice); ++ method enable(); ++ method disable(); ++ method select_ioaddr(Builtin::number); ++ method set_context(Builtin::symbol); ++ ++ attribute Builtin::symbol context; ++ attribute Device::AbstractDevice device; ++ attribute PCI::AbstractDevice pci_device; ++ attribute Builtin::symbol ioaddr; ++ attribute Builtin::number BAR_0; ++ attribute Builtin::number irq; ++ attribute Builtin::number bars; ++ } + + provided sequence register() + { +@@ -28,7 +54,7 @@ + provided chunk LKM::prototypes(); + provided chunk LKM::code(); + +- provided pointcut PCI::pci_probe_hook(PCI::AbstractDevice); ++ provided pointcut PCI::pci_probe_hook(PCI::Device); + } + + provided sequence remove() +@@ -36,6 +62,6 @@ + provided chunk LKM::prototypes(); + provided chunk LKM::code(); + +- provided pointcut PCI::pci_remove_hook(PCI::AbstractDevice); ++ provided pointcut PCI::pci_remove_hook(PCI::Device); + } + } diff -r 3e715b3e0ecd -r ffdb018893e2 series --- a/series Sun Nov 18 02:19:07 2012 +0100 +++ b/series Thu Nov 22 15:37:46 2012 -0800 @@ -1,4 +1,5 @@ rathaxes_add_a_test_to_reproduce_the_pointer_to_rathaxes_bug.patch +rathaxes_fix_builtin_symbol.patch rathaxes_use_single_file_language_tests.patch rathaxes_rename_pci_device_to_pci_abstractdevice.patch rathaxes_remove_useless_xmit_tso_cksum_offload_method_from_e1000.patch