comparison rathaxes_rewrite_create_and_destroy_device_in_the_e1000_sample.patch @ 97:ffdb018893e2

Finish the patch on the create/destroy_device rewrite in the e1000 sample and fix Builtin::symbol
author Louis Opter <louis@lse.epita.fr>
date Thu, 22 Nov 2012 15:37:46 -0800
parents 3e715b3e0ecd
children e2c237d6c37b
comparison
equal deleted inserted replaced
96:3e715b3e0ecd 97:ffdb018893e2
1 # HG changeset patch 1 # HG changeset patch
2 # Parent a7ba4e6eae2c9086c0b9876494165bf21ad1f405 2 # Parent d65cd0228e5c25692e6f37d0524e61ae26102a33
3 rathaxes: rewrite the {create,destroy}_device functions in the e1000 sample 3 rathaxes: rehaul the device initialization/destruction in the e1000 sample
4
5 - Add several chunks on the e1000::Context; these chunks perform
6 low-level, device-dependant operations and should be move in the
7 front-end at some point. They weave into pointcuts defined by the
8 Ethernet subsystem;
9 - The e1000::{create,destroy}_device sequence templates are entirely
10 gone; they are replaced by the aforementioned chunks and more generic
11 code in the PCI and Ethernet subsystems;
12 - The PCI::{probe,remove} chunks/pointcuts have been rehauled and are
13 centered on the new PCI::Device type template.
4 14
5 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt 15 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt
6 --- a/rathaxes/samples/e1000/e1000.blt 16 --- a/rathaxes/samples/e1000/e1000.blt
7 +++ b/rathaxes/samples/e1000/e1000.blt 17 +++ b/rathaxes/samples/e1000/e1000.blt
8 @@ -1,4 +1,4 @@ 18 @@ -1,4 +1,4 @@
9 -with e1000, Ethernet, Socket, PCI, LKM, Log 19 -with e1000, Ethernet, Socket, PCI, LKM, Log
10 +with e1000, Ethernet, Socket, PCI, LKM, Log, Builtin 20 +with e1000, Ethernet, Socket, PCI, LKM, Log, Builtin
11 { 21 {
12 template type e1000::RxDescriptor() 22 template type e1000::RxDescriptor()
13 { 23 {
14 @@ -288,7 +288,7 @@ 24 @@ -268,6 +268,22 @@
25
26 template type e1000::Context()
27 {
28 + chunk ::decl()
29 + {
30 + struct rtx_e1000_ctx
31 + {
32 + int bars;
33 + unsigned char /* __iomem */ *ioaddr;
34 + unsigned int irq;
35 +
36 + /* we can't use the Rathaxes type here (#8) */
37 + //${e1000::RxRing} rx_ring;
38 + //${e1000::TxRing} tx_ring;
39 + struct rtx_e1000_rx_ring rx_ring;
40 + struct rtx_e1000_tx_ring tx_ring;
41 + };
42 + }
43 +
44 chunk Ethernet::SubContext()
45 {
46 /*
47 @@ -278,28 +294,58 @@
48 ${e1000::Context} hw_ctx;
49 }
50
51 - chunk ::decl()
52 + chunk Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx,
53 + Builtin::number bars,
54 + Builtin::symbol ioaddr,
55 + Builtin::number irq)
56 {
57 - /*
58 - * Yes, this typedef looks ugly but read the remark about
59 - * Ethernet::Device in ethernet.blt.
60 - */
61 - struct rtx_e1000_ctx
15 { 62 {
16 int bars; 63 - int bars;
17 unsigned char /* __iomem */ *ioaddr; 64 - unsigned char /* __iomem */ *ioaddr;
18 - int irq; 65 - int irq;
19 + unsigned int irq; 66 -
20 67 - /* we can't use the Rathaxes type here (#8) */
21 /* we can't use the Rathaxes type here (#8) */ 68 - //${e1000::RxRing} rx_ring;
22 //${e1000::RxRing} rx_ring; 69 - //${e1000::TxRing} tx_ring;
23 @@ -298,8 +298,11 @@ 70 - struct rtx_e1000_rx_ring rx_ring;
24 }; 71 - struct rtx_e1000_tx_ring tx_ring;
72 - };
73 + struct rtx_e1000_ctx *hw_ctx = &${rtx_ether_ctx}->hw_ctx;
74 + hw_ctx->bars = ${bars};
75 + hw_ctx->ioaddr = ${ioaddr};
76 + hw_ctx->irq = ${irq};
77 + }
25 } 78 }
26 79
27 - chunk ::init() 80 - chunk ::init()
28 + chunk ::init(Builtin::number bars, Builtin::number ioaddr, Builtin::number irq) 81 + chunk Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx)
29 { 82 {
30 + ${self}->bars = ${bars}; 83 + {
31 + ${self}->ioaddr = ${ioaddr}; 84 + struct rtx_e1000_ctx *hw_ctx = &${rtx_ether_ctx}->hw_ctx;
32 + ${self}->irq = irq; 85 + rtx_e1000_register_write32(hw_ctx, E1000_CTRL, E1000_CMD_RST);
86 + udelay(10);
87 + }
88 + }
89 +
90 + chunk Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx)
91 + {
92 + {
93 + struct rtx_e1000_ctx *hw_ctx = &${rtx_ether_ctx}->hw_ctx;
94 + /* Shamelessly borrowed from Minix */
95 + for (int i = 0; i < 3; ++i)
96 + {
97 + rtx_e1000_register_write32(hw_ctx, E1000_EEPROM_READ, (i << 8) | 1);
98 + int value;
99 + do
100 + value = rtx_e1000_register_read32(hw_ctx, E1000_EEPROM_READ);
101 + while ((value & (1 << 4)) == 0);
102 + value >>= 16;
103 + /*
104 + * XXX: The net_dev manipulations here should take place in the
105 + * ethernet templates:
106 + * TODO: recevoir un Builtin::symbol avec le tableau ici pour
107 + * pouvoir les remonter directement.
108 + */
109 + ${rtx_ether_ctx}->net_dev->dev_addr[i * 2] = value & 0xff;
110 + ${rtx_ether_ctx}->net_dev->dev_addr[i * 2 + 1] = (value >> 8) & 0xff;
111 + }
112 +
113 + /* TODO: deplacer ça dans Ethernet (see above point): */
114 + memcpy(${rtx_ether_ctx}->net_dev->perm_addr,
115 + ${rtx_ether_ctx}->net_dev->dev_addr,
116 + ${rtx_ether_ctx}->net_dev->addr_len);
117 +
118 + ${Log::info("e1000::create: mac address loaded from the EEPROM")};
119 + }
33 } 120 }
34 121
35 map 122 map
36 @@ -479,40 +482,16 @@ 123 @@ -477,91 +523,6 @@
37 124 }
38 template sequence e1000::create_device() 125 }
39 { 126
127 - template sequence e1000::create_device()
128 - {
40 - chunk Ethernet::create_device(PCI::AbstractDevice pdev, Ethernet::Device rtx_ether_ctx) 129 - chunk Ethernet::create_device(PCI::AbstractDevice pdev, Ethernet::Device rtx_ether_ctx)
41 + chunk Ethernet::create_device(Ethernet::Device rtx_ether_ctx, 130 - {
42 + Builtin::number bars,
43 + Builtin::number ioaddr,
44 + Builtin::number irq)
45 {
46 - /* 131 - /*
47 - * PCI init stuff: 132 - * PCI init stuff:
48 - * 133 - *
49 - * Some of that code should certainly be moved in the PCI/Ethernet 134 - * Some of that code should certainly be moved in the PCI/Ethernet
50 - * blts, also at some point maybe we could do that completely 135 - * blts, also at some point maybe we could do that completely
51 - * automatically in the PCI/Ethernet blts. 136 - * automatically in the PCI/Ethernet blts.
52 - */ 137 - */
53 + /* XXX: Use the rathaxes type directly here (#51): */ 138 -
54 + struct rtx_e1000_ctx *hw_ctx = &${rtx_ether_ctx}->hw_ctx;
55 + ${cast local.hw_ctx as e1000::Context};
56
57 - /* 139 - /*
58 - * We could have used an init function here but since we can't init 140 - * We could have used an init function here but since we can't init
59 - * all the fields at once (see, ioaddr) and cannot call a C 141 - * all the fields at once (see, ioaddr) and cannot call a C
60 - * function within a placeholder (${}), it wasn't really worth it. 142 - * function within a placeholder (${}), it wasn't really worth it.
61 - */ 143 - */
76 - 158 -
77 - /* 159 - /*
78 - * The really device specific algorithm starts here (so it should 160 - * The really device specific algorithm starts here (so it should
79 - * certainly be written in the frontend): 161 - * certainly be written in the frontend):
80 - */ 162 - */
81 + ${local.hw_ctx.init(bars, ioaddr, irq)}; 163 -
82 164 - /* Reset the card */
83 /* Reset the card */ 165 - rtx_e1000_register_write32(&${rtx_ether_ctx}->hw_ctx, E1000_CTRL, E1000_CMD_RST);
84 rtx_e1000_register_write32(&${rtx_ether_ctx}->hw_ctx, E1000_CTRL, E1000_CMD_RST); 166 - udelay(10);
85 @@ -533,6 +512,7 @@ 167 -
86 ${rtx_ether_ctx}->net_dev->dev_addr[i * 2 + 1] = (value >> 8) & 0xff; 168 - /* Now we can load its mac address (thanks minix code) */
87 } 169 - for (int i = 0; i < 3; ++i)
88 170 - {
89 + /* XXX: use ${rtx_ether_ctx.set_mac_address()}; : */ 171 - rtx_e1000_register_write32(&${rtx_ether_ctx}->hw_ctx, E1000_EEPROM_READ, (i << 8) | 1);
90 memcpy(${rtx_ether_ctx}->net_dev->perm_addr, 172 -
91 ${rtx_ether_ctx}->net_dev->dev_addr, 173 - int value;
92 ${rtx_ether_ctx}->net_dev->addr_len); 174 - do
175 - value = rtx_e1000_register_read32(&${rtx_ether_ctx}->hw_ctx, E1000_EEPROM_READ);
176 - while ((value & (1 << 4)) == 0);
177 - value >>= 16;
178 -
179 - ${rtx_ether_ctx}->net_dev->dev_addr[i * 2] = value & 0xff;
180 - ${rtx_ether_ctx}->net_dev->dev_addr[i * 2 + 1] = (value >> 8) & 0xff;
181 - }
182 -
183 - memcpy(${rtx_ether_ctx}->net_dev->perm_addr,
184 - ${rtx_ether_ctx}->net_dev->dev_addr,
185 - ${rtx_ether_ctx}->net_dev->addr_len);
186 -
187 - ${Log::info("e1000::create: mac address loaded from the EEPROM")};
188 - }
189 -
190 - chunk ::CALL()
191 - {
192 - }
193 - }
194 -
195 - template sequence e1000::destroy_device()
196 - {
197 - chunk Ethernet::destroy_device(PCI::AbstractDevice pdev, Ethernet::Device rtx_ether_ctx)
198 - {
199 - /*
200 - * Here, we should have some checks to avoid to free resources that
201 - * haven't been allocated. (e.g: in case of previous errors).
202 - */
203 - iounmap(${rtx_ether_ctx}->hw_ctx.ioaddr);
204 - pci_release_selected_regions(${pdev}, ${rtx_ether_ctx}->hw_ctx.bars);
205 - }
206 -
207 - chunk ::CALL()
208 - {
209 - }
210 - }
211 -
212 /* TODO: make that a method of e1000::Context */
213 template sequence e1000::print_status(Ethernet::Device ctx)
214 {
93 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti 215 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti
94 --- a/rathaxes/samples/e1000/e1000.rti 216 --- a/rathaxes/samples/e1000/e1000.rti
95 +++ b/rathaxes/samples/e1000/e1000.rti 217 +++ b/rathaxes/samples/e1000/e1000.rti
96 @@ -1,8 +1,5 @@ 218 @@ -1,8 +1,5 @@
97 interface e1000 : Socket, Ethernet, PCI, LKM, Builtin 219 interface e1000 : Socket, Ethernet, PCI, LKM, Builtin
100 - required variable Builtin::symbol set_master; 222 - required variable Builtin::symbol set_master;
101 - 223 -
102 required variable Builtin::number rx_ring_size; 224 required variable Builtin::number rx_ring_size;
103 required variable Builtin::number tx_ring_size; 225 required variable Builtin::number tx_ring_size;
104 required variable Builtin::number rx_buffer_len; 226 required variable Builtin::number rx_buffer_len;
105 @@ -12,7 +9,8 @@ 227 @@ -10,9 +7,18 @@
106 { 228
229 provided type Context
230 {
231 + method decl();
232 +
107 chunk Ethernet::SubContext(); 233 chunk Ethernet::SubContext();
108 method decl(); 234 - method decl();
109 - method init(); 235 - method init();
110 + /* XXX: used types: */ 236 +
111 + method init(Builtin::number, Builtin::number, Builtin::number); 237 + /* Callbacks/Hooks which should probably be in the front-end: */
238 + chunk Ethernet::adapter_init_context(Ethernet::Device,
239 + Builtin::number,
240 + Builtin::symbol,
241 + Builtin::number);
242 +// chunk Ethernet::adapter_init_context(Ethernet::Device);
243 + chunk Ethernet::adapter_reset(Ethernet::Device);
244 + chunk Ethernet::adapter_load_mac_address(Ethernet::Device);
112 } 245 }
113 246
114 provided type RxDescriptor 247 provided type RxDescriptor
248 @@ -76,18 +82,6 @@
249 chunk ::decl();
250 }
251
252 - provided sequence create_device()
253 - {
254 - provided chunk Ethernet::create_device(PCI::AbstractDevice, Ethernet::Device);
255 - provided chunk ::CALL();
256 - }
257 -
258 - provided sequence destroy_device()
259 - {
260 - provided chunk Ethernet::destroy_device(PCI::AbstractDevice, Ethernet::Device);
261 - provided chunk ::CALL();
262 - }
263 -
264 /*
265 * This should take an e1000::Context as the first argument but this was
266 * not working as wished.
115 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt 267 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt
116 --- a/rathaxes/samples/e1000/ethernet.blt 268 --- a/rathaxes/samples/e1000/ethernet.blt
117 +++ b/rathaxes/samples/e1000/ethernet.blt 269 +++ b/rathaxes/samples/e1000/ethernet.blt
118 @@ -111,6 +111,13 @@ 270 @@ -113,6 +113,8 @@
119 ${self}->net_dev = ${net_dev}; 271
120 }
121
122 + chunk set_mac_address(Builtin::number addr)
123 + {
124 + memcpy(${self}->net_dev->perm_addr,
125 + ${self}->net_dev->dev_addr,
126 + ${self}->net_dev->addr_len);
127 + }
128 +
129 map 272 map
130 { 273 {
131 } 274 + pci_device: ${self}->pci_dev;
132 @@ -249,9 +256,26 @@ 275 + net_device: ${self}->net_dev;
276 }
277 }
278
279 @@ -210,48 +212,72 @@
280 };
281 }
282
283 - /* For now the type is not handled, so we just omit it (see #17) */
284 - chunk PCI::pci_probe_hook(PCI::AbstractDevice pdev)
285 + /*
286 + * NOTE: for now, the error handling is leaking from PCI::probe(), but
287 + * it's better than doing it at all.
288 + *
289 + * XXX: the chunk argument isn't correctly expanded by the
290 + * compiler I have to use the same name as the actual C
291 + * variable:
292 + */
293 + chunk PCI::pci_probe_hook(PCI::Device rtx_pci_dev)
294 {
295 - /*
296 - * This typedef is needed to workaround a bug in CNorm __std__
297 - * dialect.
298 - */
299 ${Ethernet::Device} rtx_ether_ctx;
300 - struct net_device *net_dev;
301 - int error;
302 + ${Ethernet::AbstractDevice} net_dev;
303
304 - /* Initialize the net_device structure */
305 net_dev = alloc_etherdev(sizeof(*rtx_ether_ctx));
306 - if (net_dev == 0)
307 + if (!net_dev)
308 {
309 - ${Log::info("cannot allocate memory")};
310 - /*
311 - * Again, the error should be "raised" in the parent context.
312 - *
313 - * Here we know that we can return ENOMEM because *we* wrote
314 - * the parent context.
315 - */
316 - return -ENOMEM;
317 + ${Log::info("cannot allocate the ethernet device context")};
318 + error = -ENOMEM;
319 + goto fail;
320 }
321 - SET_NETDEV_DEV(net_dev, &${pdev}->dev);
322 + SET_NETDEV_DEV(net_dev, ${rtx_pci_dev.device});
323 strlcpy(net_dev->name, ${config.ifname}, sizeof(net_dev->name));
324 - net_dev->irq = ${pdev}->irq;
325 + net_dev->irq = ${rtx_pci_dev.irq};
326 net_dev->netdev_ops = &rtx_ether_ops;
327
328 error = register_netdev(net_dev);
329 if (error)
330 {
331 ${Log::info("cannot register the driver in the net subsystem")};
332 - return error;
333 + goto fail;
334 }
335
133 /* Initialize our context held by the net_device structure */ 336 /* Initialize our context held by the net_device structure */
134 ${rtx_ether_ctx.init(local.net_dev, pdev)}; 337 - ${rtx_ether_ctx.init(local.net_dev, pdev)};
135 338 + /*
136 + /* XXX: The following code should probably part of PCI:: */ 339 + * XXX: the cast is here because the compiler resolve the
137 + 340 + * type of rtx_pci_dev.pci_device to the type of
138 pci_set_drvdata(${pdev}, net_dev); 341 + * rtx_pci_dev instead of the type of rtx_pci_dev.pci_device.
342 + *
343 + * Also, I'm getting placeholder in the generated code if
344 + * I don't open a scope here.
345 + */
346 + {
347 + struct pci_dev *pci_device = ${rtx_pci_dev.pci_device};
348 + ${cast local.pci_device as PCI::AbstractDevice};
349 + ${local.rtx_ether_ctx.init(local.net_dev, local.pci_device)};
350 + }
351
352 - pci_set_drvdata(${pdev}, net_dev);
353 + /* Register ourselves in the parent context: */
354 + /* ${rtx_pci_dev.set_context(local.rtx_ether_ctx)}; */
355 + ${rtx_pci_dev}->context = rtx_ether_ctx;
139 356
140 - ${pointcut Ethernet::create_device(pdev, local.rtx_ether_ctx)}; 357 - ${pointcut Ethernet::create_device(pdev, local.rtx_ether_ctx)};
141 + int bars = pci_select_bars(${pdev}, IORESOURCE_MEM); 358 + /*
142 + 359 + * XXX: the asssignments/casts are here to circumvent
143 + if (pci_enable_device_mem(${pdev})) 360 + * typing issues in the compiler (see previous XXX).
144 + ${Log::info("pci_enable_device_mem failed")}; 361 + */
145 + if (pci_request_selected_regions(${pdev}, bars, ${config.name})) 362 + int bars = ${rtx_pci_dev.bars};
146 + ${Log::info("pci_request_selected_regions failed")}; 363 + unsigned char /* __iomem */ *ioaddr = ${rtx_pci_dev.ioaddr};
147 + if (${config.set_master}) 364 + int irq = ${rtx_pci_dev.irq};
148 + pci_set_master(${pdev}); 365 + ${cast local.bars as Builtin::number};
149 + 366 + ${cast local.irq as Builtin::number};
150 + /* 0 here is for BAR_0: */ 367 + ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx,
151 + unsigned char /* __iomem */ *ioaddr = pci_ioremap_bar(${pdev}, 0); 368 + local.bars,
152 + if (!ioaddr) 369 + local.ioaddr,
153 + ${Log::info("pci_ioremap_bar failed")}; 370 + local.irq)};
154 + 371 + ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)};
155 + unsigned int irq = net_dev->irq; 372 + ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)};
156 + ${pointcut Ethernet::create_device(local.rtx_ether_ctx, local.bars, local.ioaddr, local.irq)}; 373 }
374
375 /* This chunk should be removed (see #26) */
376 @@ -262,16 +288,18 @@
377
378 template sequence Ethernet::exit()
379 {
380 - chunk PCI::pci_remove_hook(PCI::AbstractDevice pdev)
381 + /*
382 + * XXX: We have to use the same name as the C variable for
383 + * the chunk argument...
384 + */
385 + chunk PCI::pci_remove_hook(PCI::Device rtx_pci_dev)
386 {
387 - /* workaround for cnorm unstrict */
388 - struct net_device *net_dev = pci_get_drvdata(${pdev});
389 - ${Ethernet::Device} rtx_ether_ctx = netdev_priv(net_dev);
390 + ${Ethernet::Device} rtx_ether_ctx = ${rtx_pci_dev.context};
391
392 - ${pointcut Ethernet::destroy_device(pdev, local.rtx_ether_ctx)};
393 + BUG_ON(!rtx_ether_ctx);
394
395 - unregister_netdev(net_dev);
396 - free_netdev(net_dev);
397 + unregister_netdev(${local.rtx_ether_ctx.net_device});
398 + free_netdev(${local.rtx_ether_ctx.net_device});
157 } 399 }
158 400
159 /* This chunk should be removed (see #26) */ 401 /* This chunk should be removed (see #26) */
160 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti 402 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti
161 --- a/rathaxes/samples/e1000/ethernet.rti 403 --- a/rathaxes/samples/e1000/ethernet.rti
162 +++ b/rathaxes/samples/e1000/ethernet.rti 404 +++ b/rathaxes/samples/e1000/ethernet.rti
163 @@ -1,5 +1,8 @@ 405 @@ -1,4 +1,4 @@
164 -interface Ethernet : Socket, PCI, LKM 406 -interface Ethernet : Socket, PCI, LKM
165 +interface Ethernet : Socket, PCI, LKM, Builtin 407 +interface Ethernet : Socket, PCI, LKM, Builtin
166 { 408 {
167 + /* XXX: This should be in pci.rti, also maybe we need a bool type */
168 + required variable Builtin::symbol set_master;
169 +
170 required variable Builtin::string ifname; 409 required variable Builtin::string ifname;
171 410
172 provided type ProtocolId 411 @@ -23,6 +23,9 @@
173 @@ -22,6 +25,8 @@
174 chunk LKM::includes();
175 method decl(); 412 method decl();
176 method init(Ethernet::AbstractDevice, PCI::AbstractDevice); 413 method init(Ethernet::AbstractDevice, PCI::AbstractDevice);
177 + method set_mac_address(Builtin::number);
178 +
179 pointcut Ethernet::SubContext(); 414 pointcut Ethernet::SubContext();
180 } 415 +
181 416 + attribute PCI::AbstractDevice pci_device;
182 @@ -54,7 +59,10 @@ 417 + attribute Ethernet::AbstractDevice net_device;
418 }
419
420 required sequence open(Ethernet::Device)
421 @@ -52,15 +55,18 @@
422 provided sequence init()
423 {
183 provided chunk LKM::data(); 424 provided chunk LKM::data();
184 provided chunk PCI::pci_probe_hook(PCI::AbstractDevice); 425 - provided chunk PCI::pci_probe_hook(PCI::AbstractDevice);
426 + provided chunk PCI::pci_probe_hook(PCI::Device);
185 427
186 - provided pointcut Ethernet::create_device(PCI::AbstractDevice, Ethernet::Device); 428 - provided pointcut Ethernet::create_device(PCI::AbstractDevice, Ethernet::Device);
187 + provided pointcut Ethernet::create_device(Ethernet::Device, 429 + provided pointcut Ethernet::adapter_init_context(Ethernet::Device,
188 + Builtin::number, 430 + Builtin::number,
189 + Builtin::number, 431 + Builtin::symbol,
190 + Builtin::number); 432 + Builtin::number);
433 + provided pointcut Ethernet::adapter_reset(Ethernet::Device);
434 + provided pointcut Ethernet::adapter_load_mac_address(Ethernet::Device);
191 } 435 }
192 436
193 provided sequence exit() 437 provided sequence exit()
438 {
439 - provided chunk PCI::pci_remove_hook(PCI::AbstractDevice);
440 -
441 - provided pointcut Ethernet::destroy_device(PCI::AbstractDevice, Ethernet::Device);
442 + provided chunk PCI::pci_remove_hook(PCI::Device);
443 }
444 }
445 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx
446 --- a/rathaxes/samples/e1000/lkm.rtx
447 +++ b/rathaxes/samples/e1000/lkm.rtx
448 @@ -74,7 +74,6 @@
449 */
450 PCI::vendor_id = 0x8086;
451 PCI::product_id = 0x100e;
452 - PCI::set_master = true;
453
454 Ethernet::ifname = "rtx%d";
455
456 diff --git a/rathaxes/samples/e1000/pci.blt b/rathaxes/samples/e1000/pci.blt
457 --- a/rathaxes/samples/e1000/pci.blt
458 +++ b/rathaxes/samples/e1000/pci.blt
459 @@ -12,12 +12,102 @@
460 struct pci_dev;
461 }
462
463 - chunk ::init(PCI::AbstractDevice)
464 + chunk ::init(PCI::AbstractDevice)
465 {
466 }
467
468 + chunk set_context(Builtin::symbol ctx)
469 + {
470 + pci_set_drvdata(${self}, ${ctx});
471 + }
472 +
473 map
474 {
475 + context: pci_get_drvdata(${self});
476 + }
477 + }
478 +
479 + template type PCI::Device()
480 + {
481 + chunk ::decl()
482 + {
483 + struct rtx_pci_dev
484 + {
485 + struct pci_dev *pdev;
486 + int bars;
487 + /* It could be an array at some point: */
488 + unsigned char /* __iomem */ *ioaddr;
489 + void *context;
490 + };
491 + }
492 +
493 + chunk ::init(PCI::AbstractDevice pdev)
494 + {
495 + ${self}->pdev = ${pdev};
496 + ${self}->bars = pci_select_bars(${pdev}, IORESOURCE_MEM);
497 + ${self}->ioaddr = NULL;
498 + ${self}->context = NULL;
499 + }
500 +
501 + chunk LKM::prototypes()
502 + {
503 + static int rtx_pci_device_enable(struct rtx_pci_dev *);
504 + static void rtx_pci_device_disable(struct rtx_pci_dev *);
505 + }
506 +
507 + chunk LKM::code()
508 + {
509 + static int rtx_pci_device_enable(struct rtx_pci_dev *self)
510 + {
511 + int error;
512 + error = pci_enable_device(self->pdev);
513 + if (error)
514 + return error;
515 + error = pci_request_selected_regions(self->pdev, self->bars, ${config.name});
516 + if (error)
517 + return error;
518 + pci_set_master(self->pdev);
519 + return 0;
520 + }
521 +
522 + static void rtx_pci_device_disable(struct rtx_pci_dev *self)
523 + {
524 + if (self->ioaddr)
525 + iounmap(self->ioaddr);
526 + pci_release_selected_regions(self->pdev, self->bars);
527 + pci_disable_device(self->pdev);
528 + }
529 + }
530 +
531 + chunk enable()
532 + {
533 + rtx_pci_device_enable(${self});
534 + }
535 +
536 + chunk disable()
537 + {
538 + rtx_pci_device_disable(${self});
539 + }
540 +
541 + chunk select_ioaddr(Builtin::number bar)
542 + {
543 + ${self}->ioaddr = pci_ioremap_bar(${self}->pdev, ${bar});
544 + }
545 +
546 + chunk set_context(Builtin::symbol ctx)
547 + {
548 + ${self}->context = ctx;
549 + }
550 +
551 + map
552 + {
553 + context: ${self}->context;
554 + device: &${self}->pdev->dev;
555 + pci_device: ${self}->pdev;
556 + irq: ${self}->pdev->irq;
557 + bars: ${self}->bars;
558 + ioaddr: ${self}->ioaddr;
559 + BAR_0: 0;
560 }
561 }
562
563 @@ -34,24 +124,67 @@
564 static int /* __devinit */ rtx_pci_probe(struct pci_dev *pdev,
565 const struct pci_device_id *pdev_id)
566 {
567 - int err;
568 + ${cast local.pdev as PCI::AbstractDevice};
569 + int error;
570 + ${PCI::Device} *rtx_pci_dev;
571
572 - err = pci_enable_device(pdev);
573 - if (err < 0)
574 + rtx_pci_dev = kmalloc(sizeof(*rtx_pci_dev), GFP_KERNEL);
575 + if (!rtx_pci_dev)
576 + {
577 + ${Log::info("cannot allocate the pci device context")};
578 + error = -ENOMEM;
579 goto fail;
580 + }
581
582 - /* Use local. to reference a local C variable: */
583 - ${cast local.pdev as PCI::AbstractDevice};
584 - ${pointcut PCI::pci_probe_hook(local.pdev)};
585 + /*
586 + * XXX: I'm getting placeholder in the generated code if I don't
587 + * open a scope here:
588 + */
589 + {
590 + ${local.rtx_pci_dev.init(local.pdev)};
591 + }
592 +
593 + /* ${local.pdev.set_context(local.rtx_pci_dev)}; */
594 + pci_set_drvdata(pdev, rtx_pci_dev);
595 +
596 + /* ${local.rtx_pci_dev.enable()}; */
597 + error = rtx_pci_device_enable(rtx_pci_dev);
598 + if (error)
599 + {
600 + ${Log::info("rtx_pci_device_enable failed")};
601 + goto fail;
602 + }
603 +
604 + /* ${local.rtx_pci_dev.select_ioaddr(local.rtx_pci_dev.BAR_0)}; */
605 + rtx_pci_dev->ioaddr = pci_ioremap_bar(
606 + rtx_pci_dev->pdev, ${local.rtx_pci_dev.BAR_0}
607 + );
608 + if (!${local.rtx_pci_dev.ioaddr})
609 + {
610 + ${Log::info("can't map the device address space")};
611 + error = 1; /* XXX anything more approriate? */
612 + goto fail;
613 + }
614 +
615 + /*
616 + * XXX: We have to cast here because the compiler is
617 + * confused by the fact that rtx_pci_dev is a
618 + * pointer.
619 + */
620 + ${cast local.rtx_pci_dev as PCI::Device};
621 + ${pointcut PCI::pci_probe_hook(local.rtx_pci_dev)};
622
623 return 0;
624
625 - fail:
626 - return err;
627 + fail:
628 + /* ${local.pdev.set_context(NULL)}; */
629 + pci_set_drvdata(pdev, NULL);
630 + kfree(rtx_pci_dev);
631 + return error;
632 }
633 }
634
635 - /* This chunk should be remove (see #26) */
636 + /* This chunk should be removed (see #26) */
637 chunk ::CALL()
638 {
639 }
640 @@ -69,9 +202,16 @@
641 static void rtx_pci_remove(struct pci_dev *pdev)
642 {
643 ${cast local.pdev as PCI::AbstractDevice};
644 - ${pointcut PCI::pci_remove_hook(local.pdev)};
645 + ${PCI::Device} *rtx_pci_dev = ${local.pdev.context};
646
647 - pci_disable_device(pdev);
648 + BUG_ON(!rtx_pci_dev);
649 +
650 + /* XXX: compiler confused by the pointer type. */
651 + ${cast local.rtx_pci_dev as PCI::Device};
652 + ${pointcut PCI::pci_remove_hook(local.rtx_pci_dev)};
653 +
654 + /* ${local.rtx_pci_dev.disable()}; */
655 + rtx_pci_device_disable(rtx_pci_dev);
656 }
657 }
658
659 diff --git a/rathaxes/samples/e1000/pci.rti b/rathaxes/samples/e1000/pci.rti
660 --- a/rathaxes/samples/e1000/pci.rti
661 +++ b/rathaxes/samples/e1000/pci.rti
662 @@ -1,14 +1,40 @@
663 -interface PCI : LKM
664 +interface PCI : LKM, Builtin, Device
665 {
666 + required variable Builtin::string LKM::name;
667 + required variable Builtin::number PCI::vendor_id;
668 + required variable Builtin::number PCI::product_id;
669 +
670 provided type PCI::AbstractDevice
671 {
672 chunk LKM::includes();
673 +
674 method decl();
675 method init(PCI::AbstractDevice);
676 + method set_context(Builtin::symbol);
677 +
678 + attribute Builtin::symbol context;
679 }
680
681 - required variable Builtin::number PCI::vendor_id;
682 - required variable Builtin::number PCI::product_id;
683 + provided type PCI::Device
684 + {
685 + chunk LKM::prototypes();
686 + chunk LKM::code();
687 +
688 + method decl();
689 + method init(PCI::AbstractDevice);
690 + method enable();
691 + method disable();
692 + method select_ioaddr(Builtin::number);
693 + method set_context(Builtin::symbol);
694 +
695 + attribute Builtin::symbol context;
696 + attribute Device::AbstractDevice device;
697 + attribute PCI::AbstractDevice pci_device;
698 + attribute Builtin::symbol ioaddr;
699 + attribute Builtin::number BAR_0;
700 + attribute Builtin::number irq;
701 + attribute Builtin::number bars;
702 + }
703
704 provided sequence register()
705 {
706 @@ -28,7 +54,7 @@
707 provided chunk LKM::prototypes();
708 provided chunk LKM::code();
709
710 - provided pointcut PCI::pci_probe_hook(PCI::AbstractDevice);
711 + provided pointcut PCI::pci_probe_hook(PCI::Device);
712 }
713
714 provided sequence remove()
715 @@ -36,6 +62,6 @@
716 provided chunk LKM::prototypes();
717 provided chunk LKM::code();
718
719 - provided pointcut PCI::pci_remove_hook(PCI::AbstractDevice);
720 + provided pointcut PCI::pci_remove_hook(PCI::Device);
721 }
722 }