Mercurial > archived > louis > epitech > mq > rathaxes
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 } |