Mercurial > archived > louis > epitech > mq > rathaxes
comparison rathaxes_sample_e1000_rewrite_device_dependent_code.patch @ 132:f2e4dd91dc6f
Wip, leave some "functions" empty but start some build tests
author | Louis Opter <kalessin@kalessin.fr> |
---|---|
date | Sun, 05 Jan 2014 18:21:41 +0100 |
parents | c209851a82de |
children | dbb4a3b383cb |
comparison
equal
deleted
inserted
replaced
131:c209851a82de | 132:f2e4dd91dc6f |
---|---|
4 | 4 |
5 diff --git a/notes.txt b/notes.txt | 5 diff --git a/notes.txt b/notes.txt |
6 new file mode 100644 | 6 new file mode 100644 |
7 --- /dev/null | 7 --- /dev/null |
8 +++ b/notes.txt | 8 +++ b/notes.txt |
9 @@ -0,0 +1,9 @@ | 9 @@ -0,0 +1,26 @@ |
10 +Remarks for David & Lionel: | |
11 + | |
10 +- Too much changes to not start over; | 12 +- Too much changes to not start over; |
11 +- Lack of methods is extremely annoying and requires a lot of workarounds (e.g: | 13 +- Lack of methods is extremely annoying and requires a lot of workarounds (e.g: |
12 + see the register read/write/set/unset methods on e1000::Context); | 14 + see the register read/write/set/unset methods on e1000::Context); |
13 +- I'm using a pointcut inside the ethernet context "decl data_types" to inject | 15 +- I'm using a pointcut inside the ethernet context "decl data_types" to inject |
14 + my hardware context; it's impossible to get it back without hardcoding stuff, | 16 + my hardware context; it's impossible to get it back without hardcoding stuff, |
15 + because the ethernet subsystem isn't aware of the type of the field (so I | 17 + because the ethernet subsystem isn't aware of the type of the field (so I |
16 + can't write an attribute). Being able to just inject a type (instead of a | 18 + can't write an attribute). Being able to just inject a type (instead of a |
17 + whole structure field) might not be the best solution but would solve this | 19 + whole structure field) might not be the best solution but would solve this |
18 + issue/use case. | 20 + issue/use case; |
21 +- Can I use the same name for a pointcut and a sequence (e.g: Ethernet::send | |
22 + bot a sequence name and a pointcut same thing for the interrupt handler); | |
23 +- Lack of support for circular dependencies make some code annoying or | |
24 + incorrect (circular dependencies between abstract and concrete types via the | |
25 + attribute or circular dependencies between the rings and the hardware | |
26 + context). | |
27 + | |
28 +Todo/Totry: | |
29 + | |
30 +- Use the rtx_ether_ctx attribute on AbstractDevice to initialize Device | |
31 + objects in ethernet.bl; | |
32 +- Worry about the code being executed concurrently, e.g: what happens if the | |
33 + interrupt handler is called right before we disable it in the close path? | |
34 + | |
35 +Questions: | |
19 diff --git a/rathaxes/samples/e1000/CMakeLists.txt b/rathaxes/samples/e1000/CMakeLists.txt | 36 diff --git a/rathaxes/samples/e1000/CMakeLists.txt b/rathaxes/samples/e1000/CMakeLists.txt |
37 old mode 100755 | |
38 new mode 100644 | |
20 --- a/rathaxes/samples/e1000/CMakeLists.txt | 39 --- a/rathaxes/samples/e1000/CMakeLists.txt |
21 +++ b/rathaxes/samples/e1000/CMakeLists.txt | 40 +++ b/rathaxes/samples/e1000/CMakeLists.txt |
22 @@ -9,7 +9,6 @@ | 41 @@ -17,9 +17,9 @@ |
23 pci.rti | |
24 socket.rti | |
25 ethernet.rti | |
26 - e1000.rti | |
27 BLT | |
28 log.blt | |
29 lkm.blt | |
30 @@ -17,9 +16,8 @@ | |
31 dma.blt | 42 dma.blt |
32 pci.blt | 43 pci.blt |
33 socket.blt | 44 socket.blt |
34 - e1000.blt | 45 - e1000.blt |
35 ethernet.blt) | 46 - ethernet.blt) |
47 + ethernet.blt | |
48 + e1000.blt) | |
36 | 49 |
37 -IF (LINUX_KBUILD_DIR) | 50 -IF (LINUX_KBUILD_DIR) |
38 - ADD_RATHAXES_LKM(e1000 e1000_src) | 51 - ADD_RATHAXES_LKM(e1000 e1000_src) |
39 -ENDIF (LINUX_KBUILD_DIR) | 52 -ENDIF (LINUX_KBUILD_DIR) |
40 +#IF (LINUX_KBUILD_DIR) | 53 +#IF (LINUX_KBUILD_DIR) |
41 +# ADD_RATHAXES_LKM(e1000 e1000_src) | 54 +# ADD_RATHAXES_LKM(e1000 e1000_src) |
42 +#ENDIF (LINUX_KBUILD_DIR) | 55 +#ENDIF (LINUX_KBUILD_DIR) |
56 diff --git a/rathaxes/samples/e1000/dma.blt b/rathaxes/samples/e1000/dma.blt | |
57 old mode 100755 | |
58 new mode 100644 | |
59 diff --git a/rathaxes/samples/e1000/dma.rti b/rathaxes/samples/e1000/dma.rti | |
60 old mode 100755 | |
61 new mode 100644 | |
43 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt | 62 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt |
63 old mode 100755 | |
64 new mode 100644 | |
44 --- a/rathaxes/samples/e1000/e1000.blt | 65 --- a/rathaxes/samples/e1000/e1000.blt |
45 +++ b/rathaxes/samples/e1000/e1000.blt | 66 +++ b/rathaxes/samples/e1000/e1000.blt |
46 @@ -170,14 +170,15 @@ | 67 @@ -1,8 +1,148 @@ |
47 for (i = 0; i != ${config.rx_ring_size}; ++i) | 68 with e1000, Ethernet, Socket, DMA, PCI, LKM, Log, Builtin |
48 { | 69 { |
49 ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i]; | 70 - template type e1000::RxDescriptor() |
50 - // XXX #46: ${rtx_ether_ctx.init_rx_skbuff(local.skbuff, config.rx_buffer_len)}; | |
51 - if (rtx_ethernet_init_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len})) | |
52 + // XXX #46: ${rtx_ether_ctx.alloc_rx_skbuff(local.skbuff, config.rx_buffer_len)}; | |
53 + if (rtx_ethernet_alloc_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len})) | |
54 { | |
55 ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")}; | |
56 goto err_skbuffs_alloc; | |
57 } | |
58 - // XXX #46: ${local.skbuff.map_from(rtx_ether_ctx.device)}; | |
59 - if (rtx_socket_skbuff_map(${local.skbuff}, ${rtx_ether_ctx.device}, RTX_DMA_FROM_DEVICE)) | |
60 + /* XXX: recuperer le dma handle et le placer correctement dans le descripteur. */ | |
61 + ${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)} | |
62 + if (${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)}) | |
63 { | |
64 ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")}; | |
65 goto err_skbuffs_map; | |
66 diff --git a/rathaxes/samples/e1000/e1000ng.blt b/rathaxes/samples/e1000/e1000ng.blt | |
67 new file mode 100755 | |
68 --- /dev/null | |
69 +++ b/rathaxes/samples/e1000/e1000ng.blt | |
70 @@ -0,0 +1,717 @@ | |
71 +with e1000ng, Ethernet, Socket, DMA, PCI, LKM, Log, Builtin | |
72 +{ | |
73 + template type e1000::Register() | 71 + template type e1000::Register() |
74 + { | 72 { |
73 - decl data_types() | |
75 + decl data_types() | 74 + decl data_types() |
76 + { | 75 + { |
77 + E1000_CTRL = 0x00000, /* Device Control - RW */ | 76 + E1000_CTRL = 0x00000, /* Device Control - RW */ |
78 + E1000_CTRL_DUP = 0x00004, /* Device Control Duplicate (Shadow) - RW */ | 77 + E1000_CTRL_DUP = 0x00004, /* Device Control Duplicate (Shadow) - RW */ |
79 + E1000_STATUS = 0x00008, /* Device Status - RO */ | 78 + E1000_STATUS = 0x00008, /* Device Status - RO */ |
211 + } | 210 + } |
212 + | 211 + |
213 + template type e1000::RxDescriptor() | 212 + template type e1000::RxDescriptor() |
214 + { | 213 + { |
215 + decl data_types() | 214 + decl data_types() |
216 + { | 215 { |
217 + __le64 buff_addr; | 216 __le64 buff_addr; |
218 + __le16 length; | 217 __le16 length; |
219 + __le16 csum; | 218 @@ -12,13 +152,39 @@ |
220 + unsigned char status; | 219 __le16 special; |
221 + unsigned char errors; | 220 } |
222 + __le16 special; | 221 |
223 + } | 222 - chunk LKM::includes() |
224 + | |
225 + map | 223 + map |
226 + { | 224 { |
227 + } | 225 - #include <linux/types.h> |
226 } | |
228 + } | 227 + } |
229 + | 228 |
229 - method init() | |
230 + // This is a generic tx descriptor for the e1000. When you use TCP | 230 + // This is a generic tx descriptor for the e1000. When you use TCP |
231 + // Segmentation Offload (TSO) the hardware actually uses two types of | 231 + // Segmentation Offload (TSO) the hardware actually uses two types of |
232 + // tx descriptors in its tx ring: | 232 + // tx descriptors in its tx ring: |
233 + // - context descriptors: this descriptor doesn't actually point to data to | 233 + // - context descriptors: this descriptor doesn't actually point to data to |
234 + // send but initialize the offloading engine for the data descriptor that | 234 + // send but initialize the offloading engine for the data descriptor that |
235 + // follow; | 235 + // follow; |
236 + // - data descriptors: this descriptor points to data from the skbuffs. | 236 + // - data descriptors: this descriptor points to data from the skbuffs. |
237 + template type e1000::TxDescriptor() | 237 + template type e1000::TxDescriptor() |
238 + { | 238 + { |
239 + decl data_types() | 239 + decl data_types() |
240 + { | 240 { |
241 + __le64 buff_addr; | 241 + __le64 buff_addr; |
242 + union { | 242 + union { |
243 + __le32 data; | 243 + __le32 data; |
244 + struct { | 244 + struct { |
245 + __le16 length; | 245 + __le16 length; |
253 + unsigned char status; | 253 + unsigned char status; |
254 + unsigned char csum_start; /* CSS */ | 254 + unsigned char csum_start; /* CSS */ |
255 + __le16 special; | 255 + __le16 special; |
256 + } fields; | 256 + } fields; |
257 + } upper; | 257 + } upper; |
258 + } | 258 } |
259 + | 259 |
260 + map | 260 map |
261 + { | 261 @@ -26,44 +192,131 @@ |
262 + } | 262 } |
263 + } | 263 } |
264 + | 264 |
265 - /* | |
266 - * This is a generic tx descriptor for the e1000. When you use TCP | |
267 - * Segmentation Offload (TSO) the hardware actually uses two types of | |
268 - * tx descriptors in its tx ring: | |
269 - * - context descriptors: this descriptor doesn't actually point to data to | |
270 - * send but initialize the offloading engine for the data descriptor that | |
271 - * follow; | |
272 - * - data descriptors: this descriptor points to data from the skbuffs. | |
273 - */ | |
274 - template type e1000::TxDescriptor() | |
265 + template type e1000::Buffer() | 275 + template type e1000::Buffer() |
266 + { | 276 { |
277 - decl data_types() | |
267 + decl data_types() | 278 + decl data_types() |
268 + { | 279 { |
280 - __le64 buff_addr; | |
281 - union | |
282 - { | |
283 - __le32 data; | |
284 - struct | |
285 - { | |
286 - __le16 length; | |
287 - unsigned char csum_offset; /* CSO */ | |
288 - unsigned char cmd; | |
289 - } fields; | |
290 - } lower; | |
291 - union | |
292 - { | |
293 - __le32 data; | |
294 - struct | |
295 - { | |
296 - unsigned char status; | |
297 - unsigned char csum_start; /* CSS */ | |
298 - __le16 special; | |
299 - } fields; | |
300 - } upper; | |
269 + ${Socket::SKBuff} sk_buff; | 301 + ${Socket::SKBuff} sk_buff; |
270 + ${DMA::DMAHandle} dma; | 302 + ${DMA::DMAHandle} dma; |
271 + } | 303 } |
272 + | 304 |
305 - method init() | |
273 + method init(Socket::SKBuff sk_buff, DMA::DMAHandle dma) | 306 + method init(Socket::SKBuff sk_buff, DMA::DMAHandle dma) |
274 + { | 307 { |
275 + ${self.sk_buff} = ${sk_buff}; | 308 + ${self.sk_buff} = ${sk_buff}; |
276 + ${self.dma} = ${dma}; | 309 + ${self.dma} = ${dma}; |
277 + } | 310 + } |
278 + | 311 + |
279 + map | 312 + map |
281 + sk_buff: ${self}->sk_buff; | 314 + sk_buff: ${self}->sk_buff; |
282 + dma: ${self}->dma; | 315 + dma: ${self}->dma; |
283 + } | 316 + } |
284 + } | 317 + } |
285 + | 318 + |
286 + template type e1000::MMIO | 319 + template type e1000::MMIO() |
287 + { | 320 + { |
288 + decl data_types() | 321 + decl data_types() |
289 + { | 322 + { |
290 + unsigned char *io; | 323 + unsigned char *io; |
291 + } | 324 + } |
326 + method init(Builtin::symbol io) | 359 + method init(Builtin::symbol io) |
327 + { | 360 + { |
328 + ${self.io} = ${io}; | 361 + ${self.io} = ${io}; |
329 + } | 362 + } |
330 + | 363 + |
331 + method read32(${e1000::Register} reg) | 364 + method read32(e1000::Register reg) |
332 + { | 365 + { |
333 + ioread32(${self.io} + ${local.reg}); | 366 + ioread32(${self.io} + ${local.reg}); |
334 + } | 367 + } |
335 + | 368 + |
336 + method write32(${e1000::Register} reg, ${Builtin::number} value) | 369 + method write32(e1000::Register reg, Builtin::number value) |
337 + { | 370 + { |
338 + iowrite32(${local.value}, ${self.io} + ${local.reg}); | 371 + iowrite32(${local.value}, ${self.io} + ${local.reg}); |
339 + } | 372 + } |
340 + | 373 + |
341 + method set32(${e1000::Register} reg, ${Builtin::number} value) | 374 + method set32(e1000::Register reg, Builtin::number value) |
342 + { | 375 + { |
343 + iowrite32(ioread32(${self.io} + ${local.reg}) | value, ${self.io} + ${local.reg}); | 376 + iowrite32(ioread32(${self.io} + ${local.reg}) | value, ${self.io} + ${local.reg}); |
344 + } | 377 + } |
345 + | 378 + |
346 + method unset32(${e1000::Register} reg, ${Builtin::number} value) | 379 + method unset32(e1000::Register reg, Builtin::number value) |
347 + { | 380 + { |
348 + iowrite32(ioread32(${self.io} + ${local.reg}) & ~value, ${self.io} + ${local.reg}); | 381 + iowrite32(ioread32(${self.io} + ${local.reg}) & ~value, ${self.io} + ${local.reg}); |
349 + } | 382 + } |
350 + | 383 + |
351 + map | 384 + map |
385 + } | 418 + } |
386 + | 419 + |
387 + method init(e1000::MMIO io, Builtin::number desc_count, Builtin::number desc_size) | 420 + method init(e1000::MMIO io, Builtin::number desc_count, Builtin::number desc_size) |
388 + { | 421 + { |
389 + rtx_e1000_ring_init(&${self}, ${io}, ${desc_count}, ${desc_size}); | 422 + rtx_e1000_ring_init(&${self}, ${io}, ${desc_count}, ${desc_size}); |
390 + } | 423 } |
391 + } | 424 |
392 + | 425 map |
426 @@ -71,32 +324,27 @@ | |
427 } | |
428 } | |
429 | |
430 - /* | |
431 - * Ring of e1000::RxDescriptors and their corresponding skbuffs. | |
432 - * | |
433 - * - size: total size of the ring in bytes. | |
434 - * - base: address of the ring (we can't use the typedef here until we get | |
435 - * CNorm unstrict); | |
436 - * - dma_base: (physical) address of the ring where the device can access | |
437 - * the different descriptors; | |
438 - * - skbuffs: array of the skbuffs and their dma (physical) address | |
439 - * associated with each descriptor. | |
440 - */ | |
441 - template type e1000::RxRing() | |
393 + template type e1000::RxRing() | 442 + template type e1000::RxRing() |
394 + { | 443 { |
444 - decl data_types() | |
395 + decl data_types() | 445 + decl data_types() |
396 + { | 446 { |
447 - unsigned int size; | |
448 - ${e1000::RxDescriptor.ref} base; | |
449 - dma_addr_t dma_base; | |
450 - ${Socket::SKBuff} skbuffs[${config.rx_ring_size}]; | |
397 + ${e1000::Ring} ring; | 451 + ${e1000::Ring} ring; |
398 + } | 452 } |
399 + | 453 |
454 - method init() | |
400 + chunk LKM::prototypes() | 455 + chunk LKM::prototypes() |
401 + { | 456 { |
402 + static int rtx_e1000_alloc_rx_ressources(${e1000::RxRing.ref}); | 457 + static int rtx_e1000_alloc_rx_ressources(${e1000::RxRing.ref}); |
403 + } | 458 } |
404 + | 459 |
460 - chunk Ethernet::adapter_init_rx(Ethernet::Device rtx_ether_ctx) | |
405 + chunk LKM::code() | 461 + chunk LKM::code() |
406 + { | 462 + { |
407 + static int rtx_e1000_alloc_rx_ressources(${e1000::RxRing.ref} self) | 463 + static int rtx_e1000_alloc_rx_ressources(${e1000::RxRing.ref} self) |
408 + { | 464 + { |
409 + return 0; | 465 + return 0; |
410 + } | 466 + } |
411 + } | 467 + } |
412 + | 468 + |
413 + chunk Ethernet::adapter_init_rx(Ethernet::Device rtx_ether_ctx) | 469 + chunk Ethernet::adapter_init_rx(Ethernet::Device rtx_ether_ctx) |
414 + { | 470 { |
415 + { | 471 { |
416 + ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; | 472 ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; |
417 + | 473 @@ -167,18 +415,16 @@ |
418 + /* | 474 * Allocate the skbuffs, map them for DMA, and write their address |
419 + * Receive initialization (section 14.4): | 475 * in the corresponding descriptor. |
420 + * | 476 */ |
421 + * 1. Program the receive address, in RAL/RAH; | 477 - for (i = 0; i != ${config.rx_ring_size}; ++i) |
422 + * 2. Initialize the Multicast Table Array; | 478 - { |
423 + * 3. Program the interrupt mask register (done in | 479 + for (i = 0; i != ${config.rx_ring_size}; ++i) { |
424 + * e1000::activate_device_interruption); | 480 ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i]; |
425 + * 4. Allocate the receive descriptor ring and map it to make it | 481 - // XXX #46: ${rtx_ether_ctx.init_rx_skbuff(local.skbuff, config.rx_buffer_len)}; |
426 + * accessible by the device; | 482 - if (rtx_ethernet_init_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len})) |
427 + * 5. Write the start address of the ring in RDBAL/RDBAH and set | 483 - { |
428 + * RDLEN (Receive Descriptor Length) to the size of the ring; | |
429 + * 6. Set the RDH/RDT (Receive Descriptor Head/Tail) indexes to the | |
430 + * beginning and end of the ring; | |
431 + * 7. Make sure that RCTL.BSIZE and .BSEX are at 0 to configure the | |
432 + * receive buffer size to 2048 bytes (e1000::rx_buffer_len). | |
433 + * 8. Set RCTL.EN to enable the receiver. | |
434 + * | |
435 + * The ugly casts here are caused by the lack of CNorm unstrict. | |
436 + */ | |
437 + | |
438 + int i; | |
439 + | |
440 + /* 1. Program the receive address */ | |
441 + | |
442 + /* (We should use uint{32,16}_t but CNorm doesn't know them yet) */ | |
443 + rtx_e1000_register_write32(hw_ctx, E1000_RAL, | |
444 + *(unsigned int *)(${rtx_ether_ctx.dev_addr})); | |
445 + /* | |
446 + * The 16 upper bits of RAH also store the AS bits (which should be | |
447 + * 0) and the AV bit (should be 1 to set the address as valid). | |
448 + */ | |
449 + rtx_e1000_register_write32(hw_ctx, E1000_RAH, | |
450 + *(unsigned short *)(&${rtx_ether_ctx.dev_addr}[4])); | |
451 + rtx_e1000_register_set32(hw_ctx, E1000_RAH, E1000_RAH_AV); | |
452 + | |
453 + ${Log::info("adapter_init_rx: receive address programmed")}; | |
454 + | |
455 + /* 2. Initialize the MTA */ | |
456 + | |
457 + for (i = 0; i != 128; ++i) | |
458 + rtx_e1000_register_write32(hw_ctx, E1000_MTA + i * 4, 0); | |
459 + | |
460 + ${Log::info("adapter_init_rx: MTA init done")}; | |
461 + | |
462 + /* 4. Setup the receive descriptor ring */ | |
463 + | |
464 + /* Allocate the descriptors */ | |
465 + hw_ctx->rx_ring.size = ${config.rx_ring_size} * sizeof(*hw_ctx->rx_ring.base); | |
466 + hw_ctx->rx_ring.size = ALIGN(hw_ctx->rx_ring.size, 4096); | |
467 + hw_ctx->rx_ring.base = ${DMA::alloc_coherent( | |
468 + rtx_ether_ctx.device, | |
469 + local.hw_ctx.rx_ring.size, | |
470 + local.hw_ctx.rx_ring.dma_base.dma_handle | |
471 + )}; | |
472 + if (!hw_ctx->rx_ring.base) | |
473 + { | |
474 + ${Log::info("adapter_init_rx: cannot allocate the descriptors for the rx ring")}; | |
475 + goto err_rx_ring_alloc; | |
476 + } | |
477 + | |
478 + ${Log::info("adapter_init_rx: rx descriptors allocated")}; | |
479 + | |
480 + /* | |
481 + * Allocate the skbuffs, map them for DMA, and write their address | |
482 + * in the corresponding descriptor. | |
483 + */ | |
484 + for (i = 0; i != ${config.rx_ring_size}; ++i) | |
485 + { | |
486 + ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i]; | |
487 + // XXX #46: ${rtx_ether_ctx.alloc_rx_skbuff(local.skbuff, config.rx_buffer_len)}; | 484 + // XXX #46: ${rtx_ether_ctx.alloc_rx_skbuff(local.skbuff, config.rx_buffer_len)}; |
488 + if (rtx_ethernet_alloc_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len})) | 485 + if (rtx_ethernet_alloc_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len})) { |
489 + { | 486 ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")}; |
490 + ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")}; | 487 goto err_skbuffs_alloc; |
491 + goto err_skbuffs_alloc; | 488 } |
492 + } | 489 - // XXX #46: ${local.skbuff.map_from(rtx_ether_ctx.device)}; |
490 - if (rtx_socket_skbuff_map(${local.skbuff}, ${rtx_ether_ctx.device}, RTX_DMA_FROM_DEVICE)) | |
491 - { | |
493 + /* XXX: recuperer le dma handle et le placer correctement dans le descripteur. */ | 492 + /* XXX: recuperer le dma handle et le placer correctement dans le descripteur. */ |
494 + ${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)} | 493 + ${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)} |
495 + if (${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)}) | 494 + if (${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)}) { |
496 + { | 495 ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")}; |
497 + ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")}; | 496 goto err_skbuffs_map; |
498 + goto err_skbuffs_map; | 497 } |
499 + } | 498 @@ -212,8 +458,7 @@ |
500 + hw_ctx->rx_ring.base[i].buff_addr = cpu_to_le64(${local.skbuff.sk_buff}); | 499 goto init_rx_ok; |
501 + } | 500 |
502 + | 501 err_skbuffs_alloc: |
503 + // ${Log::info("adapter_init_rx: skbuffs allocated}; | 502 - while (i--) |
504 + pr_info("rtx_e1k: adapter_init_rx: skbuffs allocated, headlen=%d", skb_headlen((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i - 1].skbuff)); | 503 - { |
505 + | |
506 + /* 5. Save the emplacement and the size of the ring in RDBA/RDLEN */ | |
507 + rtx_e1000_register_write32(hw_ctx, E1000_RDBAL, hw_ctx->rx_ring.dma_base & 0xffffffff); | |
508 + rtx_e1000_register_write32(hw_ctx, E1000_RDBAH, hw_ctx->rx_ring.dma_base >> 32); | |
509 + rtx_e1000_register_write32(hw_ctx, E1000_RDLEN, hw_ctx->rx_ring.size); | |
510 + | |
511 + /* 6. Setup RDH/RDT */ | |
512 + rtx_e1000_register_write32(hw_ctx, E1000_RDH, 0); | |
513 + rtx_e1000_register_write32(hw_ctx, E1000_RDT, ${config.rx_ring_size} - 1); | |
514 + | |
515 + /* 7. Configure the buffer size, */ | |
516 + rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_BSIZE_${config.rx_buffer_len}); | |
517 + | |
518 + /* 8. Enable the receiver */ | |
519 + rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_EN); | |
520 + | |
521 + ${Log::info("adapter_init_rx: receive registers configured and receiver enabled")}; | |
522 + | |
523 + /* | |
524 + * XXX: We can't return here since we are not in a function but | |
525 + * in a chunk of code (injected in a function). | |
526 + */ | |
527 + goto init_rx_ok; | |
528 + | |
529 + err_skbuffs_alloc: | |
530 + while (i--) { | 504 + while (i--) { |
531 + dma_unmap_single( | 505 dma_unmap_single( |
532 + ${rtx_ether_ctx.device}, | 506 ${rtx_ether_ctx.device}, |
533 + /* XXX Leaking cast because of the array: */ | 507 /* XXX Leaking cast because of the array: */ |
534 + *((dma_addr_t *)&(hw_ctx->rx_ring.skbuffs[i].dma_handle)), | 508 @@ -238,487 +483,87 @@ |
535 + ${config.rx_buffer_len}, | 509 } |
536 + DMA_FROM_DEVICE); | 510 } |
537 + err_skbuffs_map: | 511 |
538 + /* XXX leaking cast: */ | 512 - map |
539 + dev_kfree_skb((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff); | |
540 + } | |
541 + | |
542 + dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx->rx_ring.size, | |
543 + hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base); | |
544 + err_rx_ring_alloc: | |
545 + /* | |
546 + * XXX: Likewise, if there is something else to rollback in the | |
547 + * enclosing function, this won't be done. | |
548 + */ | |
549 + return -ENOMEM; | |
550 + | |
551 + init_rx_ok: (void)0; /* NOP, to make this a valid label. */ | |
552 + } | |
553 + } | |
554 + | |
555 + method init(e1000::MMIO io, Builtin::number desc_count) | 513 + method init(e1000::MMIO io, Builtin::number desc_count) |
556 + { | 514 { |
515 - size: ((${self}).size); | |
516 - dma_base: ((${self}).dma_base); | |
517 - } | |
518 - } | |
519 - | |
520 - /* | |
521 - * Ring of e1000::TxDescriptors, this is a bit similar to the Rx ring except | |
522 - * that we don't really have to manage the skbuffs themselves (they are | |
523 - * given to use by the kernel). | |
524 - * | |
525 - * - size: total size of the ring in bytes. | |
526 - * - base: address of the ring (we can't use the typedef here until we get | |
527 - * CNorm unstrict); | |
528 - * - dma_base: (physical) address of the ring where the device can access | |
529 - * the different descriptors; | |
530 - * - skbuffs: the skbuffs associated with each descriptor of the ring; | |
531 - * - head: index on the head of the ring; | |
532 - * - tail: index on the tail of the ring. | |
533 - * | |
534 - * Keep in mind that the head and tail fields are, obviously, not | |
535 - * synchronized with TDT/TDH on the device. | |
536 - */ | |
537 - template type e1000::TxRing() | |
538 - { | |
539 - decl data_types() | |
540 - { | |
541 - unsigned int size; | |
542 - /* XXX: can't use ${e1000::TxDescriptor} here: */ | |
543 - ${e1000::TxDescriptor.ref} base; /* rename to descs */ | |
544 - dma_addr_t dma_base; | |
545 - ${Socket::SKBuff} skbuffs[${config.tx_ring_size}]; | |
546 - unsigned short head; | |
547 - unsigned short tail; | |
557 + ${self.ring.init(local.io, local.desc_count, self.desc_size)}; | 548 + ${self.ring.init(local.io, local.desc_count, self.desc_size)}; |
558 + } | 549 } |
559 + | 550 |
551 - chunk LKM::prototypes() | |
560 + method alloc() | 552 + method alloc() |
561 + { | 553 { |
554 - static void rtx_e1000_tx_ring_clean(${e1000::TxRing.ref}); | |
555 - static unsigned int rtx_e1000_tx_ring_descriptors_remaining(${e1000::TxRing.ref}); | |
556 - static int rtx_e1000_tx_ring_tso_cksum_offload(${e1000::TxRing.ref}, ${Socket::SKBuff.ref}); | |
557 - static void rtx_e1000_tx_ring_put(${e1000::TxRing.ref}, ${Socket::SKBuff.ref}); | |
558 - /* FIXME: See issue #54 */ | |
559 - static void rtx_e1000_tx_ring_start_xmit(${e1000::TxRing.ref}, /*const*/ ${e1000::Context.ref}); | |
560 - } | |
561 - | |
562 - chunk LKM::code() | |
563 - { | |
564 - static void rtx_e1000_tx_ring_clean(${e1000::TxRing.ref} self) | |
565 - { | |
566 - ${e1000::TxDescriptor.ref} tx_desc; | |
567 - bool done; | |
568 - | |
569 - for (; self->head != self->tail; self->head++) | |
570 - { | |
571 - tx_desc = &self->base[self->head]; | |
572 - done = tx_desc->upper.fields.status & E1000_TXD_STAT_DD; | |
573 - if (!done) | |
574 - break ; | |
575 - } | |
576 - | |
577 - pr_info("%s: tx_ring_clean: moving head to %d/%d", ${config.name}, self->head, ${config.tx_ring_size}); | |
578 - } | |
579 - | |
580 - static unsigned int rtx_e1000_tx_ring_descriptors_remaining(${e1000::TxRing.ref} self) | |
581 - { | |
582 - if (self->tail == self->head) /* ring is empty */ | |
583 - return 256; /* XXX: ${config.tx_ring_size}; */ | |
584 - if (self->tail > self->head) | |
585 - /* XXX: ${config.tx_ring_size} */ | |
586 - return 256 - (self->tail - self->head); | |
587 - return self->head - self->tail; | |
588 - } | |
589 - | |
590 - static int rtx_e1000_tx_ring_tso_cksum_offload(${e1000::TxRing.ref} self, ${Socket::SKBuff.ref} skb) | |
591 - { | |
592 - ${Socket::AbstractSKBuff.ref} k_skb = skb->skbuff; | |
593 - return skb_is_gso(${local.k_skb.k_sk_buff}) || ${local.k_skb.k_sk_buff}->ip_summed == CHECKSUM_PARTIAL; | |
594 - } | |
595 - | |
596 - static void rtx_e1000_tx_ring_put(${e1000::TxRing.ref} self, ${Socket::SKBuff.ref} skb) | |
597 - { | |
598 - WARN_ON(!skb); | |
599 - | |
600 - /* | |
601 - * Mark it as the last buffer (EOP) and ask the card to | |
602 - * insert the Ethernet FCS (Frame Check Sequence). | |
603 - * | |
604 - * XXX: it sucks to use skb_headlen() here (this part of the | |
605 - * code shouldn't be aware of it and use something more | |
606 - * abstract. | |
607 - */ | |
608 - ${Socket::AbstractSKBuff.ref} k_skb = skb->skbuff; | |
609 - ${e1000::TxDescriptor.ref} tx_desc = &self->base[self->tail]; | |
610 - tx_desc->lower.data = cpu_to_le32( | |
611 - E1000_TXD_CMD_EOP | | |
612 - E1000_TXD_CMD_IFCS | | |
613 - E1000_TXD_CMD_RS | | |
614 - skb_headlen(${local.k_skb.k_sk_buff})); | |
615 - tx_desc->upper.data = 0; | |
616 - tx_desc->buff_addr = cpu_to_le64(${local.skb.dma_handle.k_dma_handle}); | |
617 - memcpy(&self->skbuffs[self->tail], ${local.k_skb.k_sk_buff}, sizeof(*${local.k_skb.k_sk_buff})); | |
618 - self->tail = (self->tail + 1) % ${config.tx_ring_size}; | |
619 - } | |
620 - | |
621 - /* FIXME: See issue #54 */ | |
622 - static void rtx_e1000_tx_ring_start_xmit(${e1000::TxRing.ref} self, /*const*/ ${e1000::Context.ref} hw_ctx) | |
623 - { | |
624 - pr_info("%s: start_xmit: moving tail to %d/%d", ${config.name}, self->tail, ${config.tx_ring_size}); | |
625 - rtx_e1000_register_write32(hw_ctx, E1000_TDT, self->tail); | |
626 - } | |
627 - } | |
628 - | |
629 - chunk Ethernet::adapter_init_tx(Ethernet::Device rtx_ether_ctx) | |
630 - { | |
631 - { | |
632 - ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
633 - | |
634 - /* | |
635 - * Transmission initialization (section 14.5): | |
636 - * | |
637 - * 1. Allocate the transmit descriptors ring and map it to make it | |
638 - * accessible by the device; | |
639 - * 2. Write the start address of the ring in TDBAL/TDBAH and set | |
640 - * TDLEN to the size of the ring; | |
641 - * 3. Set the TDH/TDT indexes to the beginning and end of the ring; | |
642 - * 4. Set TCTL.PSP to pad short packets and TCTL.EN to enable the | |
643 - * transmitter. | |
644 - */ | |
645 - | |
646 - /* 1. Allocate the tx ring */ | |
647 - hw_ctx->tx_ring.size = ${config.tx_ring_size} * sizeof(*hw_ctx->tx_ring.base); | |
648 - hw_ctx->tx_ring.size = ALIGN(hw_ctx->tx_ring.size, 4096); | |
649 - hw_ctx->tx_ring.base = dma_alloc_coherent( | |
650 - ${rtx_ether_ctx.device}, | |
651 - hw_ctx->tx_ring.size, | |
652 - &hw_ctx->tx_ring.dma_base, | |
653 - GFP_KERNEL); | |
654 - if (!hw_ctx->rx_ring.base) | |
655 - { | |
656 - ${Log::info("adapter_init_tx: cannot allocate the descriptors for the tx ring")}; | |
657 - /* | |
658 - * XXX: If there is something else to rollback in the enclosing | |
659 - * function, this won't be done. | |
660 - */ | |
661 - return -ENOMEM; | |
662 - } | |
663 - | |
664 - ${Log::info("adapter_init_tx: tx descriptors allocated")}; | |
665 - | |
666 - /* 2. Save the emplacement and the size of the ring in TDBA/TDLEN */ | |
667 - rtx_e1000_register_write32(hw_ctx, E1000_TDBAL, hw_ctx->tx_ring.dma_base & 0xffffffff); | |
668 - rtx_e1000_register_write32(hw_ctx, E1000_TDBAH, hw_ctx->tx_ring.dma_base >> 32); | |
669 - rtx_e1000_register_write32(hw_ctx, E1000_TDLEN, hw_ctx->tx_ring.size); | |
670 - | |
671 - /* 3. Setup TDH/TDT to zero: the queue is empty */ | |
672 - rtx_e1000_register_write32(hw_ctx, E1000_TDH, 0); | |
673 - rtx_e1000_register_write32(hw_ctx, E1000_TDT, 0); | |
674 - hw_ctx->tx_ring.head = 0; | |
675 - hw_ctx->tx_ring.tail = 0; | |
676 - | |
677 - /* 4. Set TCTL.PSP and enable the transmitter */ | |
678 - rtx_e1000_register_set32(hw_ctx, E1000_TCTL, E1000_TCTL_PSP|E1000_TCTL_EN); | |
679 - | |
680 - ${Log::info("adapter_init_tx: transmit registers configured and transmitter enabled")}; | |
681 - } | |
682 - } | |
683 - | |
684 - method clean() | |
685 - { | |
686 - rtx_e1000_tx_ring_clean(${self}); | |
687 - } | |
688 - | |
689 - method descriptors_remaining() | |
690 - { | |
691 - rtx_e1000_tx_ring_descriptors_remaining(${self}); | |
692 - } | |
693 - | |
694 - method tso_cksum_offload(Socket::SKBuff skb) | |
695 - { | |
696 - } | |
697 - | |
698 - method put(Socket::SKBuff skb) | |
699 - { | |
700 - rtx_e1000_tx_ring_put(${self}, &${skb}); | |
701 - } | |
702 - | |
703 - method start_xmit(e1000::Context ctx) | |
704 - { | |
705 - rtx_e1000_tx_ring_start_xmit(${self}, ${ctx}); | |
706 - } | |
707 - | |
708 - method init() | |
709 - { | |
562 + rtx_e1000_alloc_rx_ressources(${self}); | 710 + rtx_e1000_alloc_rx_ressources(${self}); |
563 + } | 711 } |
564 + | 712 |
565 + map | 713 map |
566 + { | 714 { |
567 + descs: ((${self})->descs); // TODO: fix cast pour directement avoir les descs | 715 + descs: ((${self})->descs); // TODO: fix cast pour directement avoir les descs |
568 + desc_size: sizeof(/* XXX ${e1000::RxDescriptor} */int); | 716 + desc_size: sizeof(/* XXX ${e1000::RxDescriptor} */int); |
569 + } | 717 } |
570 + } | 718 } |
571 + | 719 |
720 - template type e1000::Context() | |
572 + template type e1000::TxRing() | 721 + template type e1000::TxRing() |
573 + { | 722 { |
723 - decl data_types() | |
574 + decl data_types() | 724 + decl data_types() |
575 + { | 725 { |
726 - int bars; | |
727 - unsigned char /* __iomem */ *ioaddr; | |
728 - ${e1000::RxRing.scalar} rx_ring; | |
729 - ${e1000::TxRing.scalar} tx_ring; | |
576 + ${e1000::Ring} ring; | 730 + ${e1000::Ring} ring; |
577 + } | 731 } |
578 + | 732 |
733 - chunk Ethernet::HardwareContext() | |
579 + chunk LKM::prototypes() | 734 + chunk LKM::prototypes() |
580 + { | 735 { |
736 - /* | |
737 - * Force the generation of the structure in the "headers" part, we | |
738 - * have to do this since we do not use the structure in this blt | |
739 - * (we hacked a bit and used it in ethernet.blt directly). | |
740 - */ | |
741 - ${e1000::Context} hw_ctx; | |
581 + static int rtx_e1000_alloc_tx_ressources(${e1000::TxRing.ref}); | 742 + static int rtx_e1000_alloc_tx_ressources(${e1000::TxRing.ref}); |
582 + } | 743 } |
583 + | 744 |
745 - chunk Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx, | |
746 - Builtin::number bars, | |
747 - Builtin::symbol ioaddr) | |
584 + chunk LKM::code() | 748 + chunk LKM::code() |
585 + { | 749 { |
586 + static int rtx_e1000_alloc_tx_ressources(${e1000::TxRing.ref} self) | 750 + static int rtx_e1000_alloc_tx_ressources(${e1000::TxRing.ref} self) |
587 + { | 751 { |
752 - ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
753 - hw_ctx->bars = ${bars}; | |
754 - hw_ctx->ioaddr = ${ioaddr}; | |
588 + return 0; | 755 + return 0; |
589 + } | 756 } |
590 + } | 757 } |
591 + | 758 |
759 - chunk Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx) | |
592 + method init(e1000::MMIO io, Builtin::number desc_count) | 760 + method init(e1000::MMIO io, Builtin::number desc_count) |
593 + { | 761 { |
762 - { | |
763 - /* XXX Naming this variable 'hw_ctx' kicks the decl out of the generated code */ | |
764 - ${e1000::Context.ref} tmp_hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
765 - rtx_e1000_register_write32(tmp_hw_ctx, E1000_CTRL, E1000_CMD_RST); | |
766 - udelay(10); | |
767 - } | |
594 + ${self.ring.init(local.io, local.desc_count, self.desc_size)}; | 768 + ${self.ring.init(local.io, local.desc_count, self.desc_size)}; |
595 + } | 769 } |
596 + | 770 |
771 - chunk Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx) | |
597 + method alloc() | 772 + method alloc() |
598 + { | 773 { |
774 - { | |
775 - ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
776 - /* Shamelessly borrowed from Minix */ | |
777 - for (int i = 0; i < 3; ++i) | |
778 - { | |
779 - rtx_e1000_register_write32(hw_ctx, E1000_EEPROM_READ, (i << 8) | 1); | |
780 - int value; | |
781 - do | |
782 - value = rtx_e1000_register_read32(hw_ctx, E1000_EEPROM_READ); | |
783 - while ((value & (1 << 4)) == 0); | |
784 - value >>= 16; | |
785 - /* | |
786 - * NOTE: I'm not sure if Ethernet::Device should be | |
787 - * accessed directly here. But since we need to take it in | |
788 - * parameter (so we can get back our e1000::Context) it | |
789 - * seems inadequate to set this in another way: | |
790 - */ | |
791 - ${rtx_ether_ctx.dev_addr}[i * 2] = value & 0xff; | |
792 - ${rtx_ether_ctx.dev_addr}[i * 2 + 1] = (value >> 8) & 0xff; | |
793 - } | |
794 - ${Log::info("e1000::create: mac address loaded from the EEPROM")}; | |
795 - } | |
796 - } | |
797 - | |
798 - chunk Ethernet::adapter_setup(Ethernet::Device rtx_ether_ctx) | |
799 - { | |
800 - { | |
801 - ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
802 - | |
803 - /* | |
804 - * "General Configuration" (section 14.3): | |
805 - * | |
806 - * - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection & | |
807 - * negociation; | |
808 - * - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation; | |
809 - * - CTRL.PHY_RST: Unset it; | |
810 - * - CTRL.ILOS: Unset it (ILOS is Invert Loss Of Signal); | |
811 - * - CTRL.VME: Make sure it's not set to disable VLAN support; | |
812 - * - Set the control flow registers to 0; | |
813 - * - Finally, initialize all the statistic registers from | |
814 - * E1000_CRCERRS to E1000_TSCTFC. | |
815 - */ | |
816 - rtx_e1000_register_set32(hw_ctx, E1000_CTRL, | |
817 - E1000_CMD_ASDE | | |
818 - E1000_CMD_SLU); | |
819 - rtx_e1000_register_unset32(hw_ctx, E1000_CTRL, | |
820 - E1000_CMD_LRST | | |
821 - E1000_CMD_FRCSPD | | |
822 - E1000_CMD_PHY_RST | | |
823 - E1000_CMD_ILOS | | |
824 - E1000_CMD_VME); | |
825 - rtx_e1000_register_write32(hw_ctx, E1000_FCAH, 0); | |
826 - rtx_e1000_register_write32(hw_ctx, E1000_FCAL, 0); | |
827 - rtx_e1000_register_write32(hw_ctx, E1000_FCT, 0); | |
828 - rtx_e1000_register_write32(hw_ctx, E1000_FCTTV, 0); | |
829 - /* | |
830 - * XXX: Using int i clashes with another int i from the | |
831 - * "parent" chunk: | |
832 - */ | |
833 - for (int j = 0; j != 64; ++j) | |
834 - rtx_e1000_register_write32(hw_ctx, E1000_CRCERRS + j * 4, 0); | |
835 - | |
836 - ${Log::info("adapter_setup: general configuration done")}; | |
837 - } | |
599 + rtx_e1000_alloc_tx_ressources(${self}); | 838 + rtx_e1000_alloc_tx_ressources(${self}); |
600 + } | 839 } |
601 + | 840 |
602 + map | 841 map |
603 + { | 842 { |
843 - rx_ring: ((${self})->rx_ring); | |
844 - //tx_ring: ((${self})->tx_ring); XXX Circular dep with Context | |
604 + descs: ((${self})->descs); // TODO: fix cast pour directement avoir les descs | 845 + descs: ((${self})->descs); // TODO: fix cast pour directement avoir les descs |
605 + desc_size: sizeof(/* XXX ${e1000::TxDescriptor} */int); | 846 + desc_size: sizeof(/* XXX ${e1000::TxDescriptor} */int); |
606 + } | 847 } |
607 + } | 848 } |
608 + | 849 |
850 - template type e1000::Register() | |
609 + template type e1000::Context() | 851 + template type e1000::Context() |
610 + { | 852 { |
853 - decl data_types() | |
611 + decl data_types() | 854 + decl data_types() |
612 + { | 855 { |
856 - E1000_CTRL = 0x00000, /* Device Control - RW */ | |
857 - E1000_CTRL_DUP = 0x00004, /* Device Control Duplicate (Shadow) - RW */ | |
858 - E1000_STATUS = 0x00008, /* Device Status - RO */ | |
859 - E1000_EEPROM_FLASH = 0x00010, /* EEPROM/Flash Control - RW */ | |
860 - E1000_EEPROM_READ = 0x00014, /* EEPROM Read - RW */ | |
861 - E1000_CTRL_EXT = 0x00018, /* Extended Device Control - RW */ | |
862 - E1000_FLA = 0x0001C, /* Flash Access - RW */ | |
863 - E1000_MDIC = 0x00020, /* MDI Control - RW */ | |
864 - E1000_IMS = 0x000D0, /* Interrupt Mask Set */ | |
865 - E1000_IMC = 0x000D8, /* Interrupt Mask Clear */ | |
866 - E1000_ICR = 0x000C0, /* Interrupt Cause Read - R/clr */ | |
867 - E1000_FCAL = 0x00028, /* Flow Control Address Low */ | |
868 - E1000_FCAH = 0x0002c, /* Flow Control Address High */ | |
869 - E1000_FCT = 0x00030, /* Flow Control Type */ | |
870 - E1000_RCTL = 0x00100, /* Receive Control */ | |
871 - E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value */ | |
872 - E1000_TCTL = 0x00400, /* Transmit Control */ | |
873 - E1000_CRCERRS = 0x04000, /* CRC Error Count (base address of the statistic register spaces) */ | |
874 - E1000_RAL = 0x05400, /* Receive Address Low */ | |
875 - E1000_RAH = 0x05404, /* Receive Address High */ | |
876 - E1000_MTA = 0x05200, /* Multicast Table Array */ | |
877 - E1000_RDBAL = 0x02800, /* Receive Descriptor Base Address (Low 32 bits) */ | |
878 - E1000_RDBAH = 0x02804, /* Receive Descriptor Base Address (High 32 bits) */ | |
879 - E1000_RDLEN = 0x02808, /* Receive Descriptor Length */ | |
880 - E1000_RDH = 0x02810, /* Receive Descriptor Head */ | |
881 - E1000_RDT = 0x02818, /* Receive Descriptor Tail */ | |
882 - E1000_TDBAL = 0x03800, /* Transmit Descriptor Base Address (Low 32 bits) */ | |
883 - E1000_TDBAH = 0x03804, /* Transmit Descriptor Base Address (High 33 bits) */ | |
884 - E1000_TDLEN = 0x03808, /* Transmit Descriptor Length */ | |
885 - E1000_TDH = 0x03810, /* Transmit Descriptor Head */ | |
886 - E1000_TDT = 0x03818, /* Transmit Descriptor Tail */ | |
613 + ${e1000::MMIO} io; | 887 + ${e1000::MMIO} io; |
614 + ${e1000::TxRing} tx_ring; | 888 + ${e1000::TxRing} tx_ring; |
615 + ${e1000::RxRing} rx_ring; | 889 + ${e1000::RxRing} rx_ring; |
616 + } | 890 } |
617 + | 891 |
892 - method init(Builtin::number value) | |
618 + chunk LKM::includes() | 893 + chunk LKM::includes() |
619 + { | 894 { |
895 - ${self} = ${value}; | |
620 + #include <linux/types.h> | 896 + #include <linux/types.h> |
621 + } | 897 } |
622 + | 898 |
899 - map | |
900 - { | |
901 - } | |
902 - } | |
903 - | |
904 - template type e1000::Commands() | |
905 - { | |
906 - decl data_types() | |
907 - { | |
908 - E1000_CMD_FD = 0x00000001, /* Full duplex.0=half; 1=full */ | |
909 - E1000_CMD_BEM = 0x00000002, /* Endian Mode.0=little,1=big */ | |
910 - E1000_CMD_PRIOR = 0x00000004, /* Priority on PCI. 0=rx,1=fair */ | |
911 - E1000_CMD_GIO_MASTER_DISABLE = 0x00000004, /* Blocks new Master requests */ | |
912 - E1000_CMD_LRST = 0x00000008, /* Link reset. 0=normal,1=reset */ | |
913 - E1000_CMD_TME = 0x00000010, /* Test mode. 0=normal,1=test */ | |
914 - E1000_CMD_SLE = 0x00000020, /* Serial Link on 0=dis,1=en */ | |
915 - E1000_CMD_ASDE = 0x00000020, /* Auto-speed detect enable */ | |
916 - E1000_CMD_SLU = 0x00000040, /* Set link up (Force Link) */ | |
917 - E1000_CMD_ILOS = 0x00000080, /* Invert Loss-Of Signal */ | |
918 - E1000_CMD_SPD_SEL = 0x00000300, /* Speed Select Mask */ | |
919 - E1000_CMD_SPD_10 = 0x00000000, /* Force 10Mb */ | |
920 - E1000_CMD_SPD_100 = 0x00000100, /* Force 100Mb */ | |
921 - E1000_CMD_SPD_1000 = 0x00000200, /* Force 1Gb */ | |
922 - E1000_CMD_BEM32 = 0x00000400, /* Big Endian 32 mode */ | |
923 - E1000_CMD_FRCSPD = 0x00000800, /* Force Speed */ | |
924 - E1000_CMD_FRCDPX = 0x00001000, /* Force Duplex */ | |
925 - E1000_CMD_D_UD_EN = 0x00002000, /* Dock/Undock enable */ | |
926 - E1000_CMD_D_UD_POLARITY = 0x00004000, /* Defined polarity of Dock/Undock indication in SDP[0] */ | |
927 - E1000_CMD_FORCE_PHY_RESET = 0x00008000, /* Reset both PHY ports, through PHYRST_N pin */ | |
928 - E1000_CMD_EXT_LINK_EN = 0x00010000, /* enable link status from external LINK_0 and LINK_1 pins */ | |
929 - E1000_CMD_SWDPIN0 = 0x00040000, /* SWDPIN 0 value */ | |
930 - E1000_CMD_SWDPIN1 = 0x00080000, /* SWDPIN 1 value */ | |
931 - E1000_CMD_SWDPIN2 = 0x00100000, /* SWDPIN 2 value */ | |
932 - E1000_CMD_SWDPIN3 = 0x00200000, /* SWDPIN 3 value */ | |
933 - E1000_CMD_SWDPIO0 = 0x00400000, /* SWDPIN 0 Input or output */ | |
934 - E1000_CMD_SWDPIO1 = 0x00800000, /* SWDPIN 1 input or output */ | |
935 - E1000_CMD_SWDPIO2 = 0x01000000, /* SWDPIN 2 input or output */ | |
936 - E1000_CMD_SWDPIO3 = 0x02000000, /* SWDPIN 3 input or output */ | |
937 - E1000_CMD_RST = 0x04000000, /* Global reset */ | |
938 - E1000_CMD_RFCE = 0x08000000, /* Receive Flow Control enable */ | |
939 - E1000_CMD_TFCE = 0x10000000, /* Transmit flow control enable */ | |
940 - E1000_CMD_RTE = 0x20000000, /* Routing tag enable */ | |
941 - E1000_CMD_VME = 0x40000000, /* IEEE VLAN mode enable */ | |
942 - E1000_CMD_PHY_RST = 0x80000000, /* PHY Reset */ | |
943 - E1000_CMD_SW2FW_INT = 0x02000000, /* Initiate an interrupt to manageability engine */ | |
944 - E1000_INTR_TXDW = 0x00000001, /* Transmit desc written back */ | |
945 - E1000_INTR_TXQE = 0x00000002, /* Transmit Queue empty */ | |
946 - E1000_INTR_LSC = 0x00000004, /* Link Status Change */ | |
947 - E1000_INTR_RXSEQ = 0x00000008, /* rx sequence error */ | |
948 - E1000_INTR_RXDMT0 = 0x00000010, /* rx desc min. threshold (0) */ | |
949 - E1000_INTR_RXO = 0x00000040, /* rx overrun */ | |
950 - E1000_INTR_RXT0 = 0x00000080, /* rx timer intr (ring 0) */ | |
951 - E1000_INTR_MDAC = 0x00000200, /* MDIO access complete */ | |
952 - E1000_RAH_AV = (1 << 31), /* Set the MAC Address as Valid */ | |
953 - E1000_RCTL_EN = (1 << 1), /* Receiver Enable */ | |
954 - E1000_RCTL_BSEX = (1 << 25), /* Buffer Size Extension */ | |
955 - E1000_RCTL_BSIZE_256 = ((1 << 16) | (1 << 17)), | |
956 - E1000_RCTL_BSIZE_512 = (1 << 17), | |
957 - E1000_RCTL_BSIZE_1024 = (1 << 16), | |
958 - E1000_RCTL_BSIZE_2048 = 0, | |
959 - E1000_RCTL_BSIZE_4096 = (E1000_RCTL_BSEX | (1 << 16) | (1 << 17)), | |
960 - E1000_RCTL_BSIZE_8192 = (E1000_RCTL_BSEX | (1 << 17)), | |
961 - E1000_RCTL_BSIZE_16384 = (E1000_RCTL_BSEX | (1 << 16)), | |
962 - E1000_TCTL_EN = (1 << 1), /* Transmitter Enable */ | |
963 - E1000_TCTL_PSP = (1 << 3), /* Pad Short Packet */ | |
964 - } | |
965 - | |
966 - map | |
967 - { | |
968 - } | |
969 - } | |
970 - | |
971 - template type e1000::TxDescriptorFlags() | |
972 - { | |
973 - decl data_types() | |
974 - { | |
975 - E1000_TXD_DTYP_D = 0x00100000, /* Data Descriptor */ | |
976 - E1000_TXD_DTYP_C = 0x00000000, /* Context Descriptor */ | |
977 - E1000_TXD_POPTS_IXSM = 0x01, /* Insert IP checksum */ | |
978 - E1000_TXD_POPTS_TXSM = 0x02, /* Insert TCP/UDP checksum */ | |
979 - E1000_TXD_CMD_EOP = 0x01000000, /* End of Packet */ | |
980 - E1000_TXD_CMD_IFCS = 0x02000000, /* Insert FCS (Ethernet CRC) */ | |
981 - E1000_TXD_CMD_IC = 0x04000000, /* Insert Checksum */ | |
982 - E1000_TXD_CMD_RS = 0x08000000, /* Report Status */ | |
983 - E1000_TXD_CMD_RPS = 0x10000000, /* Report Packet Sent */ | |
984 - E1000_TXD_CMD_DEXT = 0x20000000, /* Descriptor extension (0 = legacy) */ | |
985 - E1000_TXD_CMD_VLE = 0x40000000, /* Add VLAN tag */ | |
986 - E1000_TXD_CMD_IDE = 0x80000000, /* Enable Tidv register */ | |
987 - E1000_TXD_STAT_DD = 0x00000001, /* Descriptor Done */ | |
988 - E1000_TXD_STAT_EC = 0x00000002, /* Excess Collisions */ | |
989 - E1000_TXD_STAT_LC = 0x00000004, /* Late Collisions */ | |
990 - E1000_TXD_STAT_TU = 0x00000008, /* Transmit underrun */ | |
991 - E1000_TXD_CMD_TCP = 0x01000000, /* TCP packet */ | |
992 - E1000_TXD_CMD_IP = 0x02000000, /* IP packet */ | |
993 - E1000_TXD_CMD_TSE = 0x04000000, /* TCP Seg enable */ | |
994 - E1000_TXD_STAT_TC = 0x00000004, /* Tx Underrun */ | |
995 - } | |
996 - | |
997 - map | |
998 - { | |
999 - } | |
1000 - } | |
1001 - | |
1002 - /* TODO: make that a method of e1000::Context */ | |
1003 - template sequence e1000::print_status(Ethernet::Device rtx_ether_ctx) | |
1004 - { | |
1005 - chunk LKM::prototypes() | |
623 + chunk LKM::prototypes() | 1006 + chunk LKM::prototypes() |
624 + { | 1007 { |
625 + static void rtx_e1000_print_status(${e1000::Context.ref}); | 1008 static void rtx_e1000_print_status(${e1000::Context.ref}); |
626 + } | 1009 } |
627 + | 1010 |
1011 - chunk LKM::code() | |
628 + chunk LKM::code() | 1012 + chunk LKM::code() |
629 + { | 1013 { |
630 + static void rtx_e1000_print_status(${e1000::Context.ref} hw_ctx) | 1014 static void rtx_e1000_print_status(${e1000::Context.ref} hw_ctx) |
631 + { | 1015 { |
1016 - unsigned int status = rtx_e1000_register_read32(hw_ctx, E1000_STATUS); | |
1017 - ${Log::info("card status:")}; | |
1018 - /* | |
1019 - * we can't use Log::info below because it just accept a string | |
1020 - * (as opposed to a format string with its parameters). | |
1021 - */ | |
632 + unsigned int status = rtx_e1000_reg_read32(hw_ctx, E1000_STATUS); | 1022 + unsigned int status = rtx_e1000_reg_read32(hw_ctx, E1000_STATUS); |
633 + ${Log::info("card status:")}; | 1023 + ${Log::info("card status:")}; |
634 + // XXX We can't use Log::info below because it just accept a | 1024 + // XXX We can't use Log::info below because it just accept a |
635 + // string (as opposed to a format string with its parameters): | 1025 + // string (as opposed to a format string with its parameters): |
636 + pr_info("\tRegister value: 0x%x\n", status); | 1026 pr_info("\tRegister value: 0x%x\n", status); |
637 + pr_info("\tMode: %s\n", (status & 1) ? "Full": "Half"); | 1027 pr_info("\tMode: %s\n", (status & 1) ? "Full": "Half"); |
638 + pr_info("\tLink: %s\n", (status & 2) ? "Up" : "Down"); | 1028 pr_info("\tLink: %s\n", (status & 2) ? "Up" : "Down"); |
639 + pr_info("\tTransmission: %s\n", (status & 4) ? "Paused" : "Ok"); | 1029 @@ -727,300 +572,178 @@ |
640 + pr_info("\tInterface: %s\n", (status & 3) == 3 ? "Up" : "Down"); | 1030 } |
641 + } | 1031 } |
642 + } | 1032 |
643 + | 1033 - chunk ::CALL() |
644 + chunk Ethernet::HardwareContext() | 1034 + chunk Ethernet::HardwareContext() |
645 + { | 1035 { |
1036 - rtx_e1000_print_status(&${rtx_ether_ctx}->hw_ctx); | |
1037 - } | |
1038 - } | |
1039 - | |
1040 - /* | |
1041 - * We should have been able to do something along those lines, but | |
1042 - * it didn't work so we made the call manually. | |
1043 - * | |
1044 - * Ideally: | |
1045 - * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, E1000_STATUS)}; | |
1046 - * | |
1047 - * Ideally2, not sure about the syntax on the register parameter: | |
1048 - * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, ${e1000::Register.E1000_STATUS})}; | |
1049 - * | |
1050 - * "Acceptable": | |
1051 - * ${e1000::Register} reg_status; | |
1052 - * ${e1000.init(E1000_STATUS); // didn't work, so we used the next line | |
1053 - * reg_status = E1000_STATUS; | |
1054 - * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, reg_status)}; | |
1055 - * | |
1056 - * TODO: make them methods of e1000::Context | |
1057 - */ | |
1058 - template sequence e1000::register_read32(e1000::Context ctx, e1000::Register reg_offset) | |
1059 - { | |
1060 - chunk LKM::prototypes() | |
1061 - { | |
1062 - /* FIXME: See issue #54 */ | |
1063 - static unsigned int rtx_e1000_register_read32(/*const*/ ${e1000::Context.ref}, unsigned int); | |
646 + ${e1000::Context} hw_ctx; | 1064 + ${e1000::Context} hw_ctx; |
647 + } | 1065 } |
648 + | 1066 |
1067 - chunk LKM::code() | |
649 + chunk Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx, Builtin::symbol ioaddr) | 1068 + chunk Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx, Builtin::symbol ioaddr) |
650 + { | 1069 { |
651 + { | 1070 - /* FIXME: See issue #54 */ |
1071 - static unsigned int rtx_e1000_register_read32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset) | |
1072 { | |
1073 - return ioread32(ctx->ioaddr + reg_offset); | |
652 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | 1074 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; |
653 + ${local.hw_ctx.io.init(local.ioaddr)}; | 1075 + ${local.hw_ctx.io.init(local.ioaddr)}; |
654 + ${local.hw_ctx.rx_ring.init(local.hw_ctx.io, config.rx_ring_size)}; | 1076 + ${local.hw_ctx.rx_ring.init(local.hw_ctx.io, config.rx_ring_size)}; |
655 + ${local.hw_ctx.tx_ring.init(local.hw_ctx.io, config.tx_ring_size)}; | 1077 + ${local.hw_ctx.tx_ring.init(local.hw_ctx.io, config.tx_ring_size)}; |
656 + } | 1078 } |
657 + } | 1079 } |
658 + | 1080 |
1081 - chunk ::CALL() | |
659 + chunk Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx) | 1082 + chunk Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx) |
660 + { | 1083 { |
661 + { | 1084 - rtx_e1000_register_read32(${ctx}, ${reg_offset}); |
1085 - } | |
1086 - } | |
1087 - | |
1088 - template sequence e1000::register_write32(e1000::Context ctx, e1000::Register reg_offset, ::number value) | |
1089 - { | |
1090 - chunk LKM::prototypes() | |
1091 - { | |
1092 - /* FIXME: See issue #54 */ | |
1093 - static void rtx_e1000_register_write32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int); | |
1094 - } | |
1095 - | |
1096 - chunk LKM::code() | |
1097 - { | |
1098 - /* FIXME: See issue #54 */ | |
1099 - static void rtx_e1000_register_write32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value) | |
1100 { | |
1101 - iowrite32(value, ctx->ioaddr + reg_offset); | |
662 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | 1102 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; |
663 + // XXX #46: ${local.hw_ctx.io.write32(E1000_CTRL, E1000_CMD_RST)}; | 1103 + // XXX #46: ${local.hw_ctx.io.write32(E1000_CTRL, E1000_CMD_RST)}; |
664 + rtx_e1000_reg_write32(hw_ctx, E1000_CTRL, E1000_CMD_RST); | 1104 + rtx_e1000_reg_write32(hw_ctx, E1000_CTRL, E1000_CMD_RST); |
665 + udelay(10); // TODO: abstract this too... | 1105 + udelay(10); // TODO: abstract this too... |
666 + ${Log::info("adapter has been reset")}; | 1106 + ${Log::info("adapter has been reset")}; |
667 + } | 1107 } |
668 + } | 1108 } |
669 + | 1109 |
1110 - chunk ::CALL() | |
670 + chunk Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx) | 1111 + chunk Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx) |
671 + { | 1112 { |
1113 - rtx_e1000_register_write32(${ctx}, ${reg_offset}, ${value}); | |
1114 - } | |
1115 - } | |
672 + { | 1116 + { |
673 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | 1117 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; |
674 + // Shamelessly borrowed from Minix | 1118 + // Shamelessly borrowed from Minix |
675 + for (int i = 0; i < 3; ++i) { | 1119 + for (int i = 0; i < 3; ++i) { |
676 + rtx_e1000_reg_write32(hw_ctx, E1000_EEPROM_READ, (i << 8) | 1); | 1120 + rtx_e1000_reg_write32(hw_ctx, E1000_EEPROM_READ, (i << 8) | 1); |
684 + // parameter (so we can get back our e1000::Context) it | 1128 + // parameter (so we can get back our e1000::Context) it |
685 + // seems inadequate to set this in another way: | 1129 + // seems inadequate to set this in another way: |
686 + ${local.rtx_ether_ctx.dev_addr}[i * 2] = value & 0xff; | 1130 + ${local.rtx_ether_ctx.dev_addr}[i * 2] = value & 0xff; |
687 + ${local.rtx_ether_ctx.dev_addr}[i * 2 + 1] = (value >> 8) & 0xff; | 1131 + ${local.rtx_ether_ctx.dev_addr}[i * 2 + 1] = (value >> 8) & 0xff; |
688 + } | 1132 + } |
689 + | 1133 |
1134 - template sequence e1000::register_set32(e1000::Context ctx, e1000::Register reg_offset, ::number value) | |
1135 - { | |
1136 - chunk LKM::prototypes() | |
1137 - { | |
1138 - /* FIXME: See issue #54 */ | |
1139 - static void rtx_e1000_register_set32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int); | |
1140 - } | |
1141 - | |
1142 - chunk LKM::code() | |
1143 - { | |
1144 - /* FIXME: See issue #54 */ | |
1145 - static void rtx_e1000_register_set32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value) | |
1146 - { | |
1147 - iowrite32(rtx_e1000_register_read32(ctx, reg_offset) | value, ctx->ioaddr + reg_offset); | |
690 + ${Log::info("mac address loaded from the EEPROM")}; | 1148 + ${Log::info("mac address loaded from the EEPROM")}; |
691 + } | 1149 } |
692 + } | 1150 } |
693 + | 1151 |
1152 - chunk ::CALL() | |
1153 + // For e1000, this part is documented in the Intel Gigabit Ethernet | |
1154 + // Controller Software Developper manual. (You can find it in the | |
1155 + // doc/hardware directory). | |
694 + chunk Ethernet::adapter_setup_rx_tx(Ethernet::Device rtx_ether_ctx) | 1156 + chunk Ethernet::adapter_setup_rx_tx(Ethernet::Device rtx_ether_ctx) |
695 + { | 1157 { |
1158 - rtx_e1000_register_set32(${ctx}, ${reg_offset}, ${value}); | |
1159 - } | |
1160 - } | |
696 + { | 1161 + { |
697 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | 1162 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; |
698 + | 1163 |
1164 - template sequence e1000::register_unset32(e1000::Context ctx, e1000::Register reg_offset, ::number value) | |
1165 - { | |
1166 - chunk LKM::prototypes() | |
1167 - { | |
1168 - /* FIXME: See issue #54 */ | |
1169 - static void rtx_e1000_register_unset32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int); | |
1170 - } | |
699 + // "General Configuration" (section 14.3): | 1171 + // "General Configuration" (section 14.3): |
700 + // | 1172 + // |
701 + // - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection & | 1173 + // - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection & |
702 + // negociation; | 1174 + // negociation; |
703 + // - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation; | 1175 + // - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation; |
720 + rtx_e1000_reg_write32(hw_ctx, E1000_FCAL, 0); | 1192 + rtx_e1000_reg_write32(hw_ctx, E1000_FCAL, 0); |
721 + rtx_e1000_reg_write32(hw_ctx, E1000_FCT, 0); | 1193 + rtx_e1000_reg_write32(hw_ctx, E1000_FCT, 0); |
722 + rtx_e1000_reg_write32(hw_ctx, E1000_FCTTV, 0); | 1194 + rtx_e1000_reg_write32(hw_ctx, E1000_FCTTV, 0); |
723 + for (int i = 0; i != 64; ++i) | 1195 + for (int i = 0; i != 64; ++i) |
724 + rtx_e1000_reg_write32(hw_ctx, E1000_CRCERRS + i * 4, 0); | 1196 + rtx_e1000_reg_write32(hw_ctx, E1000_CRCERRS + i * 4, 0); |
725 + | 1197 |
1198 - chunk LKM::code() | |
1199 - { | |
1200 - /* FIXME: See issue #54 */ | |
1201 - static void rtx_e1000_register_unset32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value) | |
1202 - { | |
1203 - iowrite32(rtx_e1000_register_read32(ctx, reg_offset) & ~value, ctx->ioaddr + reg_offset); | |
726 + ${Log::info("adapter_setup: general configuration done")}; | 1204 + ${Log::info("adapter_setup: general configuration done")}; |
727 + } | 1205 } |
728 + } | 1206 } |
729 + | 1207 |
1208 - chunk ::CALL() | |
730 + chunk Ethernet::adapter_enable_interrupts(Ethernet::Device) | 1209 + chunk Ethernet::adapter_enable_interrupts(Ethernet::Device) |
731 + { | 1210 { |
1211 - rtx_e1000_register_unset32(${ctx}, ${reg_offset}, ${value}); | |
1212 - } | |
1213 - } | |
732 + { | 1214 + { |
733 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | 1215 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; |
734 + rtx_e1000_reg_write32( | 1216 + rtx_e1000_reg_write32( |
735 + hw_ctx, | 1217 + hw_ctx, |
736 + E1000_IMS, | 1218 + E1000_IMS, |
737 + E1000_INTR_TXDW|E1000_INTR_TXQE|E1000_INTR_LSC| | 1219 + E1000_INTR_TXDW|E1000_INTR_TXQE|E1000_INTR_LSC| |
738 + E1000_INTR_RXO|E1000_INTR_RXT0 | 1220 + E1000_INTR_RXO|E1000_INTR_RXT0 |
739 + ); | 1221 + ); |
740 + | 1222 |
1223 - template sequence activate_device_interruption(Ethernet::Device rtx_ether_ctx) | |
1224 - { | |
1225 - chunk ::CALL() | |
1226 - { | |
1227 - rtx_e1000_register_write32(&${rtx_ether_ctx}->hw_ctx, E1000_IMS, | |
1228 - E1000_INTR_TXDW | | |
1229 - E1000_INTR_TXQE | | |
1230 - E1000_INTR_LSC | | |
1231 - E1000_INTR_RXO | | |
1232 - E1000_INTR_RXT0); | |
1233 - } | |
1234 - } | |
1235 - | |
1236 - /* TODO: | |
1237 - * | |
1238 - * Refactor into two methods (one in RxRing and one in TxRing) and make use | |
1239 - * of the new methods in Socket::SKBuff. | |
1240 - */ | |
1241 - template sequence free_rx_tx(Ethernet::Device rtx_ether_ctx) | |
1242 - { | |
1243 - chunk ::CALL() | |
1244 - { | |
1245 - /* | |
1246 - * XXX: Not generated if named "hw_ctx" (which is funny because | |
1247 - * it's used and works in the template right above this one): | |
1248 - */ | |
1249 - ${e1000::Context.ref} hw_ctx_; | |
1250 - hw_ctx_ = &${rtx_ether_ctx}->hw_ctx; | |
1251 - | |
1252 - /* | |
1253 - * Free the rx ring: | |
1254 - * - Unmap and free the skbuffs; | |
1255 - * - Free the descriptors array. | |
1256 - */ | |
1257 - for (int i = 0; i != ${config.rx_ring_size}; ++i) | |
1258 - { | |
1259 - /* | |
1260 - * XXX Leaking casts: | |
1261 - * | |
1262 - * We should go through the rtx types (Socket::SKBuff, | |
1263 - * AbstractSKBuff), but we can't because of the array here, | |
1264 - * which is not supported by the compiler. | |
1265 - */ | |
1266 - dma_unmap_single( | |
1267 - ${rtx_ether_ctx.device}, | |
1268 - *((dma_addr_t *)&(hw_ctx_->rx_ring.skbuffs[i].dma_handle)), | |
1269 - ${config.rx_buffer_len}, | |
1270 - DMA_FROM_DEVICE); | |
1271 - dev_kfree_skb((struct sk_buff *)hw_ctx_->rx_ring.skbuffs[i].skbuff); | |
1272 - } | |
1273 - dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx_->rx_ring.size, | |
1274 - hw_ctx_->rx_ring.base, hw_ctx_->rx_ring.dma_base); | |
1275 - ${Log::info("free_rx_tx: rx ring free'ed")}; | |
1276 - | |
1277 - /* | |
1278 - * Free the tx ring: | |
1279 - * - Free the descriptors array. | |
1280 - */ | |
1281 - dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx_->tx_ring.size, | |
1282 - hw_ctx_->tx_ring.base, hw_ctx_->tx_ring.dma_base); | |
1283 - ${Log::info("free_rx_tx: tx ring free'ed")}; | |
1284 - } | |
1285 - } | |
1286 - | |
1287 - template sequence handle_interrupt(Ethernet::Device rtx_ether_ctx) | |
1288 - { | |
1289 - chunk ::CALL() | |
1290 - { | |
1291 - unsigned int icr = rtx_e1000_register_read32(&${rtx_ether_ctx}->hw_ctx, E1000_ICR); | |
1292 - pr_info("%s: interrupt received, ICR: 0x%x", ${config.name}, icr); | |
1293 - if (icr) | |
1294 - { | |
1295 - if (icr & E1000_INTR_LSC) | |
1296 - { | |
1297 - ${Log::info("handle_interrupt: cable link status changed, dumping card status:")}; | |
1298 - ${e1000::print_status(rtx_ether_ctx)}; | |
1299 - } | |
1300 - if (icr & (E1000_INTR_TXQE|E1000_INTR_TXDW)) | |
1301 - { | |
1302 - ${Log::info("handle_interrupt: TxRing: packet(s) sent")}; | |
1303 - /* | |
1304 - * XXX Do a Rathaxes call (how can I bind | |
1305 - * "&${rtx_ether_ctx}->hw_ctx.tx_ring" to e1000::TxRing easily?) | |
1306 - */ | |
1307 - rtx_e1000_tx_ring_clean(&${rtx_ether_ctx}->hw_ctx.tx_ring); | |
1308 - } | |
1309 - if (icr & E1000_INTR_RXT0) | |
1310 - { | |
1311 - ${Log::info("handle_interrupt: RxRing: packet(s) received")}; | |
1312 - } | |
1313 - if (icr & E1000_INTR_RXO) | |
1314 - { | |
1315 - ${Log::info("handle_interrupt: RxRing: overrun")}; | |
1316 - } | |
1317 - | |
1318 - return IRQ_HANDLED; | |
741 + // XXX We should probably move that elsewhere (it just used to | 1319 + // XXX We should probably move that elsewhere (it just used to |
742 + // be done right after we enabled interrupts when this was | 1320 + // be done right after we enabled interrupts when this was |
743 + // still in lkm.rtx): | 1321 + // still in lkm.rtx): |
744 + ${local.hw_ctx.print_status()}; | 1322 + // XXX #46: ${local.hw_ctx.print_status()}; |
745 + } | 1323 + rtx_e1000_print_status(hw_ctx); |
746 + } | 1324 } |
747 + | 1325 } |
748 + chunk Ethernet::handle_interrupt(Ethernet::Device rtx_ether_ctx) | 1326 - } |
1327 | |
1328 - template sequence e1000::xmit(Ethernet::Device rtx_ether_ctx, Socket::AbstractSKBuff kernel_skb) | |
1329 - { | |
1330 - chunk ::CALL() | |
1331 + chunk Ethernet::disable_interrupts(Ethernet::Device rtx_ether_ctx) | |
1332 { | |
1333 - /* | |
1334 - * Put packets on the TX ring, must return NETDEV_TX_OK or | |
1335 - * NETDEV_TX_BUSY. | |
1336 - */ | |
1337 + { ${Log::info("adapter_disable_interrupts: TBD...")}; } | |
1338 + } | |
1339 | |
1340 - ${Socket::SKBuff} skb; | |
1341 - ${e1000::Context.ref} hw_ctx; | |
1342 - ${e1000::TxRing.ref} tx_ring; | |
1343 - ${Device::AbstractDevice.ref} devp; | |
1344 + chunk Ethernet::adapter_handle_interrupt(Ethernet::Device rtx_ether_ctx) | |
749 + { | 1345 + { |
750 + { | 1346 + { |
751 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | 1347 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; |
752 + unsigned int icr = rtx_e1000_reg_read32(hw_ctx, E1000_ICR); | 1348 + unsigned int icr = rtx_e1000_reg_read32(hw_ctx, E1000_ICR); |
753 + pr_info("%s: interrupt received, ICR: 0x%x", ${config.name}, icr); | 1349 + pr_info("%s: interrupt received, ICR: 0x%x", ${config.name}, icr); |
754 + if (icr) { | 1350 + if (icr) { |
755 + if (icr & E1000_INTR_LSC) { | 1351 + if (icr & E1000_INTR_LSC) { |
756 + ${Log::info("handle_interrupt: cable link status changed, dumping card status:")}; | 1352 + ${Log::info("handle_interrupt: cable link status changed, dumping card status:")}; |
757 + ${local.hw_ctx.print_status()}; | 1353 + // XXX #46: ${local.hw_ctx.print_status()}; |
1354 + rtx_e1000_print_status(hw_ctx); | |
758 + } | 1355 + } |
759 + if (icr & (E1000_INTR_TXQE|E1000_INTR_TXDW)) { | 1356 + if (icr & (E1000_INTR_TXQE|E1000_INTR_TXDW)) { |
760 + ${Log::info("handle_interrupt: TxRing: packet(s) sent")}; | 1357 + ${Log::info("handle_interrupt: TxRing: packet(s) sent")}; |
761 + } | 1358 + } |
762 + if (icr & E1000_INTR_RXT0) { | 1359 + if (icr & E1000_INTR_RXT0) { |
763 + ${Log::info("handle_interrupt: RxRing: packet(s) received")}; | 1360 + ${Log::info("handle_interrupt: RxRing: packet(s) received")}; |
764 + } | 1361 + } |
765 + if (icr & E1000_INTR_RXO) { | 1362 + if (icr & E1000_INTR_RXO) { |
766 + ${Log::info("handle_interrupt: RxRing: overrun")}; | 1363 + ${Log::info("handle_interrupt: RxRing: overrun")}; |
767 + } | 1364 + } |
768 + | 1365 |
1366 - ${local.skb.init(kernel_skb)}; | |
1367 - hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
1368 - tx_ring = &hw_ctx->tx_ring; | |
1369 - devp = (${Device::AbstractDevice.ref})${rtx_ether_ctx.device}; | |
769 + // XXX: This sucks since we don't know the pointcut context: | 1370 + // XXX: This sucks since we don't know the pointcut context: |
770 + return IRQ_HANDLED; | 1371 + return IRQ_HANDLED; |
771 + } | 1372 + } |
772 + } | 1373 + } |
773 + } | 1374 + } |
774 + | 1375 |
1376 - ${Log::info("xmit: skbuff details:")}; | |
1377 - /* | |
1378 - * skb does not expand on the bound C variable (should be | |
1379 - * rtx_skbuff), which is funny because it works for the | |
1380 - * sequence template call right after. | |
1381 - */ | |
1382 - /* | |
1383 - * XXX: doesn't work (I tried to pass self explicitely too): | |
1384 - * ${local.skb.dump_infos()}; | |
1385 - */ | |
1386 - rtx_socket_skbuff_dump_infos(&skb); | |
1387 + chunk Ethernet::adapter_xmit(Ethernet::Device rtx_ether_ctx, Socket::SKBuff rtx_skb) | |
1388 + { | |
1389 + { ${Log::info("adapter_xmit: TBD...")}; } | |
1390 + } | |
1391 | |
1392 - /* | |
1393 - * The transmission is going to be several steps: | |
1394 - * 1. TCP Segmentation Offload & Checksum Offloading: pick a | |
1395 - * descriptor from the tx ring and fill it as a context | |
1396 - * descriptor to allow the card to slice into several packets | |
1397 - * according to the MSS; | |
1398 - * 2. DMA Map the skbuff data as slices of 4096; | |
1399 - * 3. Signal the hardware that data is available via a tx desc. | |
1400 - */ | |
1401 + chunk Ethernet::adapter_disable_rx(Ethernet::Device rtx_ether_ctx) | |
1402 + { | |
1403 + { ${Log::info("adapter_disable_rx: TBD..")}; } | |
1404 + } | |
1405 | |
1406 - /* XXX: same thing wanted to use: ${local.tx_ring.descriptors_remaining()} */ | |
1407 - if (!rtx_e1000_tx_ring_descriptors_remaining(tx_ring)) | |
1408 - return NETDEV_TX_BUSY; | |
1409 + chunk Ethernet::adpater_disable_tx(Ethernet::Device rtx_ether_ctx) | |
1410 + { | |
1411 + { ${Log::info("adapter_disable_tx: TBD..")}; } | |
1412 + } | |
1413 | |
1414 - /* 1. Offloading */ | |
1415 + chunk Ethernet::adapter_free_rx_tx(Ethernet::Device rtx_ether_ctx) | |
1416 + { | |
1417 + { ${Log::info("adapter_free_rx_tx: TBD..")}; } | |
1418 + } | |
1419 | |
1420 - /* XXX: ${local.tx_ring.tso_cksum_offload(skb)}; */ | |
1421 - if (rtx_e1000_tx_ring_tso_cksum_offload(tx_ring, &skb)) | |
1422 - { | |
1423 - ${Log::info("xmit: the packet needs to be fragmented and/or checksummed but this not implemented yet!")}; | |
1424 - goto err_offload; | |
1425 - } | |
1426 | |
1427 - /* 2. Map the data */ | |
775 + method print_status() | 1428 + method print_status() |
776 + { | 1429 + { |
777 + rtx_e1000_print_status(${self}); | 1430 + rtx_e1000_print_status(${self}); |
778 + } | 1431 + } |
779 + | 1432 |
1433 - /* XXX: ${local.skb.map_to(devp.k_device)}; */ | |
1434 - if (rtx_socket_skbuff_map(&skb, ${devp.k_device}, DMA_TO_DEVICE)) | |
1435 - { | |
1436 - ${Log::info("xmit: can't DMA map a SKbuff")}; | |
1437 - goto err_skb_map_to; | |
1438 - } | |
1439 - | |
1440 - /* 3. Update the TX Ring and signal the hardware */ | |
1441 - | |
1442 - /* XXX: ${local.tx_ring.put(skb)}; */ | |
1443 - rtx_e1000_tx_ring_put(tx_ring, &skb); | |
1444 - | |
1445 - /* XXX: ${local.tx_ring.start_xmit(hw_ctx)}; */ | |
1446 - rtx_e1000_tx_ring_start_xmit(tx_ring, hw_ctx); | |
1447 - | |
1448 - return NETDEV_TX_OK; | |
1449 - | |
1450 - err_offload: | |
1451 - err_skb_map_to: | |
1452 - /* XXX: ${local.skb.unmap_to_and_free(local.dev)}; */ | |
1453 - rtx_socket_skbuff_unmap_and_free(&skb, ${devp.k_device}, DMA_TO_DEVICE); | |
1454 - return NETDEV_TX_OK; | |
780 + map | 1455 + map |
781 + { | 1456 + { |
782 + io: ${self}->io; | 1457 + io: ${self}->io; |
783 + rx_ring: ${self}->rx_ring; | 1458 + rx_ring: ${self}->rx_ring; |
784 + tx_ring: ${self}->tx_ring; | 1459 + tx_ring: ${self}->tx_ring; |
785 + } | 1460 } |
786 + } | 1461 } |
787 +} | 1462 } |
788 diff --git a/rathaxes/samples/e1000/e1000ng.rti b/rathaxes/samples/e1000/e1000ng.rti | 1463 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti |
789 new file mode 100755 | 1464 old mode 100755 |
790 --- /dev/null | 1465 new mode 100644 |
791 +++ b/rathaxes/samples/e1000/e1000ng.rti | 1466 --- a/rathaxes/samples/e1000/e1000.rti |
792 @@ -0,0 +1,122 @@ | 1467 +++ b/rathaxes/samples/e1000/e1000.rti |
793 +interface e1000ng : Socket, Ethernet, DMA, PCI, LKM, Builtin | 1468 @@ -1,157 +1,115 @@ |
794 +{ | 1469 interface e1000 : Socket, Ethernet, DMA, PCI, LKM, Builtin |
1470 { | |
1471 - required variable Builtin::number rx_ring_size; | |
1472 - required variable Builtin::number tx_ring_size; | |
1473 - required variable Builtin::number rx_buffer_len; | |
1474 - required variable Builtin::number tx_max_data_per_desc; | |
795 + required variable Builtin::number rx_ring_size; | 1475 + required variable Builtin::number rx_ring_size; |
796 + required variable Builtin::number tx_ring_size; | 1476 + required variable Builtin::number tx_ring_size; |
797 + required variable Builtin::number rx_buffer_len; | 1477 + required variable Builtin::number rx_buffer_len; |
798 + required variable Builtin::number tx_max_data_per_desc; | 1478 + required variable Builtin::number tx_max_data_per_desc; |
799 + | 1479 |
1480 - provided type RxDescriptor | |
800 + // Hardware values/data structures, should probably be in the front-end: | 1481 + // Hardware values/data structures, should probably be in the front-end: |
801 + provided type Register { decl data_types(); } | 1482 + provided type Register { decl data_types(); } |
802 + provided type Command { decl data_types(); } | 1483 + provided type Command { decl data_types(); } |
803 + provided type TxDescriptorFlag { decl data_types(); } | 1484 + provided type TxDescriptorFlag { decl data_types(); } |
804 + provided type RxDescriptor { decl data_types(); } | 1485 + provided type RxDescriptor { decl data_types(); } |
805 + provided type TxDescriptor { decl data_types(); } | 1486 + provided type TxDescriptor { decl data_types(); } |
806 + | 1487 + |
807 + provided type Buffer | 1488 + provided type Buffer |
808 + { | 1489 { |
809 + decl data_types(); | 1490 - chunk LKM::includes(); |
1491 decl data_types(); | |
1492 - method init(); | |
810 + | 1493 + |
811 + method init(Socket::SKBuff, DMA::DMAHandle); | 1494 + method init(Socket::SKBuff, DMA::DMAHandle); |
812 + | 1495 + |
813 + attribute Socket::SKBuff.ref sk_buff; | 1496 + attribute Socket::SKBuff.ref sk_buff; |
814 + attribute DMA::DMAHandle.ref dma; | 1497 + attribute DMA::DMAHandle.ref dma; |
815 + } | 1498 } |
816 + | 1499 |
1500 - provided type TxDescriptor | |
817 + // I wish we could just leave those methods in the Context type but we also | 1501 + // I wish we could just leave those methods in the Context type but we also |
818 + // need them from the rings and that would mean a circular dependency | 1502 + // need them from the rings and that would mean a circular dependency |
819 + // between the context and the rings and Rathaxes can't handle it. | 1503 + // between the context and the rings and Rathaxes can't handle it. |
820 + provided type MMIO | 1504 + provided type MMIO |
821 + { | 1505 { |
822 + decl data_types(); | 1506 decl data_types(); |
1507 - method init(); | |
823 + | 1508 + |
824 + chunk LKM::prototypes(); | 1509 + chunk LKM::prototypes(); |
825 + chunk LKM::code(); | 1510 + chunk LKM::code(); |
826 + | 1511 + |
827 + method init(Builtin::symbol); | 1512 + method init(Builtin::symbol); |
828 + method read32(Register); | 1513 + method read32(Register); |
829 + method write32(Register, Builtin::number); | 1514 + method write32(Register, Builtin::number); |
830 + method set32(Register, Builtin::number); | 1515 + method set32(Register, Builtin::number); |
831 + method unset32(Register, Builtin::number); | 1516 + method unset32(Register, Builtin::number); |
832 + | 1517 + |
833 + attribute Builtin::symbol io; | 1518 + attribute Builtin::symbol.scalar io; |
834 + } | 1519 + } |
835 + | 1520 + |
836 + provided type Ring | 1521 + provided type Ring |
837 + { | 1522 + { |
838 + decl data_types(); | 1523 + decl data_types(); |
840 + chunk LKM::prototypes(); | 1525 + chunk LKM::prototypes(); |
841 + chunk LKM::code(); | 1526 + chunk LKM::code(); |
842 + | 1527 + |
843 + method init(MMIO, Builtin::number, Builtin::number); | 1528 + method init(MMIO, Builtin::number, Builtin::number); |
844 + | 1529 + |
845 + attribute MMIO io; | 1530 + attribute MMIO.scalar io; |
846 + attribute DMA:DMAHandle dma; | 1531 + attribute DMA::DMAHandle.scalar dma; |
847 + attribute Builtin::number size; // Total size in bytes | 1532 + attribute Builtin::number.scalar size; // Total size in bytes |
848 + attribute Builtin::symbol.ref descs; | 1533 + attribute Builtin::symbol.ref descs; |
849 + attribute Buffer.ref buffs; | 1534 + attribute Buffer.ref buffs; |
850 + } | 1535 } |
851 + | 1536 |
852 + provided type RxRing | 1537 provided type RxRing |
853 + { | 1538 { |
854 + decl data_types(); | 1539 decl data_types(); |
855 + | 1540 - method init(); |
1541 | |
1542 - /* XXX: Callback that should be in the front-end: */ | |
1543 - chunk Ethernet::adapter_init_rx(Ethernet::Device); | |
856 + chunk LKM::prototypes(); | 1544 + chunk LKM::prototypes(); |
857 + chunk LKM::code(); | 1545 + chunk LKM::code(); |
858 + | 1546 |
1547 - attribute DMA::DMAHandle.scalar dma_base; | |
1548 - attribute Builtin::number.scalar size; | |
859 + method init(MMIO, Builtin::number); | 1549 + method init(MMIO, Builtin::number); |
860 + method alloc(); // Returns != 0 on failure | 1550 + method alloc(); // Returns != 0 on failure |
861 + | 1551 + |
862 + attribute RxDescriptor descs; | 1552 + attribute RxDescriptor.scalar descs; |
863 + } | 1553 + } |
864 + | 1554 + |
865 + provided type TxRing | 1555 + provided type TxRing |
866 + { | 1556 + { |
867 + decl data_types(); | 1557 + decl data_types(); |
870 + chunk LKM::code(); | 1560 + chunk LKM::code(); |
871 + | 1561 + |
872 + method init(MMIO, Builtin::number); | 1562 + method init(MMIO, Builtin::number); |
873 + method alloc(); // Returns != 0 on failure | 1563 + method alloc(); // Returns != 0 on failure |
874 + | 1564 + |
875 + attribute TxDescriptor descs; | 1565 + attribute TxDescriptor.scalar descs; |
876 + } | 1566 } |
877 + | 1567 |
878 + provided type Context | 1568 provided type Context |
879 + { | 1569 { |
880 + decl data_types(); | 1570 - chunk Ethernet::HardwareContext(); |
881 + | 1571 decl data_types(); |
1572 | |
1573 - /* XXX: | |
1574 - * These callbacks/Hooks which should probably be in the front-end. | |
1575 - * Also, I'm not too happy about the names, it's difficult to make | |
1576 - * the difference between the probe and open parts. | |
1577 - */ | |
1578 - chunk Ethernet::adapter_init_context(Ethernet::Device, | |
1579 - Builtin::number, | |
1580 - Builtin::symbol); | |
882 + chunk LKM::includes(); | 1581 + chunk LKM::includes(); |
883 + chunk LKM::prototypes(); | 1582 + chunk LKM::prototypes(); |
884 + chunk LKM::code(); | 1583 + chunk LKM::code(); |
885 + chunk Ethernet::HardwareContext(); | 1584 + chunk Ethernet::HardwareContext(); |
886 + | 1585 + |
887 + // NOTE: Those callbacks/hooks should probably be in the front-end: | 1586 + // NOTE: Those callbacks/hooks should probably be in the front-end: |
888 + | 1587 + |
889 + // Init the hardware context structure, doesn't allocate anything. | |
890 + chunk Ethernet::adapter_init_context(Ethernet::Device, Builtin::symbol); | 1588 + chunk Ethernet::adapter_init_context(Ethernet::Device, Builtin::symbol); |
891 + | 1589 chunk Ethernet::adapter_reset(Ethernet::Device); |
892 + // Reset the adapter | 1590 chunk Ethernet::adapter_load_mac_address(Ethernet::Device); |
893 + chunk Ethernet::adapter_reset(Ethernet::Device); | 1591 - chunk Ethernet::adapter_setup(Ethernet::Device); |
894 + | |
895 + // Load the MAC address from the EEPROM and save it into the | |
896 + // dev_addr field/attribute of Ethernet::Device. | |
897 + chunk Ethernet::adapter_load_mac_address(Ethernet::Device); | |
898 + | |
899 + // Prepare the device and the resources for rx/tx. | |
900 + chunk Ethernet::adapter_setup_rx_tx(Ethernet::Device); | 1592 + chunk Ethernet::adapter_setup_rx_tx(Ethernet::Device); |
901 + | |
902 + // Enable interrupts. | |
903 + chunk Ethernet::adapter_enable_interrupts(Ethernet::Device); | 1593 + chunk Ethernet::adapter_enable_interrupts(Ethernet::Device); |
904 + | 1594 + chunk Ethernet::adapter_disable_interrupts(Ethernet::Device); |
905 + // Interrupt handler. | 1595 + chunk Ethernet::adapter_handle_interrupt(Ethernet::Device); |
906 + chunk Ethernet::handle_interrupt(Ethernet::Device); | 1596 + chunk Ethernet::adapter_xmit(Ethernet::Device, Socket::SKBuff); |
907 + | 1597 + chunk Ethernet::adapter_disable_rx(Ethernet::Device); |
1598 + chunk Ethernet::adapter_disable_tx(Ethernet::Device); | |
1599 + chunk Ethernet::adapter_free_rx_tx(Ethernet::Device); | |
1600 | |
908 + method print_status(); | 1601 + method print_status(); |
909 + | 1602 + |
910 + attribute MMIO io; | 1603 + attribute MMIO.scalar io; |
911 + attribute RxRing.scalar rx_ring; | 1604 attribute RxRing.scalar rx_ring; |
1605 - /* XXX: circular dependency with Contex: */ | |
1606 - //attribute TxRing.scalar tx_ring; | |
1607 - } | |
1608 - | |
1609 - provided type TxRing | |
1610 - { | |
1611 - chunk LKM::prototypes(); | |
1612 - chunk LKM::code(); | |
1613 - decl data_types(); | |
1614 - method init(); | |
1615 - | |
1616 - /* XXX: Callback that should be in the front-end: */ | |
1617 - chunk Ethernet::adapter_init_tx(Ethernet::Device); | |
1618 - | |
1619 - /* Clean the ring (i.e: move the head closer to the tail): */ | |
1620 - method clean(); | |
1621 - /* Return the number of clean descriptors left in the ring: */ | |
1622 - method descriptors_remaining(); | |
1623 - method tso_cksum_offload(Socket::SKBuff); | |
1624 - method put(Socket::SKBuff); | |
1625 - /* Signal the device that new dirty descriptors are on the ring: */ | |
1626 - method start_xmit(e1000::Context); | |
1627 - } | |
1628 - | |
1629 - /* | |
1630 - * These two types should actually be registers definitions in the frontend: | |
1631 - */ | |
1632 - provided type Register | |
1633 - { | |
1634 - decl data_types(); | |
1635 - method init(Builtin::number); | |
1636 - } | |
1637 - | |
1638 - provided type Commands | |
1639 - { | |
1640 - decl data_types(); | |
1641 - } | |
1642 - | |
1643 - provided type TxDescriptorFlags | |
1644 - { | |
1645 - decl data_types(); | |
1646 - } | |
1647 - | |
1648 - /* | |
1649 - * This should take an e1000::Context as the first argument but this was | |
1650 - * not working as wished. | |
1651 - */ | |
1652 - provided sequence print_status(Ethernet::Device) | |
1653 - { | |
1654 - provided chunk LKM::prototypes(); | |
1655 - provided chunk LKM::code(); | |
1656 - provided chunk ::CALL(); | |
1657 - } | |
1658 - | |
1659 - provided sequence activate_device_interruption(Ethernet::Device) | |
1660 - { | |
1661 - provided chunk ::CALL(); | |
1662 - } | |
1663 - | |
1664 - provided sequence set_up_device(Ethernet::Device) | |
1665 - { | |
1666 - provided chunk ::CALL(); | |
1667 - } | |
1668 - | |
1669 - provided sequence free_rx_tx(Ethernet::Device dev) | |
1670 - { | |
1671 - provided chunk ::CALL(); | |
1672 - } | |
1673 - | |
1674 - provided sequence handle_interrupt(Ethernet::Device) | |
1675 - { | |
1676 - provided chunk ::CALL(); | |
1677 - } | |
1678 - | |
1679 - provided sequence xmit(Ethernet::Device, Socket::AbstractSKBuff) | |
1680 - { | |
1681 - provided chunk ::CALL(); | |
1682 - } | |
1683 - | |
1684 - provided sequence register_read32(e1000::Context, e1000::Register) | |
1685 - { | |
1686 - provided chunk LKM::prototypes(); | |
1687 - provided chunk LKM::code(); | |
1688 - provided chunk ::CALL(); | |
1689 - } | |
1690 - | |
1691 - provided sequence register_write32(e1000::Context, e1000::Register, ::number) | |
1692 - { | |
1693 - provided chunk LKM::prototypes(); | |
1694 - provided chunk LKM::code(); | |
1695 - provided chunk ::CALL(); | |
1696 - } | |
1697 - | |
1698 - provided sequence register_set32(e1000::Context, e1000::Register, ::number) | |
1699 - { | |
1700 - provided chunk LKM::prototypes(); | |
1701 - provided chunk LKM::code(); | |
1702 - provided chunk ::CALL(); | |
1703 - } | |
1704 - | |
1705 - provided sequence register_unset32(e1000::Context, e1000::Register, ::number) | |
1706 - { | |
1707 - provided chunk LKM::prototypes(); | |
1708 - provided chunk LKM::code(); | |
1709 - provided chunk ::CALL(); | |
912 + attribute TxRing.scalar tx_ring; | 1710 + attribute TxRing.scalar tx_ring; |
913 + } | 1711 } |
914 +} | 1712 } |
915 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt | 1713 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt |
1714 old mode 100755 | |
1715 new mode 100644 | |
916 --- a/rathaxes/samples/e1000/ethernet.blt | 1716 --- a/rathaxes/samples/e1000/ethernet.blt |
917 +++ b/rathaxes/samples/e1000/ethernet.blt | 1717 +++ b/rathaxes/samples/e1000/ethernet.blt |
918 @@ -106,7 +106,7 @@ | 1718 @@ -1,4 +1,4 @@ |
1719 -with Ethernet, PCI, LKM, Log, Builtin | |
1720 +with Ethernet, Socket, PCI, LKM, Log, Builtin | |
1721 { | |
1722 template type Ethernet::ProtocolId() | |
1723 { | |
1724 @@ -61,7 +61,7 @@ | |
1725 | |
1726 method init(Builtin::symbol dev) | |
1727 { | |
1728 - ${self} = (${Ethernet::AbstractDevice} *)${dev}; | |
1729 + ${self} = (${Ethernet::AbstractDevice.ref})${dev}; | |
1730 } | |
1731 | |
1732 map | |
1733 @@ -104,9 +104,12 @@ | |
1734 { | |
1735 static int rtx_ethernet_alloc_rx_skbuff(${Ethernet::Device.ref} self, ${Socket::SKBuff.ref} sk_buff, ${Builtin::number} size) | |
919 { | 1736 { |
920 ${Socket::AbstractSKBuff} k_sk_buff = netdev_alloc_skb(${local.self.net_device.k_net_dev}, ${local.size}); | 1737 - ${Socket::AbstractSKBuff} k_sk_buff = netdev_alloc_skb(${local.self.net_device.k_net_dev}, ${local.size}); |
921 if (${local.k_sk_buff) { | 1738 - if (${local.k_sk_buff) { |
922 - ${local.sk_buff.init(local.k_sk_buff, local.size)}; | 1739 - ${local.sk_buff.init(local.k_sk_buff, local.size)}; |
923 + ${local.sk_buff.init(local.k_sk_buff)}; | 1740 + ${Socket::AbstractSKBuff.ref} k_skb = netdev_alloc_skb(${local.self.net_device.k_net_dev}, ${local.size}); |
1741 + if (${local.k_skb}) { | |
1742 + // XXX meh, can't use the init method since we get a copy | |
1743 + // of the pointer, so we have to do this which is | |
1744 + // inconsistent with the rest of code: | |
1745 + sk_buff->skbuff = k_skb; | |
924 return 0; | 1746 return 0; |
925 } | 1747 } |
926 return 1; | 1748 return 1; |
927 @@ -164,34 +164,30 @@ | 1749 @@ -148,7 +151,7 @@ |
1750 } | |
1751 } | |
1752 | |
1753 - template sequence Ethernet::open(Ethernet::Device dev) | |
1754 + template sequence Ethernet::open() | |
1755 { | |
1756 chunk LKM::includes() | |
1757 { | |
1758 @@ -164,60 +167,68 @@ | |
928 { | 1759 { |
929 static int rtx_ethernet_open(struct net_device *dev) | 1760 static int rtx_ethernet_open(struct net_device *dev) |
930 { | 1761 { |
931 - /* | 1762 - /* |
932 - * XXX The casts are here because the compiler doesn't resolve | 1763 - * XXX The casts are here because the compiler doesn't resolve |
937 ${local.rtx_net_dev.init(local.dev)}; | 1768 ${local.rtx_net_dev.init(local.dev)}; |
938 } | 1769 } |
939 ${Ethernet::Device.ref} rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx}; | 1770 ${Ethernet::Device.ref} rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx}; |
940 | 1771 |
941 - int error; | 1772 - int error; |
942 + ${pointcut Ethernet::adapter_setup_rx_tx(local.rtx_ether_ctx)}; | 1773 - { |
943 + | |
944 { | |
945 - ${Log::info("installing the interrupt handler")}; | 1774 - ${Log::info("installing the interrupt handler")}; |
946 + ${Log::info("Installing the interrupt handler")}; | 1775 - } |
947 } | |
948 - error = request_irq(${local.rtx_ether_ctx.irq}, | 1776 - error = request_irq(${local.rtx_ether_ctx.irq}, |
949 - rtx_ethernet_interrupt_handler, | 1777 - rtx_ethernet_interrupt_handler, |
950 - IRQF_SHARED, | 1778 - IRQF_SHARED, |
951 - ${config.name}, | 1779 - ${config.name}, |
952 - dev); | 1780 - dev); |
953 - if (error) | 1781 - if (error) |
954 - { | 1782 - { |
1783 + ${pointcut Ethernet::adapter_setup_rx_tx(local.rtx_ether_ctx)}; | |
1784 + | |
1785 + ${Log::info("Installing the interrupt handler")}; | |
955 + int error = request_irq( | 1786 + int error = request_irq( |
956 + ${local.rtx_ether_ctx.irq}, | 1787 + ${local.rtx_ether_ctx.irq}, |
957 + rtx_ethernet_interrupt_handler, | 1788 + rtx_ethernet_interrupt_handler, |
958 + IRQF_SHARED, | 1789 + IRQF_SHARED, |
959 + ${config.name}, | 1790 + ${config.name}, |
970 + | 1801 + |
971 + ${pointcut Ethernet::adapter_enable_interrupts(local.rtx_ether_ctx)}; | 1802 + ${pointcut Ethernet::adapter_enable_interrupts(local.rtx_ether_ctx)}; |
972 | 1803 |
973 return 0; | 1804 return 0; |
974 } | 1805 } |
975 @@ -269,7 +265,7 @@ | 1806 } |
1807 + | |
1808 + /* XXX This chunk should be removed (see #26) */ | |
1809 + chunk ::CALL() | |
1810 + { | |
1811 + } | |
1812 } | |
1813 | |
1814 - template sequence Ethernet::send(Ethernet::Device dev, Socket::AbstractSKBuff skb) | |
1815 + template sequence Ethernet::send() | |
1816 { | |
1817 chunk LKM::prototypes() | |
1818 { | |
1819 - static int rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev); | |
1820 + static int rtx_ethernet_xmit(struct sk_buff *skb, struct net_device *dev); | |
1821 } | |
1822 | |
1823 chunk LKM::code() | |
1824 { | |
1825 - static int rtx_ethernet_xmit(struct sk_buff* kernel_skb, struct net_device *net_dev) | |
1826 + static int rtx_ethernet_xmit(struct sk_buff *k_skb, struct net_device *net_dev) | |
1827 { | |
1828 ${Ethernet::Device.ref} rtx_ether_ctx = netdev_priv(net_dev); | |
1829 - ${Socket::AbstractSKBuff.ref} rtx_skb = (${Socket::AbstractSKBuff.ref}) kernel_skb; | |
1830 + ${Socket::SKBuff.ref} rtx_skb; | |
1831 | |
1832 - ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx, local.rtx_skb)}; | |
1833 + ${cast local.k_skb as Socket::AbstractSKBuff.ref}; | |
1834 + ${local.rtx_skb.init(local.k_skb)}; | |
1835 + | |
1836 + ${Log::info("we have one packet to transmit!")}; | |
1837 + ${pointcut Ethernet::adapter_xmit(local.rtx_ether_ctx, local.rtx_skb)}; | |
1838 } | |
1839 } | |
1840 + | |
1841 + /* XXX This chunk should be removed (see #26) */ | |
1842 + chunk ::CALL() | |
1843 + { | |
1844 + } | |
1845 } | |
1846 | |
1847 - template sequence Ethernet::close(Ethernet::Device dev) | |
1848 + template sequence Ethernet::close() | |
1849 { | |
1850 chunk LKM::prototypes() | |
1851 { | |
1852 @@ -226,31 +237,37 @@ | |
1853 | |
1854 chunk LKM::code() | |
1855 { | |
1856 - static int rtx_ethernet_close(struct net_device *dev) | |
1857 + static int rtx_ethernet_close(struct net_device *net_dev) | |
1858 { | |
1859 - ${Ethernet::AbstractDevice.ref} rtx_net_dev; | |
1860 - { /* XXX: I end up with a placeholder if I don't open a scope */ | |
1861 - ${local.rtx_net_dev.init(local.dev)}; | |
1862 - } | |
1863 + ${cast local.net_dev as Ethernet::AbstractDevice.ref}; | |
1864 + ${Ethernet::Device.ref} rtx_ether_ctx = ${local.net_dev.rtx_ether_ctx}; | |
1865 | |
1866 - ${Ethernet::Device.ref} rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx}; | |
1867 + ${pointcut Ethernet::adapter_disable_rx(local.rtx_ether_ctx)}; | |
1868 | |
1869 - /* TODO: change this pointcut into a pointcut/adapter/callback: */ | |
1870 - { | |
1871 - ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)}; | |
1872 - } | |
1873 + netif_tx_disable(net_dev); | |
1874 + ${pointcut Ethernet::adapter_disable_tx(local.rtx_ether_ctx)}; | |
1875 | |
1876 + ${pointcut Ethernet::adapter_disable_interrupts(local.rtx_ether_ctx)}; | |
1877 free_irq(${local.rtx_ether_ctx.irq}, dev); | |
1878 - { | |
1879 - ${Log::info("interrupt handler free'ed")}; | |
1880 - } | |
1881 + ${Log::info("interrupt handler free'ed")}; | |
1882 + | |
1883 + // TODO/XXX: There is definitely more stuff to do around here | |
1884 + // (e.g: clean the rings, flush some stuff...) | |
1885 + | |
1886 + ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)}; | |
1887 + ${pointcut Ethernet::adapter_free_rx_tx(local.rtx_ether_ctx)}; | |
1888 | |
1889 return 0; | |
1890 } | |
1891 } | |
1892 + | |
1893 + /* XXX This chunk should be removed (see #26) */ | |
1894 + chunk ::CALL() | |
1895 + { | |
1896 + } | |
1897 } | |
1898 | |
1899 - template sequence Ethernet::interrupt_handler(Ethernet::Device dev) | |
1900 + template sequence Ethernet::interrupt_handler() | |
1901 { | |
1902 /* | |
1903 * We can't use the irqreturn_t type here because CNornm doesn't know | |
1904 @@ -269,11 +286,16 @@ | |
976 ${Ethernet::Device.ref} rtx_ether_ctx; | 1905 ${Ethernet::Device.ref} rtx_ether_ctx; |
977 rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx}; | 1906 rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx}; |
978 | 1907 |
979 - ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)}; | 1908 - ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)}; |
980 + ${pointcut Ethernet::handle_interrupt(local.rtx_ether_ctx)}; | 1909 + ${pointcut Ethernet::adapter_handle_interrupt(local.rtx_ether_ctx)}; |
981 | 1910 |
982 return IRQ_NONE; | 1911 return IRQ_NONE; |
983 } | 1912 } |
984 @@ -342,12 +338,8 @@ | 1913 } |
1914 + | |
1915 + /* XXX This chunk should be removed (see #26) */ | |
1916 + chunk ::CALL() | |
1917 + { | |
1918 + } | |
1919 } | |
1920 | |
1921 template sequence Ethernet::init() | |
1922 @@ -342,12 +364,8 @@ | |
985 * XXX: the asssignments/casts are here to circumvent | 1923 * XXX: the asssignments/casts are here to circumvent |
986 * typing issues in the compiler (see previous XXX). | 1924 * typing issues in the compiler (see previous XXX). |
987 */ | 1925 */ |
988 - int bars = ${rtx_pci_dev.bars}; | 1926 - int bars = ${rtx_pci_dev.bars}; |
989 unsigned char /* __iomem */ *ioaddr = ${rtx_pci_dev.ioaddr}; | 1927 unsigned char /* __iomem */ *ioaddr = ${rtx_pci_dev.ioaddr}; |
993 - local.ioaddr)}; | 1931 - local.ioaddr)}; |
994 + ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx, local.ioaddr)}; | 1932 + ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx, local.ioaddr)}; |
995 ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)}; | 1933 ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)}; |
996 ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)}; | 1934 ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)}; |
997 memcpy(${local.rtx_ether_ctx.perm_addr}, | 1935 memcpy(${local.rtx_ether_ctx.perm_addr}, |
1936 @@ -355,7 +373,7 @@ | |
1937 ${local.rtx_net_dev.k_net_dev}->addr_len); | |
1938 } | |
1939 | |
1940 - /* This chunk should be removed (see #26) */ | |
1941 + /* XXX This chunk should be removed (see #26) */ | |
1942 chunk ::CALL() | |
1943 { | |
1944 } | |
1945 @@ -377,7 +395,7 @@ | |
1946 free_netdev(${local.rtx_net_dev.k_net_dev}); | |
1947 } | |
1948 | |
1949 - /* This chunk should be removed (see #26) */ | |
1950 + /* XXX This chunk should be removed (see #26) */ | |
1951 chunk ::CALL() | |
1952 { | |
1953 } | |
998 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti | 1954 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti |
1955 old mode 100755 | |
1956 new mode 100644 | |
999 --- a/rathaxes/samples/e1000/ethernet.rti | 1957 --- a/rathaxes/samples/e1000/ethernet.rti |
1000 +++ b/rathaxes/samples/e1000/ethernet.rti | 1958 +++ b/rathaxes/samples/e1000/ethernet.rti |
1001 @@ -28,8 +28,12 @@ | 1959 @@ -2,16 +2,16 @@ |
1960 { | |
1961 required variable Builtin::string ifname; | |
1962 | |
1963 - provided type ProtocolId | |
1964 - { | |
1965 - chunk LKM::prototypes(); | |
1966 - chunk LKM::data(); | |
1967 - chunk LKM::code(); | |
1968 - decl data_types(); | |
1969 + provided type ProtocolId | |
1970 + { | |
1971 + chunk LKM::prototypes(); | |
1972 + chunk LKM::data(); | |
1973 + chunk LKM::code(); | |
1974 + decl data_types(); | |
1975 | |
1976 - attribute Builtin::number.scalar id; | |
1977 - attribute Builtin::string.scalar str; | |
1978 - } | |
1979 + attribute Builtin::number.scalar id; | |
1980 + attribute Builtin::string.scalar str; | |
1981 + } | |
1982 | |
1983 provided type AbstractDevice | |
1984 { | |
1985 @@ -28,72 +28,88 @@ | |
1002 | 1986 |
1003 provided type Device | 1987 provided type Device |
1004 { | 1988 { |
1005 + decl data_types(); | 1989 + decl data_types(); |
1006 + | 1990 + |
1010 + chunk LKM::code(); | 1994 + chunk LKM::code(); |
1011 + | 1995 + |
1012 pointcut Ethernet::HardwareContext(); | 1996 pointcut Ethernet::HardwareContext(); |
1013 | 1997 |
1014 method init(Ethernet::AbstractDevice, PCI::AbstractDevice); | 1998 method init(Ethernet::AbstractDevice, PCI::AbstractDevice); |
1015 @@ -51,7 +55,7 @@ | 1999 - /* |
2000 - * Alloc (the AbstractSKBuff inside) the given SKBuff and initialize | |
2001 - * the SKBuff, return 1 if the allocation failed, 0 on success. | |
2002 - */ | |
2003 + | |
2004 + // Alloc (the AbstractSKBuff inside) the given SKBuff and initialize | |
2005 + // the SKBuff, return 1 if the allocation failed, 0 on success: | |
2006 method alloc_rx_skbuff(Socket::SKBuff, Builtin::number); | |
2007 | |
2008 attribute Device::AbstractDevice.ref device; | |
2009 attribute PCI::AbstractDevice.ref pci_device; | |
2010 attribute Ethernet::AbstractDevice.ref net_device; | |
2011 - /* | |
2012 - * I'd like to use better names here, but I'd like to understand the | |
2013 - * difference between the two first: | |
2014 - */ | |
2015 + | |
2016 + // I'd like to use better names here, but I'd like to understand the | |
2017 + // difference between the two first: | |
2018 attribute Builtin::symbol.ref perm_addr; | |
2019 attribute Builtin::symbol.ref dev_addr; | |
1016 attribute Builtin::symbol.scalar irq; | 2020 attribute Builtin::symbol.scalar irq; |
1017 } | 2021 } |
1018 | 2022 |
1019 - required sequence open(Ethernet::Device) | 2023 - required sequence open(Ethernet::Device) |
1020 + provided sequence open(Ethernet::Device) | 2024 + provided sequence open() |
1021 { | 2025 { |
1022 provided chunk LKM::includes(); | 2026 - provided chunk LKM::includes(); |
1023 provided chunk LKM::prototypes(); | 2027 - provided chunk LKM::prototypes(); |
1024 @@ -62,9 +66,8 @@ | 2028 - provided chunk LKM::code(); |
1025 * Controller Software Developper manual. (You can find it in the | 2029 + provided chunk LKM::includes(); |
1026 * doc/hardware directory). | 2030 + provided chunk LKM::prototypes(); |
1027 */ | 2031 + provided chunk LKM::code(); |
2032 | |
2033 - /* | |
2034 - * For e1000, this part is documented in the Intel Gigabit Ethernet | |
2035 - * Controller Software Developper manual. (You can find it in the | |
2036 - * doc/hardware directory). | |
2037 - */ | |
1028 - provided pointcut Ethernet::adapter_setup(Ethernet::Device); | 2038 - provided pointcut Ethernet::adapter_setup(Ethernet::Device); |
1029 - provided pointcut Ethernet::adapter_init_rx(Ethernet::Device); | 2039 - provided pointcut Ethernet::adapter_init_rx(Ethernet::Device); |
1030 - provided pointcut Ethernet::adapter_init_tx(Ethernet::Device); | 2040 - provided pointcut Ethernet::adapter_init_tx(Ethernet::Device); |
2041 + // Prepare the device and the resources for rx/tx: | |
1031 + provided pointcut Ethernet::adapter_setup_rx_tx(Ethernet::Device); | 2042 + provided pointcut Ethernet::adapter_setup_rx_tx(Ethernet::Device); |
2043 + | |
2044 + // Enable interrupts: | |
1032 + provided pointcut Ethernet::adapter_enable_interrupts(Ethernet::Device); | 2045 + provided pointcut Ethernet::adapter_enable_interrupts(Ethernet::Device); |
1033 } | 2046 } |
1034 | 2047 |
1035 required sequence send(Ethernet::Device, Socket::AbstractSKBuff) | 2048 - required sequence send(Ethernet::Device, Socket::AbstractSKBuff) |
1036 @@ -79,10 +82,12 @@ | 2049 + provided sequence send() |
1037 provided chunk LKM::code(); | 2050 { |
2051 - provided chunk LKM::prototypes(); | |
2052 - provided chunk LKM::code(); | |
2053 + provided chunk LKM::prototypes(); | |
2054 + provided chunk LKM::code(); | |
2055 + | |
2056 + // Put a packet on the tx ring and signal the device: | |
2057 + provided pointcut Ethernet::adapter_xmit(Ethernet::Device, Socket::SKBuff); | |
1038 } | 2058 } |
1039 | 2059 |
2060 - required sequence close(Ethernet::Device) | |
2061 + provided sequence close() | |
2062 { | |
2063 - provided chunk LKM::prototypes(); | |
2064 - provided chunk LKM::code(); | |
2065 + provided chunk LKM::prototypes(); | |
2066 + provided chunk LKM::code(); | |
2067 + | |
2068 + provided pointcut Ethernet::adapter_disable_rx(Ethernet::Device); | |
2069 + provided pointcut Ethernet::adapter_disable_tx(Ethernet::Device); | |
2070 + provided pointcut Ethernet::adapter_disable_interrupts(Ethernet::Device); | |
2071 + | |
2072 + // Clean and free all resources on the rx/tx rings: | |
2073 + provided pointcut Ethernet::adapter_free_rx_tx(Ethernet::Device); | |
2074 } | |
2075 | |
1040 - required sequence interrupt_handler(Ethernet::Device) | 2076 - required sequence interrupt_handler(Ethernet::Device) |
1041 + provided sequence interrupt_handler(Ethernet::Device) | 2077 + provided sequence interrupt_handler() |
1042 { | 2078 { |
1043 provided chunk LKM::prototypes(); | 2079 - provided chunk LKM::prototypes(); |
1044 provided chunk LKM::code(); | 2080 - provided chunk LKM::code(); |
1045 + | 2081 + provided chunk LKM::prototypes(); |
1046 + provided pointcut Ethernet::handle_interrupt(Ethernet::Device); | 2082 + provided chunk LKM::code(); |
2083 + | |
2084 + // Interrupt handler: | |
2085 + provided pointcut Ethernet::adapter_handle_interrupt(Ethernet::Device); | |
1047 } | 2086 } |
1048 | 2087 |
1049 provided sequence init() | 2088 - provided sequence init() |
1050 @@ -90,9 +95,7 @@ | 2089 + provided sequence init() |
1051 provided chunk LKM::data(); | 2090 { |
1052 provided chunk PCI::pci_probe_hook(PCI::Device); | 2091 - provided chunk LKM::data(); |
2092 - provided chunk PCI::pci_probe_hook(PCI::Device); | |
2093 + provided chunk LKM::data(); | |
2094 + provided chunk PCI::pci_probe_hook(PCI::Device); | |
1053 | 2095 |
1054 - provided pointcut Ethernet::adapter_init_context(Ethernet::Device, | 2096 - provided pointcut Ethernet::adapter_init_context(Ethernet::Device, |
1055 - Builtin::number, | 2097 - Builtin::number, |
1056 - Builtin::symbol); | 2098 - Builtin::symbol); |
2099 + // Init the hardware context structure, doesn't allocate anything: | |
1057 + provided pointcut Ethernet::adapter_init_context(Ethernet::Device, Builtin::symbol); | 2100 + provided pointcut Ethernet::adapter_init_context(Ethernet::Device, Builtin::symbol); |
2101 + | |
2102 + // Reset the adapter: | |
1058 provided pointcut Ethernet::adapter_reset(Ethernet::Device); | 2103 provided pointcut Ethernet::adapter_reset(Ethernet::Device); |
2104 + | |
2105 + // Load the MAC address from the EEPROM and save it into the | |
2106 + // dev_addr field/attribute of Ethernet::Device: | |
1059 provided pointcut Ethernet::adapter_load_mac_address(Ethernet::Device); | 2107 provided pointcut Ethernet::adapter_load_mac_address(Ethernet::Device); |
1060 } | 2108 } |
2109 | |
1061 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx | 2110 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx |
2111 old mode 100755 | |
2112 new mode 100644 | |
1062 --- a/rathaxes/samples/e1000/lkm.rtx | 2113 --- a/rathaxes/samples/e1000/lkm.rtx |
1063 +++ b/rathaxes/samples/e1000/lkm.rtx | 2114 +++ b/rathaxes/samples/e1000/lkm.rtx |
1064 @@ -1,34 +1,5 @@ | 2115 @@ -1,40 +1,5 @@ |
1065 device LKM use LKM, PCI, Ethernet, Log, Socket | 2116 device LKM use LKM, PCI, Ethernet, Log, Socket |
1066 { | 2117 { |
1067 - Ethernet::open(Ethernet::Device dev) | 2118 - Ethernet::open(Ethernet::Device dev) |
1068 - { | 2119 - { |
1069 - Log::info("opening the device"); | 2120 - Log::info("opening the device"); |
1091 - { | 2142 - { |
1092 - Log::info("got an interruption"); | 2143 - Log::info("got an interruption"); |
1093 - e1000::handle_interrupt(dev); | 2144 - e1000::handle_interrupt(dev); |
1094 - } | 2145 - } |
1095 - | 2146 - |
1096 Ethernet::send(Ethernet::Device dev, Socket::AbstractSKBuff skb) | 2147 - Ethernet::send(Ethernet::Device dev, Socket::AbstractSKBuff skb) |
2148 - { | |
2149 - Log::info("we have one packet to transmit!"); | |
2150 - e1000::xmit(dev, skb); | |
2151 - } | |
2152 - | |
2153 LKM::init() | |
1097 { | 2154 { |
1098 Log::info("we have one packet to transmit!"); | 2155 Log::info("loading module"); |
2156 @@ -50,7 +15,7 @@ | |
2157 { | |
2158 LKM::name = "rtx_e1k"; | |
2159 LKM::author = "Rathaxes"; | |
2160 - LKM::description = "Hello World Loadable Kernel Module (LKM)"; | |
2161 + LKM::description = "Rathaxes Intel PCI Gigabit NIC sample driver"; | |
2162 LKM::license = "GPL"; | |
2163 | |
2164 /* | |
2165 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/old_e1000.blt | |
2166 old mode 100755 | |
2167 new mode 100644 | |
2168 copy from rathaxes/samples/e1000/e1000.blt | |
2169 copy to rathaxes/samples/e1000/old_e1000.blt | |
2170 --- a/rathaxes/samples/e1000/e1000.blt | |
2171 +++ b/rathaxes/samples/e1000/old_e1000.blt | |
2172 @@ -170,14 +170,15 @@ | |
2173 for (i = 0; i != ${config.rx_ring_size}; ++i) | |
2174 { | |
2175 ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i]; | |
2176 - // XXX #46: ${rtx_ether_ctx.init_rx_skbuff(local.skbuff, config.rx_buffer_len)}; | |
2177 - if (rtx_ethernet_init_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len})) | |
2178 + // XXX #46: ${rtx_ether_ctx.alloc_rx_skbuff(local.skbuff, config.rx_buffer_len)}; | |
2179 + if (rtx_ethernet_alloc_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len})) | |
2180 { | |
2181 ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")}; | |
2182 goto err_skbuffs_alloc; | |
2183 } | |
2184 - // XXX #46: ${local.skbuff.map_from(rtx_ether_ctx.device)}; | |
2185 - if (rtx_socket_skbuff_map(${local.skbuff}, ${rtx_ether_ctx.device}, RTX_DMA_FROM_DEVICE)) | |
2186 + /* XXX: recuperer le dma handle et le placer correctement dans le descripteur. */ | |
2187 + ${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)} | |
2188 + if (${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)}) | |
2189 { | |
2190 ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")}; | |
2191 goto err_skbuffs_map; | |
2192 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/old_e1000.rti | |
2193 old mode 100755 | |
2194 new mode 100644 | |
2195 copy from rathaxes/samples/e1000/e1000.rti | |
2196 copy to rathaxes/samples/e1000/old_e1000.rti | |
1099 diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt | 2197 diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt |
2198 old mode 100755 | |
2199 new mode 100644 | |
1100 --- a/rathaxes/samples/e1000/socket.blt | 2200 --- a/rathaxes/samples/e1000/socket.blt |
1101 +++ b/rathaxes/samples/e1000/socket.blt | 2201 +++ b/rathaxes/samples/e1000/socket.blt |
1102 @@ -22,16 +22,12 @@ | 2202 @@ -22,16 +22,12 @@ |
1103 { | 2203 { |
1104 decl data_types() | 2204 decl data_types() |
1115 - static int rtx_socket_skbuff_map(${Socket::SKBuff.ref}, ${Device::AbstractDevice.ref}, ${DMA::DMADirection.scalar}); | 2215 - static int rtx_socket_skbuff_map(${Socket::SKBuff.ref}, ${Device::AbstractDevice.ref}, ${DMA::DMADirection.scalar}); |
1116 - static void rtx_socket_skbuff_unmap_and_free(${Socket::SKBuff.ref}, ${Device::AbstractDevice.ref}, ${DMA::DMADirection.scalar}); | 2216 - static void rtx_socket_skbuff_unmap_and_free(${Socket::SKBuff.ref}, ${Device::AbstractDevice.ref}, ${DMA::DMADirection.scalar}); |
1117 } | 2217 } |
1118 | 2218 |
1119 chunk LKM::code() | 2219 chunk LKM::code() |
1120 @@ -63,85 +59,6 @@ | 2220 @@ -52,98 +48,29 @@ |
1121 shinfo->nr_frags, shinfo->gso_size, shinfo->gso_segs, shinfo->gso_type | 2221 * arguments yet. |
2222 */ | |
2223 pr_info( | |
2224 - "\t protocol = %#-5x (%s) ip_summed = %d (%s)\n" | |
2225 - "\t len = %-5u data_len = %-5u head_len = %-5u\n" | |
2226 - "\t nr_frags = %u\n" | |
2227 - "\t gso_size = %-5u gso_segs = %-5u gso_type = %-5u", | |
2228 - /* XXX: can't use ${local.ethernet_proto.id} here (issue #52): */ | |
2229 - ethernet_proto.id, ${local.ethernet_proto.str}, | |
2230 - ${local.self.sk_buff.k_sk_buff}->ip_summed, ip_summed_values[${local.self.sk_buff.k_sk_buff}->ip_summed], | |
2231 - ${local.self.sk_buff.k_sk_buff}->len, ${local.self.sk_buff.k_sk_buff}->data_len, skb_headlen(${local.self.sk_buff.k_sk_buff}), | |
2232 - shinfo->nr_frags, shinfo->gso_size, shinfo->gso_segs, shinfo->gso_type | |
2233 + "\t protocol = %#-5x (%s) ip_summed = %d (%s)\n" | |
2234 + "\t len = %-5u data_len = %-5u head_len = %-5u\n" | |
2235 + "\t nr_frags = %u\n" | |
2236 + "\t gso_size = %-5u gso_segs = %-5u gso_type = %-5u", | |
2237 + /* XXX: can't use ${local.ethernet_proto.id} here (issue #52): */ | |
2238 + ethernet_proto.id, ${local.ethernet_proto.str}, | |
2239 + ${local.self.sk_buff.k_sk_buff}->ip_summed, ip_summed_values[${local.self.sk_buff.k_sk_buff}->ip_summed], | |
2240 + ${local.self.sk_buff.k_sk_buff}->len, ${local.self.sk_buff.k_sk_buff}->data_len, skb_headlen(${local.self.sk_buff.k_sk_buff}), | |
2241 + shinfo->nr_frags, shinfo->gso_size, shinfo->gso_segs, shinfo->gso_type | |
1122 ); | 2242 ); |
1123 } | 2243 } |
1124 - | 2244 - |
1125 - static int rtx_socket_skbuff_map(${Socket::SKBuff.ref} self, | 2245 - static int rtx_socket_skbuff_map(${Socket::SKBuff.ref} self, |
1126 - ${Device::AbstractDevice.ref} dev, | 2246 - ${Device::AbstractDevice.ref} dev, |
1161 - ${local.self.dma_handle} = 0; | 2281 - ${local.self.dma_handle} = 0; |
1162 - } | 2282 - } |
1163 - dev_kfree_skb_any(${local.self.sk_buff.k_sk_buff}); | 2283 - dev_kfree_skb_any(${local.self.sk_buff.k_sk_buff}); |
1164 - ${local.self.sk_buff} = NULL; | 2284 - ${local.self.sk_buff} = NULL; |
1165 - } | 2285 - } |
1166 - } | 2286 } |
1167 - | 2287 |
1168 - /* | 2288 - /* |
1169 - * XXX: the rathaxes argument kernel_skb is not actually bound to the | 2289 - * XXX: the rathaxes argument kernel_skb is not actually bound to the |
1170 - * correct C variable from Ethernet::send() (so I named it as the C | 2290 - * correct C variable from Ethernet::send() (so I named it as the C |
1171 - * variable I needed) | 2291 - * variable I needed) |
1172 - */ | 2292 - */ |
1173 - method init(Socket::AbstractSKBuff kernel_skb, Builtin::number size) | 2293 - method init(Socket::AbstractSKBuff kernel_skb, Builtin::number size) |
1174 - { | 2294 + method init(Socket::AbstractSKBuff k_skb) |
2295 { | |
1175 - ${self.sk_buff} = ${kernel_skb}; | 2296 - ${self.sk_buff} = ${kernel_skb}; |
1176 - ${self.size} = ${size}; | 2297 - ${self.size} = ${size}; |
1177 - ${self.dma_handle} = 0; | 2298 - ${self.dma_handle} = 0; |
1178 - } | 2299 + ${self} = (${Socket::SKBuff.ref})(${k_skb}); |
1179 - | 2300 } |
2301 | |
1180 - method dump_infos() | 2302 - method dump_infos() |
1181 - { | 2303 + method dump_infos() |
1182 - rtx_socket_skbuff_dump_infos(${self}); | 2304 { |
1183 - } | 2305 rtx_socket_skbuff_dump_infos(${self}); |
1184 - | 2306 } |
2307 | |
1185 - method map_to(Device::AbstractDevice dev) | 2308 - method map_to(Device::AbstractDevice dev) |
1186 - { | 2309 - { |
1187 - rtx_socket_skbuff_map(${self}, ${dev}, RTX_DMA_TO_DEVICE); | 2310 - rtx_socket_skbuff_map(${self}, ${dev}, RTX_DMA_TO_DEVICE); |
1188 - } | 2311 - } |
1189 - | 2312 - |
1198 - } | 2321 - } |
1199 - | 2322 - |
1200 - method unmap_from_and_free(Device::AbstractDevice dev) | 2323 - method unmap_from_and_free(Device::AbstractDevice dev) |
1201 - { | 2324 - { |
1202 - rtx_socket_skbuff_unmap_and_free(${self}, ${dev}, RTX_DMA_FROM_DEVICE); | 2325 - rtx_socket_skbuff_unmap_and_free(${self}, ${dev}, RTX_DMA_FROM_DEVICE); |
1203 } | 2326 - } |
1204 | 2327 - |
1205 map | 2328 map |
1206 @@ -151,13 +68,9 @@ | 2329 { |
2330 // Some work may have to be done here in order to access to some | |
2331 @@ -151,13 +78,9 @@ | |
1207 // management can be abstracted from the user. But this is at least | 2332 // management can be abstracted from the user. But this is at least |
1208 // useful for internal use: | 2333 // useful for internal use: |
1209 sk_buff: (${self})->skbuff; | 2334 sk_buff: (${self})->skbuff; |
1210 - // XXX: We need to cast here so we can do things like | 2335 - // XXX: We need to cast here so we can do things like |
1211 - // var.dma_handle = 0; but the type shouldn't be hardcoded (at the | 2336 - // var.dma_handle = 0; but the type shouldn't be hardcoded (at the |
1219 + len: ((struct sk_buff *)((${self})->sk_buff))->len; | 2344 + len: ((struct sk_buff *)((${self})->sk_buff))->len; |
1220 } | 2345 } |
1221 } | 2346 } |
1222 } | 2347 } |
1223 diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti | 2348 diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti |
2349 old mode 100755 | |
2350 new mode 100644 | |
1224 --- a/rathaxes/samples/e1000/socket.rti | 2351 --- a/rathaxes/samples/e1000/socket.rti |
1225 +++ b/rathaxes/samples/e1000/socket.rti | 2352 +++ b/rathaxes/samples/e1000/socket.rti |
1226 @@ -12,20 +12,14 @@ | 2353 @@ -12,20 +12,14 @@ |
1227 { | 2354 { |
1228 chunk LKM::prototypes(); | 2355 chunk LKM::prototypes(); |