Mercurial > archived > louis > epitech > mq > rathaxes
comparison rathaxes_sample_e1000_rewrite_device_dependent_code.patch @ 131:c209851a82de
Wip, start a rewrite of the e1000 device dependent code
author | Louis Opter <kalessin@kalessin.fr> |
---|---|
date | Fri, 03 Jan 2014 15:01:47 +0100 |
parents | |
children | f2e4dd91dc6f |
comparison
equal
deleted
inserted
replaced
130:6359457dce75 | 131:c209851a82de |
---|---|
1 # HG changeset patch | |
2 # Parent 7d00455945ec97c5851ac0d735da7c3cfbd8e39c | |
3 rathaxes: rewrite/refactor all the e1000 device dependent code | |
4 | |
5 diff --git a/notes.txt b/notes.txt | |
6 new file mode 100644 | |
7 --- /dev/null | |
8 +++ b/notes.txt | |
9 @@ -0,0 +1,9 @@ | |
10 +- Too much changes to not start over; | |
11 +- 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); | |
13 +- 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, | |
15 + 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 | |
17 + whole structure field) might not be the best solution but would solve this | |
18 + issue/use case. | |
19 diff --git a/rathaxes/samples/e1000/CMakeLists.txt b/rathaxes/samples/e1000/CMakeLists.txt | |
20 --- a/rathaxes/samples/e1000/CMakeLists.txt | |
21 +++ b/rathaxes/samples/e1000/CMakeLists.txt | |
22 @@ -9,7 +9,6 @@ | |
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 | |
32 pci.blt | |
33 socket.blt | |
34 - e1000.blt | |
35 ethernet.blt) | |
36 | |
37 -IF (LINUX_KBUILD_DIR) | |
38 - ADD_RATHAXES_LKM(e1000 e1000_src) | |
39 -ENDIF (LINUX_KBUILD_DIR) | |
40 +#IF (LINUX_KBUILD_DIR) | |
41 +# ADD_RATHAXES_LKM(e1000 e1000_src) | |
42 +#ENDIF (LINUX_KBUILD_DIR) | |
43 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt | |
44 --- a/rathaxes/samples/e1000/e1000.blt | |
45 +++ b/rathaxes/samples/e1000/e1000.blt | |
46 @@ -170,14 +170,15 @@ | |
47 for (i = 0; i != ${config.rx_ring_size}; ++i) | |
48 { | |
49 ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i]; | |
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() | |
74 + { | |
75 + decl data_types() | |
76 + { | |
77 + E1000_CTRL = 0x00000, /* Device Control - RW */ | |
78 + E1000_CTRL_DUP = 0x00004, /* Device Control Duplicate (Shadow) - RW */ | |
79 + E1000_STATUS = 0x00008, /* Device Status - RO */ | |
80 + E1000_EEPROM_FLASH = 0x00010, /* EEPROM/Flash Control - RW */ | |
81 + E1000_EEPROM_READ = 0x00014, /* EEPROM Read - RW */ | |
82 + E1000_CTRL_EXT = 0x00018, /* Extended Device Control - RW */ | |
83 + E1000_FLA = 0x0001C, /* Flash Access - RW */ | |
84 + E1000_MDIC = 0x00020, /* MDI Control - RW */ | |
85 + E1000_IMS = 0x000D0, /* Interrupt Mask Set */ | |
86 + E1000_IMC = 0x000D8, /* Interrupt Mask Clear */ | |
87 + E1000_ICR = 0x000C0, /* Interrupt Cause Read - R/clr */ | |
88 + E1000_FCAL = 0x00028, /* Flow Control Address Low */ | |
89 + E1000_FCAH = 0x0002c, /* Flow Control Address High */ | |
90 + E1000_FCT = 0x00030, /* Flow Control Type */ | |
91 + E1000_RCTL = 0x00100, /* Receive Control */ | |
92 + E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value */ | |
93 + E1000_TCTL = 0x00400, /* Transmit Control */ | |
94 + E1000_CRCERRS = 0x04000, /* CRC Error Count (base address of the statistic register spaces) */ | |
95 + E1000_RAL = 0x05400, /* Receive Address Low */ | |
96 + E1000_RAH = 0x05404, /* Receive Address High */ | |
97 + E1000_MTA = 0x05200, /* Multicast Table Array */ | |
98 + E1000_RDBAL = 0x02800, /* Receive Descriptor Base Address (Low 32 bits) */ | |
99 + E1000_RDBAH = 0x02804, /* Receive Descriptor Base Address (High 32 bits) */ | |
100 + E1000_RDLEN = 0x02808, /* Receive Descriptor Length */ | |
101 + E1000_RDH = 0x02810, /* Receive Descriptor Head */ | |
102 + E1000_RDT = 0x02818, /* Receive Descriptor Tail */ | |
103 + E1000_TDBAL = 0x03800, /* Transmit Descriptor Base Address (Low 32 bits) */ | |
104 + E1000_TDBAH = 0x03804, /* Transmit Descriptor Base Address (High 33 bits) */ | |
105 + E1000_TDLEN = 0x03808, /* Transmit Descriptor Length */ | |
106 + E1000_TDH = 0x03810, /* Transmit Descriptor Head */ | |
107 + E1000_TDT = 0x03818, /* Transmit Descriptor Tail */ | |
108 + } | |
109 + | |
110 + map | |
111 + { | |
112 + } | |
113 + } | |
114 + | |
115 + template type e1000::Commands() | |
116 + { | |
117 + decl data_types() | |
118 + { | |
119 + E1000_CMD_FD = 0x00000001, /* Full duplex.0=half; 1=full */ | |
120 + E1000_CMD_BEM = 0x00000002, /* Endian Mode.0=little,1=big */ | |
121 + E1000_CMD_PRIOR = 0x00000004, /* Priority on PCI. 0=rx,1=fair */ | |
122 + E1000_CMD_GIO_MASTER_DISABLE = 0x00000004, /* Blocks new Master requests */ | |
123 + E1000_CMD_LRST = 0x00000008, /* Link reset. 0=normal,1=reset */ | |
124 + E1000_CMD_TME = 0x00000010, /* Test mode. 0=normal,1=test */ | |
125 + E1000_CMD_SLE = 0x00000020, /* Serial Link on 0=dis,1=en */ | |
126 + E1000_CMD_ASDE = 0x00000020, /* Auto-speed detect enable */ | |
127 + E1000_CMD_SLU = 0x00000040, /* Set link up (Force Link) */ | |
128 + E1000_CMD_ILOS = 0x00000080, /* Invert Loss-Of Signal */ | |
129 + E1000_CMD_SPD_SEL = 0x00000300, /* Speed Select Mask */ | |
130 + E1000_CMD_SPD_10 = 0x00000000, /* Force 10Mb */ | |
131 + E1000_CMD_SPD_100 = 0x00000100, /* Force 100Mb */ | |
132 + E1000_CMD_SPD_1000 = 0x00000200, /* Force 1Gb */ | |
133 + E1000_CMD_BEM32 = 0x00000400, /* Big Endian 32 mode */ | |
134 + E1000_CMD_FRCSPD = 0x00000800, /* Force Speed */ | |
135 + E1000_CMD_FRCDPX = 0x00001000, /* Force Duplex */ | |
136 + E1000_CMD_D_UD_EN = 0x00002000, /* Dock/Undock enable */ | |
137 + E1000_CMD_D_UD_POLARITY = 0x00004000, /* Defined polarity of Dock/Undock indication in SDP[0] */ | |
138 + E1000_CMD_FORCE_PHY_RESET = 0x00008000, /* Reset both PHY ports, through PHYRST_N pin */ | |
139 + E1000_CMD_EXT_LINK_EN = 0x00010000, /* enable link status from external LINK_0 and LINK_1 pins */ | |
140 + E1000_CMD_SWDPIN0 = 0x00040000, /* SWDPIN 0 value */ | |
141 + E1000_CMD_SWDPIN1 = 0x00080000, /* SWDPIN 1 value */ | |
142 + E1000_CMD_SWDPIN2 = 0x00100000, /* SWDPIN 2 value */ | |
143 + E1000_CMD_SWDPIN3 = 0x00200000, /* SWDPIN 3 value */ | |
144 + E1000_CMD_SWDPIO0 = 0x00400000, /* SWDPIN 0 Input or output */ | |
145 + E1000_CMD_SWDPIO1 = 0x00800000, /* SWDPIN 1 input or output */ | |
146 + E1000_CMD_SWDPIO2 = 0x01000000, /* SWDPIN 2 input or output */ | |
147 + E1000_CMD_SWDPIO3 = 0x02000000, /* SWDPIN 3 input or output */ | |
148 + E1000_CMD_RST = 0x04000000, /* Global reset */ | |
149 + E1000_CMD_RFCE = 0x08000000, /* Receive Flow Control enable */ | |
150 + E1000_CMD_TFCE = 0x10000000, /* Transmit flow control enable */ | |
151 + E1000_CMD_RTE = 0x20000000, /* Routing tag enable */ | |
152 + E1000_CMD_VME = 0x40000000, /* IEEE VLAN mode enable */ | |
153 + E1000_CMD_PHY_RST = 0x80000000, /* PHY Reset */ | |
154 + E1000_CMD_SW2FW_INT = 0x02000000, /* Initiate an interrupt to manageability engine */ | |
155 + E1000_INTR_TXDW = 0x00000001, /* Transmit desc written back */ | |
156 + E1000_INTR_TXQE = 0x00000002, /* Transmit Queue empty */ | |
157 + E1000_INTR_LSC = 0x00000004, /* Link Status Change */ | |
158 + E1000_INTR_RXSEQ = 0x00000008, /* rx sequence error */ | |
159 + E1000_INTR_RXDMT0 = 0x00000010, /* rx desc min. threshold (0) */ | |
160 + E1000_INTR_RXO = 0x00000040, /* rx overrun */ | |
161 + E1000_INTR_RXT0 = 0x00000080, /* rx timer intr (ring 0) */ | |
162 + E1000_INTR_MDAC = 0x00000200, /* MDIO access complete */ | |
163 + E1000_RAH_AV = (1 << 31), /* Set the MAC Address as Valid */ | |
164 + E1000_RCTL_EN = (1 << 1), /* Receiver Enable */ | |
165 + E1000_RCTL_BSEX = (1 << 25), /* Buffer Size Extension */ | |
166 + E1000_RCTL_BSIZE_256 = ((1 << 16) | (1 << 17)), | |
167 + E1000_RCTL_BSIZE_512 = (1 << 17), | |
168 + E1000_RCTL_BSIZE_1024 = (1 << 16), | |
169 + E1000_RCTL_BSIZE_2048 = 0, | |
170 + E1000_RCTL_BSIZE_4096 = (E1000_RCTL_BSEX | (1 << 16) | (1 << 17)), | |
171 + E1000_RCTL_BSIZE_8192 = (E1000_RCTL_BSEX | (1 << 17)), | |
172 + E1000_RCTL_BSIZE_16384 = (E1000_RCTL_BSEX | (1 << 16)), | |
173 + E1000_TCTL_EN = (1 << 1), /* Transmitter Enable */ | |
174 + E1000_TCTL_PSP = (1 << 3), /* Pad Short Packet */ | |
175 + } | |
176 + | |
177 + map | |
178 + { | |
179 + } | |
180 + } | |
181 + | |
182 + template type e1000::TxDescriptorFlag() | |
183 + { | |
184 + decl data_types() | |
185 + { | |
186 + E1000_TXD_DTYP_D = 0x00100000, /* Data Descriptor */ | |
187 + E1000_TXD_DTYP_C = 0x00000000, /* Context Descriptor */ | |
188 + E1000_TXD_POPTS_IXSM = 0x01, /* Insert IP checksum */ | |
189 + E1000_TXD_POPTS_TXSM = 0x02, /* Insert TCP/UDP checksum */ | |
190 + E1000_TXD_CMD_EOP = 0x01000000, /* End of Packet */ | |
191 + E1000_TXD_CMD_IFCS = 0x02000000, /* Insert FCS (Ethernet CRC) */ | |
192 + E1000_TXD_CMD_IC = 0x04000000, /* Insert Checksum */ | |
193 + E1000_TXD_CMD_RS = 0x08000000, /* Report Status */ | |
194 + E1000_TXD_CMD_RPS = 0x10000000, /* Report Packet Sent */ | |
195 + E1000_TXD_CMD_DEXT = 0x20000000, /* Descriptor extension (0 = legacy) */ | |
196 + E1000_TXD_CMD_VLE = 0x40000000, /* Add VLAN tag */ | |
197 + E1000_TXD_CMD_IDE = 0x80000000, /* Enable Tidv register */ | |
198 + E1000_TXD_STAT_DD = 0x00000001, /* Descriptor Done */ | |
199 + E1000_TXD_STAT_EC = 0x00000002, /* Excess Collisions */ | |
200 + E1000_TXD_STAT_LC = 0x00000004, /* Late Collisions */ | |
201 + E1000_TXD_STAT_TU = 0x00000008, /* Transmit underrun */ | |
202 + E1000_TXD_CMD_TCP = 0x01000000, /* TCP packet */ | |
203 + E1000_TXD_CMD_IP = 0x02000000, /* IP packet */ | |
204 + E1000_TXD_CMD_TSE = 0x04000000, /* TCP Seg enable */ | |
205 + E1000_TXD_STAT_TC = 0x00000004, /* Tx Underrun */ | |
206 + } | |
207 + | |
208 + map | |
209 + { | |
210 + } | |
211 + } | |
212 + | |
213 + template type e1000::RxDescriptor() | |
214 + { | |
215 + decl data_types() | |
216 + { | |
217 + __le64 buff_addr; | |
218 + __le16 length; | |
219 + __le16 csum; | |
220 + unsigned char status; | |
221 + unsigned char errors; | |
222 + __le16 special; | |
223 + } | |
224 + | |
225 + map | |
226 + { | |
227 + } | |
228 + } | |
229 + | |
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 | |
232 + // tx descriptors in its tx ring: | |
233 + // - context descriptors: this descriptor doesn't actually point to data to | |
234 + // send but initialize the offloading engine for the data descriptor that | |
235 + // follow; | |
236 + // - data descriptors: this descriptor points to data from the skbuffs. | |
237 + template type e1000::TxDescriptor() | |
238 + { | |
239 + decl data_types() | |
240 + { | |
241 + __le64 buff_addr; | |
242 + union { | |
243 + __le32 data; | |
244 + struct { | |
245 + __le16 length; | |
246 + unsigned char csum_offset; /* CSO */ | |
247 + unsigned char cmd; | |
248 + } fields; | |
249 + } lower; | |
250 + union { | |
251 + __le32 data; | |
252 + struct { | |
253 + unsigned char status; | |
254 + unsigned char csum_start; /* CSS */ | |
255 + __le16 special; | |
256 + } fields; | |
257 + } upper; | |
258 + } | |
259 + | |
260 + map | |
261 + { | |
262 + } | |
263 + } | |
264 + | |
265 + template type e1000::Buffer() | |
266 + { | |
267 + decl data_types() | |
268 + { | |
269 + ${Socket::SKBuff} sk_buff; | |
270 + ${DMA::DMAHandle} dma; | |
271 + } | |
272 + | |
273 + method init(Socket::SKBuff sk_buff, DMA::DMAHandle dma) | |
274 + { | |
275 + ${self.sk_buff} = ${sk_buff}; | |
276 + ${self.dma} = ${dma}; | |
277 + } | |
278 + | |
279 + map | |
280 + { | |
281 + sk_buff: ${self}->sk_buff; | |
282 + dma: ${self}->dma; | |
283 + } | |
284 + } | |
285 + | |
286 + template type e1000::MMIO | |
287 + { | |
288 + decl data_types() | |
289 + { | |
290 + unsigned char *io; | |
291 + } | |
292 + | |
293 + // XXX: we'll need those functions until we get working methods (#46): | |
294 + | |
295 + chunk LKM::prototypes() | |
296 + { | |
297 + static unsigned int rtx_e1000_reg_read32(${e1000::MMIO}, ${e1000::Register}); | |
298 + static void rtx_e1000_reg_write32(${e1000:::MMIO}, ${e1000::Register}, ${Builtin::number}); | |
299 + static void rtx_e1000_reg_set32(${e1000:::MMIO}, ${e1000::Register}, ${Builtin::number}); | |
300 + static void rtx_e1000_reg_unset32(${e1000:::MMIO}, ${e1000::Register}, ${Builtin::number}); | |
301 + } | |
302 + | |
303 + chunk LKM::code() | |
304 + { | |
305 + static unsigned int rtx_e1000_reg_read32(${e1000::MMIO} io, ${e1000::Register} reg) | |
306 + { | |
307 + return ioread32(${local.io.io} + reg); | |
308 + } | |
309 + | |
310 + static void rtx_e1000_reg_write32(${e1000:::MMIO} io, ${e1000::Register} reg, ${Builtin::number} value) | |
311 + { | |
312 + return iowrite32(value, ${local.io.io} + reg); | |
313 + } | |
314 + | |
315 + static void rtx_e1000_reg_set32(${e1000:::MMIO} io, ${e1000::Register} reg, ${Builtin::number} value) | |
316 + { | |
317 + return iowrite32(rtx_e1000_reg_read32(io, reg) | value, ${local.io.io} + reg); | |
318 + } | |
319 + | |
320 + static void rtx_e1000_reg_unset32(${e1000:::MMIO} io, ${e1000::Register} reg, ${Builtin::number} value) | |
321 + { | |
322 + return iowrite32(rtx_e1000_reg_read32(io, reg) & ~value, ${local.io.io} + reg); | |
323 + } | |
324 + } | |
325 + | |
326 + method init(Builtin::symbol io) | |
327 + { | |
328 + ${self.io} = ${io}; | |
329 + } | |
330 + | |
331 + method read32(${e1000::Register} reg) | |
332 + { | |
333 + ioread32(${self.io} + ${local.reg}); | |
334 + } | |
335 + | |
336 + method write32(${e1000::Register} reg, ${Builtin::number} value) | |
337 + { | |
338 + iowrite32(${local.value}, ${self.io} + ${local.reg}); | |
339 + } | |
340 + | |
341 + method set32(${e1000::Register} reg, ${Builtin::number} value) | |
342 + { | |
343 + iowrite32(ioread32(${self.io} + ${local.reg}) | value, ${self.io} + ${local.reg}); | |
344 + } | |
345 + | |
346 + method unset32(${e1000::Register} reg, ${Builtin::number} value) | |
347 + { | |
348 + iowrite32(ioread32(${self.io} + ${local.reg}) & ~value, ${self.io} + ${local.reg}); | |
349 + } | |
350 + | |
351 + map | |
352 + { | |
353 + io: ((unsigned char *)(${self})); | |
354 + } | |
355 + } | |
356 + | |
357 + template type e1000::Ring() | |
358 + { | |
359 + decl data_types() | |
360 + { | |
361 + ${e1000::MMIO} io; | |
362 + ${DMA::DMAHandle} dma; | |
363 + ${Builtin::symbol.ref} descs; | |
364 + ${Builtin::number} size; | |
365 + ${e1000::Buffer.ref} buffs; | |
366 + } | |
367 + | |
368 + chunk LKM::prototypes() | |
369 + { | |
370 + static void rtx_e1000_ring_init(${e1000::Ring.ref}, ${e1000::MMIO}, | |
371 + ${Builtin::number}, ${Builtin::number}); | |
372 + } | |
373 + | |
374 + chunk LKM::code() | |
375 + { | |
376 + static void rtx_e1000_ring_init(${e1000::Ring.ref} self, | |
377 + ${e1000::MMIO} io, | |
378 + ${Builtin::number} desc_count, | |
379 + ${Builtin::number} desc_size) | |
380 + { | |
381 + memset(self, 0, sizeof(*self)); | |
382 + self->size = ALIGN(desc_count * desc_size, 4096); | |
383 + self->io = io; | |
384 + } | |
385 + } | |
386 + | |
387 + method init(e1000::MMIO io, Builtin::number desc_count, Builtin::number desc_size) | |
388 + { | |
389 + rtx_e1000_ring_init(&${self}, ${io}, ${desc_count}, ${desc_size}); | |
390 + } | |
391 + } | |
392 + | |
393 + template type e1000::RxRing() | |
394 + { | |
395 + decl data_types() | |
396 + { | |
397 + ${e1000::Ring} ring; | |
398 + } | |
399 + | |
400 + chunk LKM::prototypes() | |
401 + { | |
402 + static int rtx_e1000_alloc_rx_ressources(${e1000::RxRing.ref}); | |
403 + } | |
404 + | |
405 + chunk LKM::code() | |
406 + { | |
407 + static int rtx_e1000_alloc_rx_ressources(${e1000::RxRing.ref} self) | |
408 + { | |
409 + return 0; | |
410 + } | |
411 + } | |
412 + | |
413 + chunk Ethernet::adapter_init_rx(Ethernet::Device rtx_ether_ctx) | |
414 + { | |
415 + { | |
416 + ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; | |
417 + | |
418 + /* | |
419 + * Receive initialization (section 14.4): | |
420 + * | |
421 + * 1. Program the receive address, in RAL/RAH; | |
422 + * 2. Initialize the Multicast Table Array; | |
423 + * 3. Program the interrupt mask register (done in | |
424 + * e1000::activate_device_interruption); | |
425 + * 4. Allocate the receive descriptor ring and map it to make it | |
426 + * accessible by the device; | |
427 + * 5. Write the start address of the ring in RDBAL/RDBAH and set | |
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)}; | |
488 + if (rtx_ethernet_alloc_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len})) | |
489 + { | |
490 + ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")}; | |
491 + goto err_skbuffs_alloc; | |
492 + } | |
493 + /* 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)} | |
495 + if (${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)}) | |
496 + { | |
497 + ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")}; | |
498 + goto err_skbuffs_map; | |
499 + } | |
500 + hw_ctx->rx_ring.base[i].buff_addr = cpu_to_le64(${local.skbuff.sk_buff}); | |
501 + } | |
502 + | |
503 + // ${Log::info("adapter_init_rx: skbuffs allocated}; | |
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)); | |
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--) { | |
531 + dma_unmap_single( | |
532 + ${rtx_ether_ctx.device}, | |
533 + /* XXX Leaking cast because of the array: */ | |
534 + *((dma_addr_t *)&(hw_ctx->rx_ring.skbuffs[i].dma_handle)), | |
535 + ${config.rx_buffer_len}, | |
536 + DMA_FROM_DEVICE); | |
537 + err_skbuffs_map: | |
538 + /* XXX leaking cast: */ | |
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) | |
556 + { | |
557 + ${self.ring.init(local.io, local.desc_count, self.desc_size)}; | |
558 + } | |
559 + | |
560 + method alloc() | |
561 + { | |
562 + rtx_e1000_alloc_rx_ressources(${self}); | |
563 + } | |
564 + | |
565 + map | |
566 + { | |
567 + descs: ((${self})->descs); // TODO: fix cast pour directement avoir les descs | |
568 + desc_size: sizeof(/* XXX ${e1000::RxDescriptor} */int); | |
569 + } | |
570 + } | |
571 + | |
572 + template type e1000::TxRing() | |
573 + { | |
574 + decl data_types() | |
575 + { | |
576 + ${e1000::Ring} ring; | |
577 + } | |
578 + | |
579 + chunk LKM::prototypes() | |
580 + { | |
581 + static int rtx_e1000_alloc_tx_ressources(${e1000::TxRing.ref}); | |
582 + } | |
583 + | |
584 + chunk LKM::code() | |
585 + { | |
586 + static int rtx_e1000_alloc_tx_ressources(${e1000::TxRing.ref} self) | |
587 + { | |
588 + return 0; | |
589 + } | |
590 + } | |
591 + | |
592 + method init(e1000::MMIO io, Builtin::number desc_count) | |
593 + { | |
594 + ${self.ring.init(local.io, local.desc_count, self.desc_size)}; | |
595 + } | |
596 + | |
597 + method alloc() | |
598 + { | |
599 + rtx_e1000_alloc_tx_ressources(${self}); | |
600 + } | |
601 + | |
602 + map | |
603 + { | |
604 + descs: ((${self})->descs); // TODO: fix cast pour directement avoir les descs | |
605 + desc_size: sizeof(/* XXX ${e1000::TxDescriptor} */int); | |
606 + } | |
607 + } | |
608 + | |
609 + template type e1000::Context() | |
610 + { | |
611 + decl data_types() | |
612 + { | |
613 + ${e1000::MMIO} io; | |
614 + ${e1000::TxRing} tx_ring; | |
615 + ${e1000::RxRing} rx_ring; | |
616 + } | |
617 + | |
618 + chunk LKM::includes() | |
619 + { | |
620 + #include <linux/types.h> | |
621 + } | |
622 + | |
623 + chunk LKM::prototypes() | |
624 + { | |
625 + static void rtx_e1000_print_status(${e1000::Context.ref}); | |
626 + } | |
627 + | |
628 + chunk LKM::code() | |
629 + { | |
630 + static void rtx_e1000_print_status(${e1000::Context.ref} hw_ctx) | |
631 + { | |
632 + unsigned int status = rtx_e1000_reg_read32(hw_ctx, E1000_STATUS); | |
633 + ${Log::info("card status:")}; | |
634 + // XXX We can't use Log::info below because it just accept a | |
635 + // string (as opposed to a format string with its parameters): | |
636 + pr_info("\tRegister value: 0x%x\n", status); | |
637 + pr_info("\tMode: %s\n", (status & 1) ? "Full": "Half"); | |
638 + pr_info("\tLink: %s\n", (status & 2) ? "Up" : "Down"); | |
639 + pr_info("\tTransmission: %s\n", (status & 4) ? "Paused" : "Ok"); | |
640 + pr_info("\tInterface: %s\n", (status & 3) == 3 ? "Up" : "Down"); | |
641 + } | |
642 + } | |
643 + | |
644 + chunk Ethernet::HardwareContext() | |
645 + { | |
646 + ${e1000::Context} hw_ctx; | |
647 + } | |
648 + | |
649 + chunk Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx, Builtin::symbol ioaddr) | |
650 + { | |
651 + { | |
652 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | |
653 + ${local.hw_ctx.io.init(local.ioaddr)}; | |
654 + ${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)}; | |
656 + } | |
657 + } | |
658 + | |
659 + chunk Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx) | |
660 + { | |
661 + { | |
662 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | |
663 + // XXX #46: ${local.hw_ctx.io.write32(E1000_CTRL, E1000_CMD_RST)}; | |
664 + rtx_e1000_reg_write32(hw_ctx, E1000_CTRL, E1000_CMD_RST); | |
665 + udelay(10); // TODO: abstract this too... | |
666 + ${Log::info("adapter has been reset")}; | |
667 + } | |
668 + } | |
669 + | |
670 + chunk Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx) | |
671 + { | |
672 + { | |
673 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | |
674 + // Shamelessly borrowed from Minix | |
675 + for (int i = 0; i < 3; ++i) { | |
676 + rtx_e1000_reg_write32(hw_ctx, E1000_EEPROM_READ, (i << 8) | 1); | |
677 + int value; | |
678 + do { | |
679 + value = rtx_e1000_reg_read32(hw_ctx, E1000_EEPROM_READ); | |
680 + } while ((value & (1 << 4)) == 0); | |
681 + value >>= 16; | |
682 + // NOTE: I'm not sure if Ethernet::Device should be | |
683 + // accessed directly here. But since we need to take it in | |
684 + // parameter (so we can get back our e1000::Context) it | |
685 + // seems inadequate to set this in another way: | |
686 + ${local.rtx_ether_ctx.dev_addr}[i * 2] = value & 0xff; | |
687 + ${local.rtx_ether_ctx.dev_addr}[i * 2 + 1] = (value >> 8) & 0xff; | |
688 + } | |
689 + | |
690 + ${Log::info("mac address loaded from the EEPROM")}; | |
691 + } | |
692 + } | |
693 + | |
694 + chunk Ethernet::adapter_setup_rx_tx(Ethernet::Device rtx_ether_ctx) | |
695 + { | |
696 + { | |
697 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | |
698 + | |
699 + // "General Configuration" (section 14.3): | |
700 + // | |
701 + // - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection & | |
702 + // negociation; | |
703 + // - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation; | |
704 + // - CTRL.PHY_RST: Unset it; | |
705 + // - CTRL.ILOS: Unset it (ILOS is Invert Loss Of Signal); | |
706 + // - CTRL.VME: Make sure it's not set to disable VLAN support; | |
707 + // - Set the control flow registers to 0; | |
708 + // - Finally, initialize all the statistic registers from | |
709 + // E1000_CRCERRS to E1000_TSCTFC. | |
710 + // | |
711 + // XXX #46: Use the read/write/set/unset methods on Context | |
712 + rtx_e1000_reg_set32(hw_ctx, E1000_CTRL, E1000_CMD_ASDE|E1000_CMD_SLU); | |
713 + rtx_e1000_reg_unset32( | |
714 + hw_ctx, | |
715 + E1000_CTRL, | |
716 + E1000_CMD_LRST|E1000_CMD_FRCSPD|E1000_CMD_PHY_RST| | |
717 + E1000_CMD_ILOS|E1000_CMD_VME | |
718 + ); | |
719 + rtx_e1000_reg_write32(hw_ctx, E1000_FCAH, 0); | |
720 + rtx_e1000_reg_write32(hw_ctx, E1000_FCAL, 0); | |
721 + rtx_e1000_reg_write32(hw_ctx, E1000_FCT, 0); | |
722 + rtx_e1000_reg_write32(hw_ctx, E1000_FCTTV, 0); | |
723 + for (int i = 0; i != 64; ++i) | |
724 + rtx_e1000_reg_write32(hw_ctx, E1000_CRCERRS + i * 4, 0); | |
725 + | |
726 + ${Log::info("adapter_setup: general configuration done")}; | |
727 + } | |
728 + } | |
729 + | |
730 + chunk Ethernet::adapter_enable_interrupts(Ethernet::Device) | |
731 + { | |
732 + { | |
733 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | |
734 + rtx_e1000_reg_write32( | |
735 + hw_ctx, | |
736 + E1000_IMS, | |
737 + E1000_INTR_TXDW|E1000_INTR_TXQE|E1000_INTR_LSC| | |
738 + E1000_INTR_RXO|E1000_INTR_RXT0 | |
739 + ); | |
740 + | |
741 + // XXX We should probably move that elsewhere (it just used to | |
742 + // be done right after we enabled interrupts when this was | |
743 + // still in lkm.rtx): | |
744 + ${local.hw_ctx.print_status()}; | |
745 + } | |
746 + } | |
747 + | |
748 + chunk Ethernet::handle_interrupt(Ethernet::Device rtx_ether_ctx) | |
749 + { | |
750 + { | |
751 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; | |
752 + unsigned int icr = rtx_e1000_reg_read32(hw_ctx, E1000_ICR); | |
753 + pr_info("%s: interrupt received, ICR: 0x%x", ${config.name}, icr); | |
754 + if (icr) { | |
755 + if (icr & E1000_INTR_LSC) { | |
756 + ${Log::info("handle_interrupt: cable link status changed, dumping card status:")}; | |
757 + ${local.hw_ctx.print_status()}; | |
758 + } | |
759 + if (icr & (E1000_INTR_TXQE|E1000_INTR_TXDW)) { | |
760 + ${Log::info("handle_interrupt: TxRing: packet(s) sent")}; | |
761 + } | |
762 + if (icr & E1000_INTR_RXT0) { | |
763 + ${Log::info("handle_interrupt: RxRing: packet(s) received")}; | |
764 + } | |
765 + if (icr & E1000_INTR_RXO) { | |
766 + ${Log::info("handle_interrupt: RxRing: overrun")}; | |
767 + } | |
768 + | |
769 + // XXX: This sucks since we don't know the pointcut context: | |
770 + return IRQ_HANDLED; | |
771 + } | |
772 + } | |
773 + } | |
774 + | |
775 + method print_status() | |
776 + { | |
777 + rtx_e1000_print_status(${self}); | |
778 + } | |
779 + | |
780 + map | |
781 + { | |
782 + io: ${self}->io; | |
783 + rx_ring: ${self}->rx_ring; | |
784 + tx_ring: ${self}->tx_ring; | |
785 + } | |
786 + } | |
787 +} | |
788 diff --git a/rathaxes/samples/e1000/e1000ng.rti b/rathaxes/samples/e1000/e1000ng.rti | |
789 new file mode 100755 | |
790 --- /dev/null | |
791 +++ b/rathaxes/samples/e1000/e1000ng.rti | |
792 @@ -0,0 +1,122 @@ | |
793 +interface e1000ng : Socket, Ethernet, DMA, PCI, LKM, Builtin | |
794 +{ | |
795 + required variable Builtin::number rx_ring_size; | |
796 + required variable Builtin::number tx_ring_size; | |
797 + required variable Builtin::number rx_buffer_len; | |
798 + required variable Builtin::number tx_max_data_per_desc; | |
799 + | |
800 + // Hardware values/data structures, should probably be in the front-end: | |
801 + provided type Register { decl data_types(); } | |
802 + provided type Command { decl data_types(); } | |
803 + provided type TxDescriptorFlag { decl data_types(); } | |
804 + provided type RxDescriptor { decl data_types(); } | |
805 + provided type TxDescriptor { decl data_types(); } | |
806 + | |
807 + provided type Buffer | |
808 + { | |
809 + decl data_types(); | |
810 + | |
811 + method init(Socket::SKBuff, DMA::DMAHandle); | |
812 + | |
813 + attribute Socket::SKBuff.ref sk_buff; | |
814 + attribute DMA::DMAHandle.ref dma; | |
815 + } | |
816 + | |
817 + // 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 | |
819 + // between the context and the rings and Rathaxes can't handle it. | |
820 + provided type MMIO | |
821 + { | |
822 + decl data_types(); | |
823 + | |
824 + chunk LKM::prototypes(); | |
825 + chunk LKM::code(); | |
826 + | |
827 + method init(Builtin::symbol); | |
828 + method read32(Register); | |
829 + method write32(Register, Builtin::number); | |
830 + method set32(Register, Builtin::number); | |
831 + method unset32(Register, Builtin::number); | |
832 + | |
833 + attribute Builtin::symbol io; | |
834 + } | |
835 + | |
836 + provided type Ring | |
837 + { | |
838 + decl data_types(); | |
839 + | |
840 + chunk LKM::prototypes(); | |
841 + chunk LKM::code(); | |
842 + | |
843 + method init(MMIO, Builtin::number, Builtin::number); | |
844 + | |
845 + attribute MMIO io; | |
846 + attribute DMA:DMAHandle dma; | |
847 + attribute Builtin::number size; // Total size in bytes | |
848 + attribute Builtin::symbol.ref descs; | |
849 + attribute Buffer.ref buffs; | |
850 + } | |
851 + | |
852 + provided type RxRing | |
853 + { | |
854 + decl data_types(); | |
855 + | |
856 + chunk LKM::prototypes(); | |
857 + chunk LKM::code(); | |
858 + | |
859 + method init(MMIO, Builtin::number); | |
860 + method alloc(); // Returns != 0 on failure | |
861 + | |
862 + attribute RxDescriptor descs; | |
863 + } | |
864 + | |
865 + provided type TxRing | |
866 + { | |
867 + decl data_types(); | |
868 + | |
869 + chunk LKM::prototypes(); | |
870 + chunk LKM::code(); | |
871 + | |
872 + method init(MMIO, Builtin::number); | |
873 + method alloc(); // Returns != 0 on failure | |
874 + | |
875 + attribute TxDescriptor descs; | |
876 + } | |
877 + | |
878 + provided type Context | |
879 + { | |
880 + decl data_types(); | |
881 + | |
882 + chunk LKM::includes(); | |
883 + chunk LKM::prototypes(); | |
884 + chunk LKM::code(); | |
885 + chunk Ethernet::HardwareContext(); | |
886 + | |
887 + // NOTE: Those callbacks/hooks should probably be in the front-end: | |
888 + | |
889 + // Init the hardware context structure, doesn't allocate anything. | |
890 + chunk Ethernet::adapter_init_context(Ethernet::Device, Builtin::symbol); | |
891 + | |
892 + // Reset the adapter | |
893 + chunk Ethernet::adapter_reset(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); | |
901 + | |
902 + // Enable interrupts. | |
903 + chunk Ethernet::adapter_enable_interrupts(Ethernet::Device); | |
904 + | |
905 + // Interrupt handler. | |
906 + chunk Ethernet::handle_interrupt(Ethernet::Device); | |
907 + | |
908 + method print_status(); | |
909 + | |
910 + attribute MMIO io; | |
911 + attribute RxRing.scalar rx_ring; | |
912 + attribute TxRing.scalar tx_ring; | |
913 + } | |
914 +} | |
915 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt | |
916 --- a/rathaxes/samples/e1000/ethernet.blt | |
917 +++ b/rathaxes/samples/e1000/ethernet.blt | |
918 @@ -106,7 +106,7 @@ | |
919 { | |
920 ${Socket::AbstractSKBuff} k_sk_buff = netdev_alloc_skb(${local.self.net_device.k_net_dev}, ${local.size}); | |
921 if (${local.k_sk_buff) { | |
922 - ${local.sk_buff.init(local.k_sk_buff, local.size)}; | |
923 + ${local.sk_buff.init(local.k_sk_buff)}; | |
924 return 0; | |
925 } | |
926 return 1; | |
927 @@ -164,34 +164,30 @@ | |
928 { | |
929 static int rtx_ethernet_open(struct net_device *dev) | |
930 { | |
931 - /* | |
932 - * XXX The casts are here because the compiler doesn't resolve | |
933 - * "enclosed" type (e.g: local.var.enclosed) correctly. | |
934 - */ | |
935 ${Ethernet::AbstractDevice.ref} rtx_net_dev; | |
936 { /* XXX: I end up with a placeholder if I don't open a scope */ | |
937 ${local.rtx_net_dev.init(local.dev)}; | |
938 } | |
939 ${Ethernet::Device.ref} rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx}; | |
940 | |
941 - int error; | |
942 + ${pointcut Ethernet::adapter_setup_rx_tx(local.rtx_ether_ctx)}; | |
943 + | |
944 { | |
945 - ${Log::info("installing the interrupt handler")}; | |
946 + ${Log::info("Installing the interrupt handler")}; | |
947 } | |
948 - error = request_irq(${local.rtx_ether_ctx.irq}, | |
949 - rtx_ethernet_interrupt_handler, | |
950 - IRQF_SHARED, | |
951 - ${config.name}, | |
952 - dev); | |
953 - if (error) | |
954 - { | |
955 + int error = request_irq( | |
956 + ${local.rtx_ether_ctx.irq}, | |
957 + rtx_ethernet_interrupt_handler, | |
958 + IRQF_SHARED, | |
959 + ${config.name}, | |
960 + dev | |
961 + ); | |
962 + if (error) { | |
963 ${Log::info("Cannot register the interrupt handler")}; | |
964 return error; | |
965 } | |
966 - ${pointcut Ethernet::adapter_setup(local.rtx_ether_ctx)}; | |
967 - ${pointcut Ethernet::adapter_init_rx(local.rtx_ether_ctx)}; | |
968 - ${pointcut Ethernet::adapter_init_tx(local.rtx_ether_ctx)}; | |
969 - ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)}; | |
970 + | |
971 + ${pointcut Ethernet::adapter_enable_interrupts(local.rtx_ether_ctx)}; | |
972 | |
973 return 0; | |
974 } | |
975 @@ -269,7 +265,7 @@ | |
976 ${Ethernet::Device.ref} rtx_ether_ctx; | |
977 rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx}; | |
978 | |
979 - ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)}; | |
980 + ${pointcut Ethernet::handle_interrupt(local.rtx_ether_ctx)}; | |
981 | |
982 return IRQ_NONE; | |
983 } | |
984 @@ -342,12 +338,8 @@ | |
985 * XXX: the asssignments/casts are here to circumvent | |
986 * typing issues in the compiler (see previous XXX). | |
987 */ | |
988 - int bars = ${rtx_pci_dev.bars}; | |
989 unsigned char /* __iomem */ *ioaddr = ${rtx_pci_dev.ioaddr}; | |
990 - ${cast local.bars as Builtin::number}; | |
991 - ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx, | |
992 - local.bars, | |
993 - local.ioaddr)}; | |
994 + ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx, local.ioaddr)}; | |
995 ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)}; | |
996 ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)}; | |
997 memcpy(${local.rtx_ether_ctx.perm_addr}, | |
998 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti | |
999 --- a/rathaxes/samples/e1000/ethernet.rti | |
1000 +++ b/rathaxes/samples/e1000/ethernet.rti | |
1001 @@ -28,8 +28,12 @@ | |
1002 | |
1003 provided type Device | |
1004 { | |
1005 + decl data_types(); | |
1006 + | |
1007 chunk LKM::includes(); | |
1008 - decl data_types(); | |
1009 + chunk LKM::prototypes(); | |
1010 + chunk LKM::code(); | |
1011 + | |
1012 pointcut Ethernet::HardwareContext(); | |
1013 | |
1014 method init(Ethernet::AbstractDevice, PCI::AbstractDevice); | |
1015 @@ -51,7 +55,7 @@ | |
1016 attribute Builtin::symbol.scalar irq; | |
1017 } | |
1018 | |
1019 - required sequence open(Ethernet::Device) | |
1020 + provided sequence open(Ethernet::Device) | |
1021 { | |
1022 provided chunk LKM::includes(); | |
1023 provided chunk LKM::prototypes(); | |
1024 @@ -62,9 +66,8 @@ | |
1025 * Controller Software Developper manual. (You can find it in the | |
1026 * doc/hardware directory). | |
1027 */ | |
1028 - provided pointcut Ethernet::adapter_setup(Ethernet::Device); | |
1029 - provided pointcut Ethernet::adapter_init_rx(Ethernet::Device); | |
1030 - provided pointcut Ethernet::adapter_init_tx(Ethernet::Device); | |
1031 + provided pointcut Ethernet::adapter_setup_rx_tx(Ethernet::Device); | |
1032 + provided pointcut Ethernet::adapter_enable_interrupts(Ethernet::Device); | |
1033 } | |
1034 | |
1035 required sequence send(Ethernet::Device, Socket::AbstractSKBuff) | |
1036 @@ -79,10 +82,12 @@ | |
1037 provided chunk LKM::code(); | |
1038 } | |
1039 | |
1040 - required sequence interrupt_handler(Ethernet::Device) | |
1041 + provided sequence interrupt_handler(Ethernet::Device) | |
1042 { | |
1043 provided chunk LKM::prototypes(); | |
1044 provided chunk LKM::code(); | |
1045 + | |
1046 + provided pointcut Ethernet::handle_interrupt(Ethernet::Device); | |
1047 } | |
1048 | |
1049 provided sequence init() | |
1050 @@ -90,9 +95,7 @@ | |
1051 provided chunk LKM::data(); | |
1052 provided chunk PCI::pci_probe_hook(PCI::Device); | |
1053 | |
1054 - provided pointcut Ethernet::adapter_init_context(Ethernet::Device, | |
1055 - Builtin::number, | |
1056 - Builtin::symbol); | |
1057 + provided pointcut Ethernet::adapter_init_context(Ethernet::Device, Builtin::symbol); | |
1058 provided pointcut Ethernet::adapter_reset(Ethernet::Device); | |
1059 provided pointcut Ethernet::adapter_load_mac_address(Ethernet::Device); | |
1060 } | |
1061 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx | |
1062 --- a/rathaxes/samples/e1000/lkm.rtx | |
1063 +++ b/rathaxes/samples/e1000/lkm.rtx | |
1064 @@ -1,34 +1,5 @@ | |
1065 device LKM use LKM, PCI, Ethernet, Log, Socket | |
1066 { | |
1067 - Ethernet::open(Ethernet::Device dev) | |
1068 - { | |
1069 - Log::info("opening the device"); | |
1070 - | |
1071 - e1000::activate_device_interruption(dev); | |
1072 - Log::info("interruption enabled"); | |
1073 - | |
1074 - e1000::print_status(dev); | |
1075 - } | |
1076 - | |
1077 - Ethernet::close(Ethernet::Device dev) | |
1078 - { | |
1079 - Log::info("closing the device"); | |
1080 - | |
1081 - /* | |
1082 - * Note: some calls to release resources must be done when IRQs are | |
1083 - * enabled (dma_free_coherent() for example). So we have to cleanup our | |
1084 - * stuff before free_interrupt_handler(). | |
1085 - */ | |
1086 - e1000::free_rx_tx(dev); | |
1087 - Log::info("free'ed up rx/tx resources"); | |
1088 - } | |
1089 - | |
1090 - Ethernet::interrupt_handler(Ethernet::Device dev) | |
1091 - { | |
1092 - Log::info("got an interruption"); | |
1093 - e1000::handle_interrupt(dev); | |
1094 - } | |
1095 - | |
1096 Ethernet::send(Ethernet::Device dev, Socket::AbstractSKBuff skb) | |
1097 { | |
1098 Log::info("we have one packet to transmit!"); | |
1099 diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt | |
1100 --- a/rathaxes/samples/e1000/socket.blt | |
1101 +++ b/rathaxes/samples/e1000/socket.blt | |
1102 @@ -22,16 +22,12 @@ | |
1103 { | |
1104 decl data_types() | |
1105 { | |
1106 - ${Socket::AbstractSKBuff.ref} skbuff; | |
1107 - ${DMA::AbstractDMAHandle.scalar} dma_handle; | |
1108 - unsigned int size; | |
1109 + ${Socket::AbstractSKBuff.ref} skbuff; | |
1110 } | |
1111 | |
1112 chunk LKM::prototypes() | |
1113 { | |
1114 static void rtx_socket_skbuff_dump_infos(${Socket::SKBuff.ref}); | |
1115 - 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}); | |
1117 } | |
1118 | |
1119 chunk LKM::code() | |
1120 @@ -63,85 +59,6 @@ | |
1121 shinfo->nr_frags, shinfo->gso_size, shinfo->gso_segs, shinfo->gso_type | |
1122 ); | |
1123 } | |
1124 - | |
1125 - static int rtx_socket_skbuff_map(${Socket::SKBuff.ref} self, | |
1126 - ${Device::AbstractDevice.ref} dev, | |
1127 - ${DMA::DMADirection.scalar} direction) | |
1128 - { | |
1129 - WARN_ON(!${local.self.sk_buff}); | |
1130 - WARN_ON(${local.self.dma_handle}); | |
1131 - /* | |
1132 - * TODO: we don't support skbuffs with paged data yet (see also | |
1133 - * http://vger.kernel.org/~davem/skb_data.html). | |
1134 - */ | |
1135 - WARN_ON(skb_is_nonlinear(${local.self.sk_buff.k_sk_buff})); | |
1136 - | |
1137 - unsigned int len = ${local.self.size}; | |
1138 - ${cast local.len as Builtin::number}; | |
1139 - ${local.self.dma_handle} = ${DMA::map(local.dev, local.self.sk_buff.k_sk_buff, local.len, local.direction)}; | |
1140 - int err = ${DMA::mapping_error(local.dev, local.self.dma_handle)}; | |
1141 - if (err) | |
1142 - { | |
1143 - ${local.self.dma_handle} = 0; | |
1144 - return err; | |
1145 - } | |
1146 - return 0; | |
1147 - } | |
1148 - | |
1149 - static void rtx_socket_skbuff_unmap_and_free(${Socket::SKBuff.ref} self, | |
1150 - ${Device::AbstractDevice.ref} dev, | |
1151 - ${DMA::DMADirection} direction) | |
1152 - { | |
1153 - WARN_ON(!${local.self.sk_buff}); | |
1154 - WARN_ON(skb_is_nonlinear(${local.self.sk_buff.k_sk_buff}); | |
1155 - | |
1156 - if (${local.self.dma_handle}) | |
1157 - { | |
1158 - unsigned int len = ${local.self.size}; | |
1159 - ${cast local.len as Builtin::number}; | |
1160 - ${DMA::unmap(local.dev, local.self.dma_handle, local.len, local.direction)}; | |
1161 - ${local.self.dma_handle} = 0; | |
1162 - } | |
1163 - dev_kfree_skb_any(${local.self.sk_buff.k_sk_buff}); | |
1164 - ${local.self.sk_buff} = NULL; | |
1165 - } | |
1166 - } | |
1167 - | |
1168 - /* | |
1169 - * 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 | |
1171 - * variable I needed) | |
1172 - */ | |
1173 - method init(Socket::AbstractSKBuff kernel_skb, Builtin::number size) | |
1174 - { | |
1175 - ${self.sk_buff} = ${kernel_skb}; | |
1176 - ${self.size} = ${size}; | |
1177 - ${self.dma_handle} = 0; | |
1178 - } | |
1179 - | |
1180 - method dump_infos() | |
1181 - { | |
1182 - rtx_socket_skbuff_dump_infos(${self}); | |
1183 - } | |
1184 - | |
1185 - method map_to(Device::AbstractDevice dev) | |
1186 - { | |
1187 - rtx_socket_skbuff_map(${self}, ${dev}, RTX_DMA_TO_DEVICE); | |
1188 - } | |
1189 - | |
1190 - method map_from(Device::AbstractDevice dev) | |
1191 - { | |
1192 - rtx_socket_skbuff_map(${self}, ${dev}, RTX_DMA_FROM_DEVICE); | |
1193 - } | |
1194 - | |
1195 - method unmap_to_and_free(Device::AbstractDevice dev) | |
1196 - { | |
1197 - rtx_socket_skbuff_unmap_and_free(${self}, ${dev}, RTX_DMA_TO_DEVICE); | |
1198 - } | |
1199 - | |
1200 - method unmap_from_and_free(Device::AbstractDevice dev) | |
1201 - { | |
1202 - rtx_socket_skbuff_unmap_and_free(${self}, ${dev}, RTX_DMA_FROM_DEVICE); | |
1203 } | |
1204 | |
1205 map | |
1206 @@ -151,13 +68,9 @@ | |
1207 // management can be abstracted from the user. But this is at least | |
1208 // useful for internal use: | |
1209 sk_buff: (${self})->skbuff; | |
1210 - // 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 | |
1212 - // same time ${DMA:AbstractDMAHandle} couldn't be used because that | |
1213 - // would yield to a struct type which you can't assign directly; | |
1214 - // but maybe doing the ->data in that case would be acceptable). | |
1215 - dma_handle: (*((dma_addr_t *)&(${self})->dma_handle)); | |
1216 - size: (${self})->size; | |
1217 + | |
1218 + data: ((struct sk_buff *)((${self})->sk_buff))->data; | |
1219 + len: ((struct sk_buff *)((${self})->sk_buff))->len; | |
1220 } | |
1221 } | |
1222 } | |
1223 diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti | |
1224 --- a/rathaxes/samples/e1000/socket.rti | |
1225 +++ b/rathaxes/samples/e1000/socket.rti | |
1226 @@ -12,20 +12,14 @@ | |
1227 { | |
1228 chunk LKM::prototypes(); | |
1229 chunk LKM::code(); | |
1230 + | |
1231 decl data_types(); | |
1232 - method init(Socket::AbstractSKBuff, Builtin::number); | |
1233 + | |
1234 + method init(Socket::AbstractSKBuff); | |
1235 method dump_infos(); | |
1236 - /* | |
1237 - * map_to and map_from return a non-zero value on failure (which | |
1238 - * doesn't correspond to an errno value): | |
1239 - */ | |
1240 - method map_to(Device::AbstractDevice); | |
1241 - method map_from(Device::AbstractDevice); | |
1242 - method unmap_to_and_free(Device::AbstractDevice); | |
1243 - method unmap_from_and_free(Device::AbstractDevice); | |
1244 | |
1245 - attribute Socket::AbstractSKBuff.ref sk_buff; | |
1246 - attribute DMA::AbstractDMAHandle.scalar dma_handle; | |
1247 - attribute Builtin::number.scalar size; | |
1248 + attribute Socket::AbstractSKBuff.ref sk_buff; | |
1249 + attribute Builtin::symbol.ref data; | |
1250 + attribute Builtin::number.scalar len; | |
1251 } | |
1252 } |