comparison rathaxes_sample_e1000_rewrite_device_dependent_code.patch @ 133:dbb4a3b383cb

Wip on build
author Louis Opter <kalessin@kalessin.fr>
date Wed, 08 Jan 2014 09:42:33 -0800
parents f2e4dd91dc6f
children 79226bb06e6a
comparison
equal deleted inserted replaced
132:f2e4dd91dc6f 133:dbb4a3b383cb
1 # HG changeset patch 1 # HG changeset patch
2 # Parent 7d00455945ec97c5851ac0d735da7c3cfbd8e39c 2 # Parent 53d3ca9da9c4cd680cf5982b9e972903fb4d3231
3 rathaxes: rewrite/refactor all the e1000 device dependent code 3 rathaxes: rewrite/refactor all the e1000 device dependent code
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,26 @@ 9 @@ -0,0 +1,40 @@
10 +Remarks for David & Lionel: 10 +Remarks for David & Lionel:
11 + 11 +
12 +- Too much changes to not start over; 12 +- Too much changes to not start over;
13 +- 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:
14 + see the register read/write/set/unset methods on e1000::Context); 14 + see the register read/write/set/unset methods on e1000::Context);
21 +- Can I use the same name for a pointcut and a sequence (e.g: Ethernet::send 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); 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 23 +- Lack of support for circular dependencies make some code annoying or
24 + incorrect (circular dependencies between abstract and concrete types via the 24 + incorrect (circular dependencies between abstract and concrete types via the
25 + attribute or circular dependencies between the rings and the hardware 25 + attribute or circular dependencies between the rings and the hardware
26 + context). 26 + context);
27 +- It would be really cool to passthrough the comments;
28 +- Not being able to use a Rathaxes type in the attributes is really annoying
29 + and forces me to hardcode a lot of stuff;
30 +- Pointcuts are scoped by subsystems which is kinda weird because different
31 + subsystems are going to share the same pointcuts (i.e: the PCI and USB
32 + susystem are going to expose the same pointcuts that can be used by the
33 + Ethernet subsystem).
27 + 34 +
28 +Todo/Totry: 35 +Todo/Totry:
29 + 36 +
30 +- Use the rtx_ether_ctx attribute on AbstractDevice to initialize Device 37 +- Use the rtx_ether_ctx attribute on AbstractDevice to initialize Device
31 + objects in ethernet.bl; 38 + objects in ethernet.bl;
32 +- Worry about the code being executed concurrently, e.g: what happens if the 39 +- 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? 40 + interrupt handler is called right before we disable it in the close path?
41 +- Why the DMA sequences are taking an AbstractDMAHandle instead of a DMAHandle?
34 + 42 +
35 +Questions: 43 +Questions:
44 +
45 +Compiler bugs:
46 +
47 +- Trying to expand a type that doesn't exists crashes the compiler instead of
48 + displaying something more useful (took me 15 minutes to figure out that I
49 + typed 3 colons instead of 2 in a placeholder).
50 diff --git a/rathaxes/compiler/passes/back/rtxIntrospect.inc.cws b/rathaxes/compiler/passes/back/rtxIntrospect.inc.cws
51 --- a/rathaxes/compiler/passes/back/rtxIntrospect.inc.cws
52 +++ b/rathaxes/compiler/passes/back/rtxIntrospect.inc.cws
53 @@ -890,6 +890,8 @@
54 local to_remove;
55 foreach placeHolder in local_node.body.compile
56 {
57 + if (!placeHolder.node.body.type)
58 + traceLine(RED + "BUG: placeHolder.node.body.type is missing in rtxIntrospect_walk<\"__rtx_chunk__\">" + DEFAULT_COLOR);
59 if (rtxIntrospect_InferPlaceHolderTypes<placeHolder.node.body.type>(placeHolder.node.body, local_node) == false)
60 {
61 pushItem to_remove;
62 diff --git a/rathaxes/compiler/passes/back/rtxPlaceHolders.inc.cws b/rathaxes/compiler/passes/back/rtxPlaceHolders.inc.cws
63 --- a/rathaxes/compiler/passes/back/rtxPlaceHolders.inc.cws
64 +++ b/rathaxes/compiler/passes/back/rtxPlaceHolders.inc.cws
65 @@ -394,7 +394,10 @@
66 { rtxPH_mapPlaceHolder(local_node.expr.id, compile, node_idx, "target_pointcut"); }
67 }
68 else
69 + {
70 + traceLine(CYAN + "LOUIS: local_node.expr: " + toString(local_node.expr) + DEFAULT_COLOR);
71 rtxPH_compile<local_node.expr.type>(local_node.expr, compile, node_idx);
72 + }
73 }
74 // Label
75 if (existVariable(local_node.label) && rtxPH_havePlaceHolder(local_node.label))
36 diff --git a/rathaxes/samples/e1000/CMakeLists.txt b/rathaxes/samples/e1000/CMakeLists.txt 76 diff --git a/rathaxes/samples/e1000/CMakeLists.txt b/rathaxes/samples/e1000/CMakeLists.txt
37 old mode 100755
38 new mode 100644
39 --- a/rathaxes/samples/e1000/CMakeLists.txt 77 --- a/rathaxes/samples/e1000/CMakeLists.txt
40 +++ b/rathaxes/samples/e1000/CMakeLists.txt 78 +++ b/rathaxes/samples/e1000/CMakeLists.txt
41 @@ -17,9 +17,9 @@ 79 @@ -17,9 +17,9 @@
42 dma.blt 80 dma.blt
43 pci.blt 81 pci.blt
51 - ADD_RATHAXES_LKM(e1000 e1000_src) 89 - ADD_RATHAXES_LKM(e1000 e1000_src)
52 -ENDIF (LINUX_KBUILD_DIR) 90 -ENDIF (LINUX_KBUILD_DIR)
53 +#IF (LINUX_KBUILD_DIR) 91 +#IF (LINUX_KBUILD_DIR)
54 +# ADD_RATHAXES_LKM(e1000 e1000_src) 92 +# ADD_RATHAXES_LKM(e1000 e1000_src)
55 +#ENDIF (LINUX_KBUILD_DIR) 93 +#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
62 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt 94 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt
63 old mode 100755
64 new mode 100644
65 --- a/rathaxes/samples/e1000/e1000.blt 95 --- a/rathaxes/samples/e1000/e1000.blt
66 +++ b/rathaxes/samples/e1000/e1000.blt 96 +++ b/rathaxes/samples/e1000/e1000.blt
67 @@ -1,8 +1,148 @@ 97 @@ -1,564 +1,8 @@
68 with e1000, Ethernet, Socket, DMA, PCI, LKM, Log, Builtin 98 -with e1000, Ethernet, Socket, DMA, PCI, LKM, Log, Builtin
99 +with e1000, Ethernet, Socket, Device, DMA, PCI, LKM, Log, Builtin
69 { 100 {
70 - template type e1000::RxDescriptor() 101 - template type e1000::RxDescriptor()
71 + template type e1000::Register() 102 + template type e1000::Register()
72 { 103 {
73 - decl data_types() 104 - decl data_types()
74 + decl data_types() 105 - {
75 + { 106 - __le64 buff_addr;
76 + E1000_CTRL = 0x00000, /* Device Control - RW */ 107 - __le16 length;
77 + E1000_CTRL_DUP = 0x00004, /* Device Control Duplicate (Shadow) - RW */ 108 - __le16 csum;
78 + E1000_STATUS = 0x00008, /* Device Status - RO */ 109 - unsigned char status;
79 + E1000_EEPROM_FLASH = 0x00010, /* EEPROM/Flash Control - RW */ 110 - unsigned char errors;
80 + E1000_EEPROM_READ = 0x00014, /* EEPROM Read - RW */ 111 - __le16 special;
81 + E1000_CTRL_EXT = 0x00018, /* Extended Device Control - RW */ 112 - }
82 + E1000_FLA = 0x0001C, /* Flash Access - RW */ 113 -
83 + E1000_MDIC = 0x00020, /* MDI Control - RW */
84 + E1000_IMS = 0x000D0, /* Interrupt Mask Set */
85 + E1000_IMC = 0x000D8, /* Interrupt Mask Clear */
86 + E1000_ICR = 0x000C0, /* Interrupt Cause Read - R/clr */
87 + E1000_FCAL = 0x00028, /* Flow Control Address Low */
88 + E1000_FCAH = 0x0002c, /* Flow Control Address High */
89 + E1000_FCT = 0x00030, /* Flow Control Type */
90 + E1000_RCTL = 0x00100, /* Receive Control */
91 + E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value */
92 + E1000_TCTL = 0x00400, /* Transmit Control */
93 + E1000_CRCERRS = 0x04000, /* CRC Error Count (base address of the statistic register spaces) */
94 + E1000_RAL = 0x05400, /* Receive Address Low */
95 + E1000_RAH = 0x05404, /* Receive Address High */
96 + E1000_MTA = 0x05200, /* Multicast Table Array */
97 + E1000_RDBAL = 0x02800, /* Receive Descriptor Base Address (Low 32 bits) */
98 + E1000_RDBAH = 0x02804, /* Receive Descriptor Base Address (High 32 bits) */
99 + E1000_RDLEN = 0x02808, /* Receive Descriptor Length */
100 + E1000_RDH = 0x02810, /* Receive Descriptor Head */
101 + E1000_RDT = 0x02818, /* Receive Descriptor Tail */
102 + E1000_TDBAL = 0x03800, /* Transmit Descriptor Base Address (Low 32 bits) */
103 + E1000_TDBAH = 0x03804, /* Transmit Descriptor Base Address (High 33 bits) */
104 + E1000_TDLEN = 0x03808, /* Transmit Descriptor Length */
105 + E1000_TDH = 0x03810, /* Transmit Descriptor Head */
106 + E1000_TDT = 0x03818, /* Transmit Descriptor Tail */
107 + }
108 +
109 + map
110 + {
111 + }
112 + }
113 +
114 + template type e1000::Commands()
115 + {
116 + decl data_types()
117 + {
118 + E1000_CMD_FD = 0x00000001, /* Full duplex.0=half; 1=full */
119 + E1000_CMD_BEM = 0x00000002, /* Endian Mode.0=little,1=big */
120 + E1000_CMD_PRIOR = 0x00000004, /* Priority on PCI. 0=rx,1=fair */
121 + E1000_CMD_GIO_MASTER_DISABLE = 0x00000004, /* Blocks new Master requests */
122 + E1000_CMD_LRST = 0x00000008, /* Link reset. 0=normal,1=reset */
123 + E1000_CMD_TME = 0x00000010, /* Test mode. 0=normal,1=test */
124 + E1000_CMD_SLE = 0x00000020, /* Serial Link on 0=dis,1=en */
125 + E1000_CMD_ASDE = 0x00000020, /* Auto-speed detect enable */
126 + E1000_CMD_SLU = 0x00000040, /* Set link up (Force Link) */
127 + E1000_CMD_ILOS = 0x00000080, /* Invert Loss-Of Signal */
128 + E1000_CMD_SPD_SEL = 0x00000300, /* Speed Select Mask */
129 + E1000_CMD_SPD_10 = 0x00000000, /* Force 10Mb */
130 + E1000_CMD_SPD_100 = 0x00000100, /* Force 100Mb */
131 + E1000_CMD_SPD_1000 = 0x00000200, /* Force 1Gb */
132 + E1000_CMD_BEM32 = 0x00000400, /* Big Endian 32 mode */
133 + E1000_CMD_FRCSPD = 0x00000800, /* Force Speed */
134 + E1000_CMD_FRCDPX = 0x00001000, /* Force Duplex */
135 + E1000_CMD_D_UD_EN = 0x00002000, /* Dock/Undock enable */
136 + E1000_CMD_D_UD_POLARITY = 0x00004000, /* Defined polarity of Dock/Undock indication in SDP[0] */
137 + E1000_CMD_FORCE_PHY_RESET = 0x00008000, /* Reset both PHY ports, through PHYRST_N pin */
138 + E1000_CMD_EXT_LINK_EN = 0x00010000, /* enable link status from external LINK_0 and LINK_1 pins */
139 + E1000_CMD_SWDPIN0 = 0x00040000, /* SWDPIN 0 value */
140 + E1000_CMD_SWDPIN1 = 0x00080000, /* SWDPIN 1 value */
141 + E1000_CMD_SWDPIN2 = 0x00100000, /* SWDPIN 2 value */
142 + E1000_CMD_SWDPIN3 = 0x00200000, /* SWDPIN 3 value */
143 + E1000_CMD_SWDPIO0 = 0x00400000, /* SWDPIN 0 Input or output */
144 + E1000_CMD_SWDPIO1 = 0x00800000, /* SWDPIN 1 input or output */
145 + E1000_CMD_SWDPIO2 = 0x01000000, /* SWDPIN 2 input or output */
146 + E1000_CMD_SWDPIO3 = 0x02000000, /* SWDPIN 3 input or output */
147 + E1000_CMD_RST = 0x04000000, /* Global reset */
148 + E1000_CMD_RFCE = 0x08000000, /* Receive Flow Control enable */
149 + E1000_CMD_TFCE = 0x10000000, /* Transmit flow control enable */
150 + E1000_CMD_RTE = 0x20000000, /* Routing tag enable */
151 + E1000_CMD_VME = 0x40000000, /* IEEE VLAN mode enable */
152 + E1000_CMD_PHY_RST = 0x80000000, /* PHY Reset */
153 + E1000_CMD_SW2FW_INT = 0x02000000, /* Initiate an interrupt to manageability engine */
154 + E1000_INTR_TXDW = 0x00000001, /* Transmit desc written back */
155 + E1000_INTR_TXQE = 0x00000002, /* Transmit Queue empty */
156 + E1000_INTR_LSC = 0x00000004, /* Link Status Change */
157 + E1000_INTR_RXSEQ = 0x00000008, /* rx sequence error */
158 + E1000_INTR_RXDMT0 = 0x00000010, /* rx desc min. threshold (0) */
159 + E1000_INTR_RXO = 0x00000040, /* rx overrun */
160 + E1000_INTR_RXT0 = 0x00000080, /* rx timer intr (ring 0) */
161 + E1000_INTR_MDAC = 0x00000200, /* MDIO access complete */
162 + E1000_RAH_AV = (1 << 31), /* Set the MAC Address as Valid */
163 + E1000_RCTL_EN = (1 << 1), /* Receiver Enable */
164 + E1000_RCTL_BSEX = (1 << 25), /* Buffer Size Extension */
165 + E1000_RCTL_BSIZE_256 = ((1 << 16) | (1 << 17)),
166 + E1000_RCTL_BSIZE_512 = (1 << 17),
167 + E1000_RCTL_BSIZE_1024 = (1 << 16),
168 + E1000_RCTL_BSIZE_2048 = 0,
169 + E1000_RCTL_BSIZE_4096 = (E1000_RCTL_BSEX | (1 << 16) | (1 << 17)),
170 + E1000_RCTL_BSIZE_8192 = (E1000_RCTL_BSEX | (1 << 17)),
171 + E1000_RCTL_BSIZE_16384 = (E1000_RCTL_BSEX | (1 << 16)),
172 + E1000_TCTL_EN = (1 << 1), /* Transmitter Enable */
173 + E1000_TCTL_PSP = (1 << 3), /* Pad Short Packet */
174 + }
175 +
176 + map
177 + {
178 + }
179 + }
180 +
181 + template type e1000::TxDescriptorFlag()
182 + {
183 + decl data_types()
184 + {
185 + E1000_TXD_DTYP_D = 0x00100000, /* Data Descriptor */
186 + E1000_TXD_DTYP_C = 0x00000000, /* Context Descriptor */
187 + E1000_TXD_POPTS_IXSM = 0x01, /* Insert IP checksum */
188 + E1000_TXD_POPTS_TXSM = 0x02, /* Insert TCP/UDP checksum */
189 + E1000_TXD_CMD_EOP = 0x01000000, /* End of Packet */
190 + E1000_TXD_CMD_IFCS = 0x02000000, /* Insert FCS (Ethernet CRC) */
191 + E1000_TXD_CMD_IC = 0x04000000, /* Insert Checksum */
192 + E1000_TXD_CMD_RS = 0x08000000, /* Report Status */
193 + E1000_TXD_CMD_RPS = 0x10000000, /* Report Packet Sent */
194 + E1000_TXD_CMD_DEXT = 0x20000000, /* Descriptor extension (0 = legacy) */
195 + E1000_TXD_CMD_VLE = 0x40000000, /* Add VLAN tag */
196 + E1000_TXD_CMD_IDE = 0x80000000, /* Enable Tidv register */
197 + E1000_TXD_STAT_DD = 0x00000001, /* Descriptor Done */
198 + E1000_TXD_STAT_EC = 0x00000002, /* Excess Collisions */
199 + E1000_TXD_STAT_LC = 0x00000004, /* Late Collisions */
200 + E1000_TXD_STAT_TU = 0x00000008, /* Transmit underrun */
201 + E1000_TXD_CMD_TCP = 0x01000000, /* TCP packet */
202 + E1000_TXD_CMD_IP = 0x02000000, /* IP packet */
203 + E1000_TXD_CMD_TSE = 0x04000000, /* TCP Seg enable */
204 + E1000_TXD_STAT_TC = 0x00000004, /* Tx Underrun */
205 + }
206 +
207 + map
208 + {
209 + }
210 + }
211 +
212 + template type e1000::RxDescriptor()
213 + {
214 + decl data_types()
215 {
216 __le64 buff_addr;
217 __le16 length;
218 @@ -12,13 +152,39 @@
219 __le16 special;
220 }
221
222 - chunk LKM::includes() 114 - chunk LKM::includes()
223 + map 115 - {
224 {
225 - #include <linux/types.h> 116 - #include <linux/types.h>
226 } 117 - }
227 + } 118 -
228
229 - method init() 119 - method init()
230 + // This is a generic tx descriptor for the e1000. When you use TCP 120 - {
231 + // Segmentation Offload (TSO) the hardware actually uses two types of 121 - }
232 + // tx descriptors in its tx ring: 122 -
233 + // - context descriptors: this descriptor doesn't actually point to data to 123 - map
234 + // send but initialize the offloading engine for the data descriptor that 124 - {
235 + // follow; 125 - }
236 + // - data descriptors: this descriptor points to data from the skbuffs. 126 - }
237 + template type e1000::TxDescriptor() 127 -
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 @@ -26,44 +192,131 @@
262 }
263 }
264
265 - /* 128 - /*
266 - * This is a generic tx descriptor for the e1000. When you use TCP 129 - * This is a generic tx descriptor for the e1000. When you use TCP
267 - * Segmentation Offload (TSO) the hardware actually uses two types of 130 - * Segmentation Offload (TSO) the hardware actually uses two types of
268 - * tx descriptors in its tx ring: 131 - * tx descriptors in its tx ring:
269 - * - context descriptors: this descriptor doesn't actually point to data to 132 - * - context descriptors: this descriptor doesn't actually point to data to
270 - * send but initialize the offloading engine for the data descriptor that 133 - * send but initialize the offloading engine for the data descriptor that
271 - * follow; 134 - * follow;
272 - * - data descriptors: this descriptor points to data from the skbuffs. 135 - * - data descriptors: this descriptor points to data from the skbuffs.
273 - */ 136 - */
274 - template type e1000::TxDescriptor() 137 - template type e1000::TxDescriptor()
275 + template type e1000::Buffer() 138 - {
276 {
277 - decl data_types() 139 - decl data_types()
278 + decl data_types() 140 - {
279 {
280 - __le64 buff_addr; 141 - __le64 buff_addr;
281 - union 142 - union
282 - { 143 - {
283 - __le32 data; 144 - __le32 data;
284 - struct 145 - struct
296 - unsigned char status; 157 - unsigned char status;
297 - unsigned char csum_start; /* CSS */ 158 - unsigned char csum_start; /* CSS */
298 - __le16 special; 159 - __le16 special;
299 - } fields; 160 - } fields;
300 - } upper; 161 - } upper;
301 + ${Socket::SKBuff} sk_buff; 162 - }
302 + ${DMA::DMAHandle} dma; 163 -
303 }
304
305 - method init() 164 - method init()
306 + method init(Socket::SKBuff sk_buff, DMA::DMAHandle dma) 165 - {
307 { 166 - }
308 + ${self.sk_buff} = ${sk_buff}; 167 -
309 + ${self.dma} = ${dma}; 168 - map
310 + } 169 - {
311 + 170 - }
312 + map 171 - }
313 + { 172 -
314 + sk_buff: ${self}->sk_buff;
315 + dma: ${self}->dma;
316 + }
317 + }
318 +
319 + template type e1000::MMIO()
320 + {
321 + decl data_types()
322 + {
323 + unsigned char *io;
324 + }
325 +
326 + // XXX: we'll need those functions until we get working methods (#46):
327 +
328 + chunk LKM::prototypes()
329 + {
330 + static unsigned int rtx_e1000_reg_read32(${e1000::MMIO}, ${e1000::Register});
331 + static void rtx_e1000_reg_write32(${e1000:::MMIO}, ${e1000::Register}, ${Builtin::number});
332 + static void rtx_e1000_reg_set32(${e1000:::MMIO}, ${e1000::Register}, ${Builtin::number});
333 + static void rtx_e1000_reg_unset32(${e1000:::MMIO}, ${e1000::Register}, ${Builtin::number});
334 + }
335 +
336 + chunk LKM::code()
337 + {
338 + static unsigned int rtx_e1000_reg_read32(${e1000::MMIO} io, ${e1000::Register} reg)
339 + {
340 + return ioread32(${local.io.io} + reg);
341 + }
342 +
343 + static void rtx_e1000_reg_write32(${e1000:::MMIO} io, ${e1000::Register} reg, ${Builtin::number} value)
344 + {
345 + return iowrite32(value, ${local.io.io} + reg);
346 + }
347 +
348 + static void rtx_e1000_reg_set32(${e1000:::MMIO} io, ${e1000::Register} reg, ${Builtin::number} value)
349 + {
350 + return iowrite32(rtx_e1000_reg_read32(io, reg) | value, ${local.io.io} + reg);
351 + }
352 +
353 + static void rtx_e1000_reg_unset32(${e1000:::MMIO} io, ${e1000::Register} reg, ${Builtin::number} value)
354 + {
355 + return iowrite32(rtx_e1000_reg_read32(io, reg) & ~value, ${local.io.io} + reg);
356 + }
357 + }
358 +
359 + method init(Builtin::symbol io)
360 + {
361 + ${self.io} = ${io};
362 + }
363 +
364 + method read32(e1000::Register reg)
365 + {
366 + ioread32(${self.io} + ${local.reg});
367 + }
368 +
369 + method write32(e1000::Register reg, Builtin::number value)
370 + {
371 + iowrite32(${local.value}, ${self.io} + ${local.reg});
372 + }
373 +
374 + method set32(e1000::Register reg, Builtin::number value)
375 + {
376 + iowrite32(ioread32(${self.io} + ${local.reg}) | value, ${self.io} + ${local.reg});
377 + }
378 +
379 + method unset32(e1000::Register reg, Builtin::number value)
380 + {
381 + iowrite32(ioread32(${self.io} + ${local.reg}) & ~value, ${self.io} + ${local.reg});
382 + }
383 +
384 + map
385 + {
386 + io: ((unsigned char *)(${self}));
387 + }
388 + }
389 +
390 + template type e1000::Ring()
391 + {
392 + decl data_types()
393 + {
394 + ${e1000::MMIO} io;
395 + ${DMA::DMAHandle} dma;
396 + ${Builtin::symbol.ref} descs;
397 + ${Builtin::number} size;
398 + ${e1000::Buffer.ref} buffs;
399 + }
400 +
401 + chunk LKM::prototypes()
402 + {
403 + static void rtx_e1000_ring_init(${e1000::Ring.ref}, ${e1000::MMIO},
404 + ${Builtin::number}, ${Builtin::number});
405 + }
406 +
407 + chunk LKM::code()
408 + {
409 + static void rtx_e1000_ring_init(${e1000::Ring.ref} self,
410 + ${e1000::MMIO} io,
411 + ${Builtin::number} desc_count,
412 + ${Builtin::number} desc_size)
413 + {
414 + memset(self, 0, sizeof(*self));
415 + self->size = ALIGN(desc_count * desc_size, 4096);
416 + self->io = io;
417 + }
418 + }
419 +
420 + method init(e1000::MMIO io, Builtin::number desc_count, Builtin::number desc_size)
421 + {
422 + rtx_e1000_ring_init(&${self}, ${io}, ${desc_count}, ${desc_size});
423 }
424
425 map
426 @@ -71,32 +324,27 @@
427 }
428 }
429
430 - /* 173 - /*
431 - * Ring of e1000::RxDescriptors and their corresponding skbuffs. 174 - * Ring of e1000::RxDescriptors and their corresponding skbuffs.
432 - * 175 - *
433 - * - size: total size of the ring in bytes. 176 - * - size: total size of the ring in bytes.
434 - * - base: address of the ring (we can't use the typedef here until we get 177 - * - base: address of the ring (we can't use the typedef here until we get
437 - * the different descriptors; 180 - * the different descriptors;
438 - * - skbuffs: array of the skbuffs and their dma (physical) address 181 - * - skbuffs: array of the skbuffs and their dma (physical) address
439 - * associated with each descriptor. 182 - * associated with each descriptor.
440 - */ 183 - */
441 - template type e1000::RxRing() 184 - template type e1000::RxRing()
442 + template type e1000::RxRing() 185 - {
443 {
444 - decl data_types() 186 - decl data_types()
445 + decl data_types() 187 - {
446 {
447 - unsigned int size; 188 - unsigned int size;
448 - ${e1000::RxDescriptor.ref} base; 189 - ${e1000::RxDescriptor.ref} base;
449 - dma_addr_t dma_base; 190 - dma_addr_t dma_base;
450 - ${Socket::SKBuff} skbuffs[${config.rx_ring_size}]; 191 - ${Socket::SKBuff} skbuffs[${config.rx_ring_size}];
451 + ${e1000::Ring} ring; 192 - }
452 } 193 -
453
454 - method init() 194 - method init()
455 + chunk LKM::prototypes() 195 - {
456 { 196 - }
457 + static int rtx_e1000_alloc_rx_ressources(${e1000::RxRing.ref}); 197 -
458 }
459
460 - chunk Ethernet::adapter_init_rx(Ethernet::Device rtx_ether_ctx) 198 - chunk Ethernet::adapter_init_rx(Ethernet::Device rtx_ether_ctx)
461 + chunk LKM::code() 199 - {
462 + { 200 - {
463 + static int rtx_e1000_alloc_rx_ressources(${e1000::RxRing.ref} self) 201 - ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx;
464 + { 202 -
465 + return 0; 203 - /*
466 + } 204 - * Receive initialization (section 14.4):
467 + } 205 - *
468 + 206 - * 1. Program the receive address, in RAL/RAH;
469 + chunk Ethernet::adapter_init_rx(Ethernet::Device rtx_ether_ctx) 207 - * 2. Initialize the Multicast Table Array;
470 { 208 - * 3. Program the interrupt mask register (done in
471 { 209 - * e1000::activate_device_interruption);
472 ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; 210 - * 4. Allocate the receive descriptor ring and map it to make it
473 @@ -167,18 +415,16 @@ 211 - * accessible by the device;
474 * Allocate the skbuffs, map them for DMA, and write their address 212 - * 5. Write the start address of the ring in RDBAL/RDBAH and set
475 * in the corresponding descriptor. 213 - * RDLEN (Receive Descriptor Length) to the size of the ring;
476 */ 214 - * 6. Set the RDH/RDT (Receive Descriptor Head/Tail) indexes to the
215 - * beginning and end of the ring;
216 - * 7. Make sure that RCTL.BSIZE and .BSEX are at 0 to configure the
217 - * receive buffer size to 2048 bytes (e1000::rx_buffer_len).
218 - * 8. Set RCTL.EN to enable the receiver.
219 - *
220 - * The ugly casts here are caused by the lack of CNorm unstrict.
221 - */
222 -
223 - int i;
224 -
225 - /* 1. Program the receive address */
226 -
227 - /* (We should use uint{32,16}_t but CNorm doesn't know them yet) */
228 - rtx_e1000_register_write32(hw_ctx, E1000_RAL,
229 - *(unsigned int *)(${rtx_ether_ctx.dev_addr}));
230 - /*
231 - * The 16 upper bits of RAH also store the AS bits (which should be
232 - * 0) and the AV bit (should be 1 to set the address as valid).
233 - */
234 - rtx_e1000_register_write32(hw_ctx, E1000_RAH,
235 - *(unsigned short *)(&${rtx_ether_ctx.dev_addr}[4]));
236 - rtx_e1000_register_set32(hw_ctx, E1000_RAH, E1000_RAH_AV);
237 -
238 - ${Log::info("adapter_init_rx: receive address programmed")};
239 -
240 - /* 2. Initialize the MTA */
241 -
242 - for (i = 0; i != 128; ++i)
243 - rtx_e1000_register_write32(hw_ctx, E1000_MTA + i * 4, 0);
244 -
245 - ${Log::info("adapter_init_rx: MTA init done")};
246 -
247 - /* 4. Setup the receive descriptor ring */
248 -
249 - /* Allocate the descriptors */
250 - hw_ctx->rx_ring.size = ${config.rx_ring_size} * sizeof(*hw_ctx->rx_ring.base);
251 - hw_ctx->rx_ring.size = ALIGN(hw_ctx->rx_ring.size, 4096);
252 - hw_ctx->rx_ring.base = ${DMA::alloc_coherent(
253 - rtx_ether_ctx.device,
254 - local.hw_ctx.rx_ring.size,
255 - local.hw_ctx.rx_ring.dma_base.dma_handle
256 - )};
257 - if (!hw_ctx->rx_ring.base)
258 - {
259 - ${Log::info("adapter_init_rx: cannot allocate the descriptors for the rx ring")};
260 - goto err_rx_ring_alloc;
261 - }
262 -
263 - ${Log::info("adapter_init_rx: rx descriptors allocated")};
264 -
265 - /*
266 - * Allocate the skbuffs, map them for DMA, and write their address
267 - * in the corresponding descriptor.
268 - */
477 - for (i = 0; i != ${config.rx_ring_size}; ++i) 269 - for (i = 0; i != ${config.rx_ring_size}; ++i)
478 - { 270 - {
479 + for (i = 0; i != ${config.rx_ring_size}; ++i) { 271 - ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i];
480 ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i];
481 - // XXX #46: ${rtx_ether_ctx.init_rx_skbuff(local.skbuff, config.rx_buffer_len)}; 272 - // XXX #46: ${rtx_ether_ctx.init_rx_skbuff(local.skbuff, config.rx_buffer_len)};
482 - if (rtx_ethernet_init_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len})) 273 - if (rtx_ethernet_init_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len}))
483 - { 274 - {
484 + // XXX #46: ${rtx_ether_ctx.alloc_rx_skbuff(local.skbuff, config.rx_buffer_len)}; 275 - ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")};
485 + if (rtx_ethernet_alloc_rx_skbuff(${local.skbuff}, ${config.rx_buffer_len})) { 276 - goto err_skbuffs_alloc;
486 ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")}; 277 - }
487 goto err_skbuffs_alloc;
488 }
489 - // XXX #46: ${local.skbuff.map_from(rtx_ether_ctx.device)}; 278 - // 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)) 279 - if (rtx_socket_skbuff_map(${local.skbuff}, ${rtx_ether_ctx.device}, RTX_DMA_FROM_DEVICE))
491 - { 280 - {
492 + /* XXX: recuperer le dma handle et le placer correctement dans le descripteur. */ 281 - ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")};
493 + ${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)} 282 - goto err_skbuffs_map;
494 + if (${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)}) { 283 - }
495 ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")}; 284 - hw_ctx->rx_ring.base[i].buff_addr = cpu_to_le64(${local.skbuff.sk_buff});
496 goto err_skbuffs_map; 285 - }
497 } 286 -
498 @@ -212,8 +458,7 @@ 287 - // ${Log::info("adapter_init_rx: skbuffs allocated};
499 goto init_rx_ok; 288 - pr_info("rtx_e1k: adapter_init_rx: skbuffs allocated, headlen=%d", skb_headlen((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i - 1].skbuff));
500 289 -
501 err_skbuffs_alloc: 290 - /* 5. Save the emplacement and the size of the ring in RDBA/RDLEN */
291 - rtx_e1000_register_write32(hw_ctx, E1000_RDBAL, hw_ctx->rx_ring.dma_base & 0xffffffff);
292 - rtx_e1000_register_write32(hw_ctx, E1000_RDBAH, hw_ctx->rx_ring.dma_base >> 32);
293 - rtx_e1000_register_write32(hw_ctx, E1000_RDLEN, hw_ctx->rx_ring.size);
294 -
295 - /* 6. Setup RDH/RDT */
296 - rtx_e1000_register_write32(hw_ctx, E1000_RDH, 0);
297 - rtx_e1000_register_write32(hw_ctx, E1000_RDT, ${config.rx_ring_size} - 1);
298 -
299 - /* 7. Configure the buffer size, */
300 - rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_BSIZE_${config.rx_buffer_len});
301 -
302 - /* 8. Enable the receiver */
303 - rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_EN);
304 -
305 - ${Log::info("adapter_init_rx: receive registers configured and receiver enabled")};
306 -
307 - /*
308 - * XXX: We can't return here since we are not in a function but
309 - * in a chunk of code (injected in a function).
310 - */
311 - goto init_rx_ok;
312 -
313 - err_skbuffs_alloc:
502 - while (i--) 314 - while (i--)
503 - { 315 - {
504 + while (i--) { 316 - dma_unmap_single(
505 dma_unmap_single( 317 - ${rtx_ether_ctx.device},
506 ${rtx_ether_ctx.device}, 318 - /* XXX Leaking cast because of the array: */
507 /* XXX Leaking cast because of the array: */ 319 - *((dma_addr_t *)&(hw_ctx->rx_ring.skbuffs[i].dma_handle)),
508 @@ -238,487 +483,87 @@ 320 - ${config.rx_buffer_len},
509 } 321 - DMA_FROM_DEVICE);
510 } 322 - err_skbuffs_map:
511 323 - /* XXX leaking cast: */
324 - dev_kfree_skb((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff);
325 - }
326 -
327 - dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx->rx_ring.size,
328 - hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base);
329 - err_rx_ring_alloc:
330 - /*
331 - * XXX: Likewise, if there is something else to rollback in the
332 - * enclosing function, this won't be done.
333 - */
334 - return -ENOMEM;
335 -
336 - init_rx_ok: (void)0; /* NOP, to make this a valid label. */
337 - }
338 - }
339 -
512 - map 340 - map
513 + method init(e1000::MMIO io, Builtin::number desc_count) 341 - {
514 {
515 - size: ((${self}).size); 342 - size: ((${self}).size);
516 - dma_base: ((${self}).dma_base); 343 - dma_base: ((${self}).dma_base);
517 - } 344 - }
518 - } 345 - }
519 - 346 -
543 - ${e1000::TxDescriptor.ref} base; /* rename to descs */ 370 - ${e1000::TxDescriptor.ref} base; /* rename to descs */
544 - dma_addr_t dma_base; 371 - dma_addr_t dma_base;
545 - ${Socket::SKBuff} skbuffs[${config.tx_ring_size}]; 372 - ${Socket::SKBuff} skbuffs[${config.tx_ring_size}];
546 - unsigned short head; 373 - unsigned short head;
547 - unsigned short tail; 374 - unsigned short tail;
548 + ${self.ring.init(local.io, local.desc_count, self.desc_size)}; 375 - }
549 } 376 -
550
551 - chunk LKM::prototypes() 377 - chunk LKM::prototypes()
552 + method alloc() 378 - {
553 {
554 - static void rtx_e1000_tx_ring_clean(${e1000::TxRing.ref}); 379 - static void rtx_e1000_tx_ring_clean(${e1000::TxRing.ref});
555 - static unsigned int rtx_e1000_tx_ring_descriptors_remaining(${e1000::TxRing.ref}); 380 - 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}); 381 - 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}); 382 - static void rtx_e1000_tx_ring_put(${e1000::TxRing.ref}, ${Socket::SKBuff.ref});
558 - /* FIXME: See issue #54 */ 383 - /* FIXME: See issue #54 */
705 - rtx_e1000_tx_ring_start_xmit(${self}, ${ctx}); 530 - rtx_e1000_tx_ring_start_xmit(${self}, ${ctx});
706 - } 531 - }
707 - 532 -
708 - method init() 533 - method init()
709 - { 534 - {
710 + rtx_e1000_alloc_rx_ressources(${self}); 535 - }
711 } 536 -
712 537 - map
713 map 538 - {
714 { 539 - }
715 + descs: ((${self})->descs); // TODO: fix cast pour directement avoir les descs 540 - }
716 + desc_size: sizeof(/* XXX ${e1000::RxDescriptor} */int); 541 -
717 }
718 }
719
720 - template type e1000::Context() 542 - template type e1000::Context()
721 + template type e1000::TxRing() 543 - {
722 {
723 - decl data_types() 544 - decl data_types()
724 + decl data_types() 545 - {
725 {
726 - int bars; 546 - int bars;
727 - unsigned char /* __iomem */ *ioaddr; 547 - unsigned char /* __iomem */ *ioaddr;
728 - ${e1000::RxRing.scalar} rx_ring; 548 - ${e1000::RxRing.scalar} rx_ring;
729 - ${e1000::TxRing.scalar} tx_ring; 549 - ${e1000::TxRing.scalar} tx_ring;
730 + ${e1000::Ring} ring; 550 - }
731 } 551 -
732
733 - chunk Ethernet::HardwareContext() 552 - chunk Ethernet::HardwareContext()
734 + chunk LKM::prototypes() 553 - {
735 {
736 - /* 554 - /*
737 - * Force the generation of the structure in the "headers" part, we 555 - * 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 556 - * 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). 557 - * (we hacked a bit and used it in ethernet.blt directly).
740 - */ 558 - */
741 - ${e1000::Context} hw_ctx; 559 - ${e1000::Context} hw_ctx;
742 + static int rtx_e1000_alloc_tx_ressources(${e1000::TxRing.ref}); 560 - }
743 } 561 -
744
745 - chunk Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx, 562 - chunk Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx,
746 - Builtin::number bars, 563 - Builtin::number bars,
747 - Builtin::symbol ioaddr) 564 - Builtin::symbol ioaddr)
748 + chunk LKM::code() 565 - {
749 { 566 - {
750 + static int rtx_e1000_alloc_tx_ressources(${e1000::TxRing.ref} self)
751 {
752 - ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; 567 - ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx;
753 - hw_ctx->bars = ${bars}; 568 - hw_ctx->bars = ${bars};
754 - hw_ctx->ioaddr = ${ioaddr}; 569 - hw_ctx->ioaddr = ${ioaddr};
755 + return 0; 570 - }
756 } 571 - }
757 } 572 -
758
759 - chunk Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx) 573 - chunk Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx)
760 + method init(e1000::MMIO io, Builtin::number desc_count) 574 - {
761 {
762 - { 575 - {
763 - /* XXX Naming this variable 'hw_ctx' kicks the decl out of the generated code */ 576 - /* 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; 577 - ${e1000::Context.ref} tmp_hw_ctx = &${rtx_ether_ctx}->hw_ctx;
765 - rtx_e1000_register_write32(tmp_hw_ctx, E1000_CTRL, E1000_CMD_RST); 578 - rtx_e1000_register_write32(tmp_hw_ctx, E1000_CTRL, E1000_CMD_RST);
766 - udelay(10); 579 - udelay(10);
767 - } 580 - }
768 + ${self.ring.init(local.io, local.desc_count, self.desc_size)}; 581 - }
769 } 582 -
770
771 - chunk Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx) 583 - chunk Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx)
772 + method alloc() 584 - {
773 {
774 - { 585 - {
775 - ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; 586 - ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx;
776 - /* Shamelessly borrowed from Minix */ 587 - /* Shamelessly borrowed from Minix */
777 - for (int i = 0; i < 3; ++i) 588 - for (int i = 0; i < 3; ++i)
778 - { 589 - {
833 - for (int j = 0; j != 64; ++j) 644 - for (int j = 0; j != 64; ++j)
834 - rtx_e1000_register_write32(hw_ctx, E1000_CRCERRS + j * 4, 0); 645 - rtx_e1000_register_write32(hw_ctx, E1000_CRCERRS + j * 4, 0);
835 - 646 -
836 - ${Log::info("adapter_setup: general configuration done")}; 647 - ${Log::info("adapter_setup: general configuration done")};
837 - } 648 - }
838 + rtx_e1000_alloc_tx_ressources(${self}); 649 - }
839 } 650 -
840 651 - map
841 map 652 - {
842 {
843 - rx_ring: ((${self})->rx_ring); 653 - rx_ring: ((${self})->rx_ring);
844 - //tx_ring: ((${self})->tx_ring); XXX Circular dep with Context 654 - //tx_ring: ((${self})->tx_ring); XXX Circular dep with Context
845 + descs: ((${self})->descs); // TODO: fix cast pour directement avoir les descs 655 - }
846 + desc_size: sizeof(/* XXX ${e1000::TxDescriptor} */int); 656 - }
847 } 657 -
848 }
849
850 - template type e1000::Register() 658 - template type e1000::Register()
851 + template type e1000::Context() 659 - {
852 {
853 - decl data_types() 660 - decl data_types()
854 + decl data_types() 661 + decl data_types()
855 { 662 {
856 - E1000_CTRL = 0x00000, /* Device Control - RW */ 663 E1000_CTRL = 0x00000, /* Device Control - RW */
857 - E1000_CTRL_DUP = 0x00004, /* Device Control Duplicate (Shadow) - RW */ 664 E1000_CTRL_DUP = 0x00004, /* Device Control Duplicate (Shadow) - RW */
858 - E1000_STATUS = 0x00008, /* Device Status - RO */ 665 @@ -593,19 +37,14 @@
859 - E1000_EEPROM_FLASH = 0x00010, /* EEPROM/Flash Control - RW */ 666 E1000_TDT = 0x03818, /* Transmit Descriptor Tail */
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 */
887 + ${e1000::MMIO} io;
888 + ${e1000::TxRing} tx_ring;
889 + ${e1000::RxRing} rx_ring;
890 } 667 }
891 668
892 - method init(Builtin::number value) 669 - method init(Builtin::number value)
893 + chunk LKM::includes() 670 - {
894 {
895 - ${self} = ${value}; 671 - ${self} = ${value};
896 + #include <linux/types.h> 672 - }
897 } 673 -
898 674 map
899 - map 675 {
900 - { 676 }
901 - } 677 }
902 - } 678
903 -
904 - template type e1000::Commands() 679 - template type e1000::Commands()
905 - { 680 + template type e1000::Command()
681 {
906 - decl data_types() 682 - decl data_types()
907 - { 683 + decl data_types()
908 - E1000_CMD_FD = 0x00000001, /* Full duplex.0=half; 1=full */ 684 {
909 - E1000_CMD_BEM = 0x00000002, /* Endian Mode.0=little,1=big */ 685 E1000_CMD_FD = 0x00000001, /* Full duplex.0=half; 1=full */
910 - E1000_CMD_PRIOR = 0x00000004, /* Priority on PCI. 0=rx,1=fair */ 686 E1000_CMD_BEM = 0x00000002, /* Endian Mode.0=little,1=big */
911 - E1000_CMD_GIO_MASTER_DISABLE = 0x00000004, /* Blocks new Master requests */ 687 @@ -670,9 +109,9 @@
912 - E1000_CMD_LRST = 0x00000008, /* Link reset. 0=normal,1=reset */ 688 }
913 - E1000_CMD_TME = 0x00000010, /* Test mode. 0=normal,1=test */ 689 }
914 - E1000_CMD_SLE = 0x00000020, /* Serial Link on 0=dis,1=en */ 690
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() 691 - template type e1000::TxDescriptorFlags()
972 - { 692 + template type e1000::TxDescriptorFlag()
693 {
973 - decl data_types() 694 - decl data_types()
974 - { 695 + decl data_types()
975 - E1000_TXD_DTYP_D = 0x00100000, /* Data Descriptor */ 696 {
976 - E1000_TXD_DTYP_C = 0x00000000, /* Context Descriptor */ 697 E1000_TXD_DTYP_D = 0x00100000, /* Data Descriptor */
977 - E1000_TXD_POPTS_IXSM = 0x01, /* Insert IP checksum */ 698 E1000_TXD_DTYP_C = 0x00000000, /* Context Descriptor */
978 - E1000_TXD_POPTS_TXSM = 0x02, /* Insert TCP/UDP checksum */ 699 @@ -701,326 +140,656 @@
979 - E1000_TXD_CMD_EOP = 0x01000000, /* End of Packet */ 700 }
980 - E1000_TXD_CMD_IFCS = 0x02000000, /* Insert FCS (Ethernet CRC) */ 701 }
981 - E1000_TXD_CMD_IC = 0x04000000, /* Insert Checksum */ 702
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 */ 703 - /* TODO: make that a method of e1000::Context */
1003 - template sequence e1000::print_status(Ethernet::Device rtx_ether_ctx) 704 - template sequence e1000::print_status(Ethernet::Device rtx_ether_ctx)
1004 - { 705 + template type e1000::RxDescriptor()
706 {
1005 - chunk LKM::prototypes() 707 - chunk LKM::prototypes()
708 + decl data_types()
709 + {
710 + __le64 buff_addr;
711 + __le16 length;
712 + __le16 csum;
713 + unsigned char status;
714 + unsigned char errors;
715 + __le16 special;
716 + }
717 +
718 + map
719 + {
720 + }
721 + }
722 +
723 + // This is a generic tx descriptor for the e1000. When you use TCP
724 + // Segmentation Offload (TSO) the hardware actually uses two types of
725 + // tx descriptors in its tx ring:
726 + // - context descriptors: this descriptor doesn't actually point to data to
727 + // send but initialize the offloading engine for the data descriptor that
728 + // follow;
729 + // - data descriptors: this descriptor points to data from the skbuffs.
730 + template type e1000::TxDescriptor()
731 + {
732 + decl data_types()
733 + {
734 + __le64 buff_addr;
735 + union {
736 + __le32 data;
737 + struct {
738 + __le16 length;
739 + unsigned char csum_offset; /* CSO */
740 + unsigned char cmd;
741 + } fields;
742 + } lower;
743 + union {
744 + __le32 data;
745 + struct {
746 + unsigned char status;
747 + unsigned char csum_start; /* CSS */
748 + __le16 special;
749 + } fields;
750 + } upper;
751 + }
752 +
753 + map
754 + {
755 + }
756 + }
757 +
758 + template type e1000::Buffer()
759 + {
760 + decl data_types()
761 + {
762 + ${Socket::SKBuff} sk_buff;
763 + ${DMA::DMAHandle} dma;
764 + }
765 +
766 + method init(Socket::SKBuff sk_buff, DMA::DMAHandle dma)
767 + {
768 + ${self.sk_buff} = ${sk_buff};
769 + ${self.dma} = ${dma};
770 + }
771 +
772 + map
773 + {
774 + sk_buff: ${self}->sk_buff;
775 + dma: ${self}->dma;
776 + }
777 + }
778 +
779 + template type e1000::Context()
780 + {
781 + decl data_types()
782 + {
783 + unsigned char *io_addr; // XXX should be annoted with __iomem
784 + // XXX Forced to hardcode the type because there is a circular
785 + // dependency between the rings and the context.
786 + // TODO: get the right generated types:
787 + int tx_ring;
788 + int rx_ring;
789 + }
790 +
791 + chunk LKM::includes()
792 + {
793 + #include <linux/types.h>
794 + }
795 +
1006 + chunk LKM::prototypes() 796 + chunk LKM::prototypes()
1007 { 797 {
1008 static void rtx_e1000_print_status(${e1000::Context.ref}); 798 static void rtx_e1000_print_status(${e1000::Context.ref});
799 +
800 + // XXX Needed until we can call methods (issue #46):
801 + static unsigned int rtx_e1000_reg_read32(${e1000::Context}, ${e1000::Register});
802 + static void rtx_e1000_reg_write32(${e1000::Context}, ${e1000::Register}, unsigned int);
803 + static void rtx_e1000_reg_set32(${e1000::Context}, ${e1000::Register}, unsigned int);
804 + static void rtx_e1000_reg_unset32(${e1000::Context}, ${e1000::Register}, unsigned int);
1009 } 805 }
1010 806
1011 - chunk LKM::code() 807 - chunk LKM::code()
1012 + chunk LKM::code() 808 + chunk LKM::code()
1013 { 809 {
1014 static void rtx_e1000_print_status(${e1000::Context.ref} hw_ctx) 810 - static void rtx_e1000_print_status(${e1000::Context.ref} hw_ctx)
811 + static void rtx_e1000_print_status(${e1000::Context.ref} self)
1015 { 812 {
1016 - unsigned int status = rtx_e1000_register_read32(hw_ctx, E1000_STATUS); 813 - unsigned int status = rtx_e1000_register_read32(hw_ctx, E1000_STATUS);
1017 - ${Log::info("card status:")}; 814 - ${Log::info("card status:")};
1018 - /* 815 - /*
1019 - * we can't use Log::info below because it just accept a string 816 - * we can't use Log::info below because it just accept a string
1020 - * (as opposed to a format string with its parameters). 817 - * (as opposed to a format string with its parameters).
1021 - */ 818 - */
1022 + unsigned int status = rtx_e1000_reg_read32(hw_ctx, E1000_STATUS); 819 + unsigned int status = rtx_e1000_reg_read32(${local.self}, E1000_STATUS);
1023 + ${Log::info("card status:")}; 820 + ${Log::info("card status:")};
1024 + // XXX We can't use Log::info below because it just accept a 821 + // XXX We can't use Log::info below because it just accepts a
1025 + // string (as opposed to a format string with its parameters): 822 + // string (as opposed to a format string with its arguments):
1026 pr_info("\tRegister value: 0x%x\n", status); 823 pr_info("\tRegister value: 0x%x\n", status);
1027 pr_info("\tMode: %s\n", (status & 1) ? "Full": "Half"); 824 pr_info("\tMode: %s\n", (status & 1) ? "Full": "Half");
1028 pr_info("\tLink: %s\n", (status & 2) ? "Up" : "Down"); 825 pr_info("\tLink: %s\n", (status & 2) ? "Up" : "Down");
1029 @@ -727,300 +572,178 @@ 826 pr_info("\tTransmission: %s\n", (status & 4) ? "Paused" : "Ok");
827 pr_info("\tInterface: %s\n", (status & 3) == 3 ? "Up" : "Down");
1030 } 828 }
829 +
830 + static unsigned int rtx_e1000_reg_read32(${e1000::Context} self, ${e1000::Register} reg)
831 + {
832 + return ioread32(${local.self.io_addr} + reg);
833 + }
834 +
835 + static void rtx_e1000_reg_write32(${e1000::Context} self,
836 + ${e1000::Register} reg,
837 + unsigned int value)
838 + {
839 + return iowrite32(value, ${local.self.io_addr.io} + reg);
840 + }
841 +
842 + static void rtx_e1000_reg_set32(${e1000::Context} self,
843 + ${e1000::Register} reg,
844 + unsigned int value)
845 + {
846 + return iowrite32(
847 + rtx_e1000_reg_read32(${local.self}, reg) | value,
848 + ${local.self.io_addr.io} + reg
849 + );
850 + }
851 +
852 + static void rtx_e1000_reg_unset32(${e1000::Context} self,
853 + ${e1000::Register} reg,
854 + unsigned int value)
855 + {
856 + return iowrite32(rtx_e1000_reg_read32(
857 + ${local.self}, reg) & ~value,
858 + ${local.self.io_addr.io} + reg
859 + );
860 + }
1031 } 861 }
1032 862
1033 - chunk ::CALL() 863 - chunk ::CALL()
864 + method init(Builtin::symbol io_addr)
865 {
866 - rtx_e1000_print_status(&${rtx_ether_ctx}->hw_ctx);
867 + ${self.io_addr} = ${io_addr};
868 + }
869 +
870 + method reg_read32(e1000::Register reg)
871 + {
872 + ioread32(${self.io_addr} + ${local.reg});
873 + }
874 +
875 + method reg_write32(e1000::Register reg, Builtin::number value)
876 + {
877 + iowrite32(${value}, ${self.io_addr} + ${reg});
878 + }
879 +
880 + method reg_set32(e1000::Register reg, Builtin::number value)
881 + {
882 + iowrite32(ioread32(${self.io_addr} + ${reg}) | ${value}, ${self.io_addr} + ${reg});
883 + }
884 +
885 + method reg_unset32(e1000::Register reg, Builtin::number value)
886 + {
887 + iowrite32(ioread32(${self.io_addr} + ${reg}) & ~${value}, ${self.io_addr} + ${reg});
888 + }
889 +
1034 + chunk Ethernet::HardwareContext() 890 + chunk Ethernet::HardwareContext()
1035 { 891 + {
1036 - rtx_e1000_print_status(&${rtx_ether_ctx}->hw_ctx); 892 + ${e1000::Context} hw_ctx;
1037 - } 893 + }
1038 - } 894 +
1039 - 895 + chunk Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx, Builtin::symbol io_addr)
896 + {
897 + {
898 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx;
899 + ${local.hw_ctx.init(local.io_addr)};
900 + ${local.hw_ctx.rx_ring.init(local.hw_ctx.io, config.rx_ring_size)};
901 + ${local.hw_ctx.tx_ring.init(local.hw_ctx.io, config.tx_ring_size)};
902 + }
903 + }
904 +
905 + chunk Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx)
906 + {
907 + {
908 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx;
909 + // XXX #46: ${local.hw_ctx.io.write32(E1000_CTRL, E1000_CMD_RST)};
910 + rtx_e1000_reg_write32(hw_ctx, E1000_CTRL, E1000_CMD_RST);
911 + udelay(10); // TODO: abstract udelay too...
912 + ${Log::info("adapter has been reset")};
913 + }
914 + }
915 +
916 + chunk Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx)
917 + {
918 + {
919 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx;
920 + // Shamelessly borrowed from Minix
921 + for (int i = 0; i < 3; ++i) {
922 + rtx_e1000_reg_write32(hw_ctx, E1000_EEPROM_READ, (i << 8) | 1);
923 + int value;
924 + do {
925 + value = rtx_e1000_reg_read32(hw_ctx, E1000_EEPROM_READ);
926 + } while ((value & (1 << 4)) == 0);
927 + value >>= 16;
928 + // NOTE: I'm not sure if Ethernet::Device should be
929 + // accessed directly here. But since we need to take it in
930 + // parameter (so we can get back our e1000::Context) it
931 + // seems inadequate to set this in another way:
932 + ${local.rtx_ether_ctx.dev_addr}[i * 2] = value & 0xff;
933 + ${local.rtx_ether_ctx.dev_addr}[i * 2 + 1] = (value >> 8) & 0xff;
934 + }
935 +
936 + ${Log::info("mac address loaded from the EEPROM")};
937 + }
938 + }
939 +
940 + // For e1000, this part is documented in the Intel Gigabit Ethernet
941 + // Controller Software Developper manual. (You can find it in the
942 + // doc/hardware directory).
943 + chunk Ethernet::adapter_setup_rx_tx(Ethernet::Device rtx_ether_ctx)
944 + {
945 + {
946 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx;
947 +
948 + // "General Configuration" (section 14.3):
949 + //
950 + // - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection &
951 + // negociation;
952 + // - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation;
953 + // - CTRL.PHY_RST: Unset it;
954 + // - CTRL.ILOS: Unset it (ILOS is Invert Loss Of Signal);
955 + // - CTRL.VME: Make sure it's not set to disable VLAN support;
956 + // - Set the control flow registers to 0;
957 + // - Finally, initialize all the statistic registers from
958 + // E1000_CRCERRS to E1000_TSCTFC.
959 +
960 + // XXX #46: Use the read/write/set/unset methods on Context
961 + rtx_e1000_reg_set32(hw_ctx, E1000_CTRL, E1000_CMD_ASDE|E1000_CMD_SLU);
962 + rtx_e1000_reg_unset32(
963 + hw_ctx,
964 + E1000_CTRL,
965 + E1000_CMD_LRST|E1000_CMD_FRCSPD|E1000_CMD_PHY_RST|
966 + E1000_CMD_ILOS|E1000_CMD_VME
967 + );
968 + rtx_e1000_reg_write32(hw_ctx, E1000_FCAH, 0);
969 + rtx_e1000_reg_write32(hw_ctx, E1000_FCAL, 0);
970 + rtx_e1000_reg_write32(hw_ctx, E1000_FCT, 0);
971 + rtx_e1000_reg_write32(hw_ctx, E1000_FCTTV, 0);
972 + for (int i = 0; i != 64; ++i)
973 + rtx_e1000_reg_write32(hw_ctx, E1000_CRCERRS + i * 4, 0);
974 +
975 + ${Log::info("adapter_setup_rx_tx: general configuration done")};
976 +
977 + int err;
978 +
979 + err = rtx_e1000_rx_ring_alloc_resources(&hw_ctx->rx_ring);
980 + if (err)
981 + goto err_alloc_rx_ring;
982 + rtx_e1000_rx_ring_configure(&hw_ctx->rx_ring);
983 +
984 + err = rtx_e1000_tx_ring_alloc_resources(&hw_ctx->tx_ring);
985 + if (err)
986 + goto err_alloc_tx_ring;
987 + rtx_e1000_tx_ring_configure(&hw_ctx->tx_ring);
988 +
989 + err_alloc_tx_ring:
990 + rtx_e1000_rx_ring_free_resources(&hw_ctx->rx_ring);
991 + err_alloc_rx_ring:
992 + // XXX Can't return here since we don't know the context.
993 + // TODO: hardcode a goto
994 + (void)1;
995 + }
996 + }
997 +
998 + chunk Ethernet::adapter_enable_interrupts(Ethernet::Device)
999 + {
1000 + {
1001 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx;
1002 + rtx_e1000_reg_write32(
1003 + hw_ctx,
1004 + E1000_IMS,
1005 + E1000_INTR_TXDW|E1000_INTR_TXQE|E1000_INTR_LSC|
1006 + E1000_INTR_RXO|E1000_INTR_RXT0
1007 + );
1008 +
1009 + // XXX We should probably move that elsewhere (it just used to
1010 + // be done right after we enabled interrupts when this was
1011 + // still in lkm.rtx):
1012 + // XXX #46: ${local.hw_ctx.print_status()};
1013 + rtx_e1000_print_status(hw_ctx);
1014 + }
1015 + }
1016 +
1017 + chunk Ethernet::disable_interrupts(Ethernet::Device rtx_ether_ctx)
1018 + {
1019 + { ${Log::info("adapter_disable_interrupts: TBD...")}; }
1020 + }
1021 +
1022 + chunk Ethernet::adapter_handle_interrupt(Ethernet::Device rtx_ether_ctx)
1023 + {
1024 + {
1025 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx;
1026 + unsigned int icr = rtx_e1000_reg_read32(hw_ctx, E1000_ICR);
1027 + pr_info("%s: interrupt received, ICR: 0x%x", ${config.name}, icr);
1028 + if (icr) {
1029 + if (icr & E1000_INTR_LSC) {
1030 + ${Log::info("handle_interrupt: cable link status changed, dumping card status:")};
1031 + // XXX #46: ${local.hw_ctx.print_status()};
1032 + rtx_e1000_print_status(hw_ctx);
1033 + }
1034 + if (icr & (E1000_INTR_TXQE|E1000_INTR_TXDW)) {
1035 + ${Log::info("handle_interrupt: TxRing: packet(s) sent")};
1036 + }
1037 + if (icr & E1000_INTR_RXT0) {
1038 + ${Log::info("handle_interrupt: RxRing: packet(s) received")};
1039 + }
1040 + if (icr & E1000_INTR_RXO) {
1041 + ${Log::info("handle_interrupt: RxRing: overrun")};
1042 + }
1043 +
1044 + // XXX: This sucks since we don't know the pointcut context:
1045 + return IRQ_HANDLED;
1046 + }
1047 + }
1048 + }
1049 +
1050 + chunk Ethernet::adapter_xmit(Ethernet::Device rtx_ether_ctx, Socket::SKBuff rtx_skb)
1051 + {
1052 + { ${Log::info("adapter_xmit: TBD...")}; }
1053 + }
1054 +
1055 + chunk Ethernet::adapter_disable_rx(Ethernet::Device rtx_ether_ctx)
1056 + {
1057 + { ${Log::info("adapter_disable_rx: TBD..")}; }
1058 + }
1059 +
1060 + chunk Ethernet::adpater_disable_tx(Ethernet::Device rtx_ether_ctx)
1061 + {
1062 + { ${Log::info("adapter_disable_tx: TBD..")}; }
1063 + }
1064 +
1065 + chunk Ethernet::adapter_free_rx_tx(Ethernet::Device rtx_ether_ctx)
1066 + {
1067 + { ${Log::info("adapter_free_rx_tx: TBD..")}; }
1068 + }
1069 +
1070 + method print_status()
1071 + {
1072 + rtx_e1000_print_status(${self});
1073 + }
1074 +
1075 + map
1076 + {
1077 + io_addr: ${self}->io;
1078 + rx_ring: ${self}->rx_ring;
1079 + tx_ring: ${self}->tx_ring;
1080 }
1081 }
1082
1040 - /* 1083 - /*
1041 - * We should have been able to do something along those lines, but 1084 - * We should have been able to do something along those lines, but
1042 - * it didn't work so we made the call manually. 1085 - * it didn't work so we made the call manually.
1043 - * 1086 - *
1044 - * Ideally: 1087 - * Ideally:
1054 - * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, reg_status)}; 1097 - * ${e1000::register_read32(rtx_ether_ctx->hw_ctx, reg_status)};
1055 - * 1098 - *
1056 - * TODO: make them methods of e1000::Context 1099 - * TODO: make them methods of e1000::Context
1057 - */ 1100 - */
1058 - template sequence e1000::register_read32(e1000::Context ctx, e1000::Register reg_offset) 1101 - template sequence e1000::register_read32(e1000::Context ctx, e1000::Register reg_offset)
1059 - { 1102 + template type e1000::Ring()
1103 {
1060 - chunk LKM::prototypes() 1104 - chunk LKM::prototypes()
1061 - { 1105 + decl data_types()
1106 {
1062 - /* FIXME: See issue #54 */ 1107 - /* FIXME: See issue #54 */
1063 - static unsigned int rtx_e1000_register_read32(/*const*/ ${e1000::Context.ref}, unsigned int); 1108 - static unsigned int rtx_e1000_register_read32(/*const*/ ${e1000::Context.ref}, unsigned int);
1064 + ${e1000::Context} hw_ctx; 1109 + ${e1000::Context} hw_ctx;
1110 + ${DMA::DMAHandle} dma;
1111 + unsigned int size;
1112 + ${Builtin::symbol.ref} descs;
1113 + ${e1000::Buffer.ref} buffs;
1065 } 1114 }
1066 1115
1067 - chunk LKM::code() 1116 - chunk LKM::code()
1068 + chunk Ethernet::adapter_init_context(Ethernet::Device rtx_ether_ctx, Builtin::symbol ioaddr) 1117 + chunk LKM::prototypes()
1069 { 1118 {
1070 - /* FIXME: See issue #54 */ 1119 - /* FIXME: See issue #54 */
1071 - static unsigned int rtx_e1000_register_read32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset) 1120 - static unsigned int rtx_e1000_register_read32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset)
1121 + static void rtx_e1000_ring_init(${e1000::Ring.ref}, ${e1000::Context}, int, int);
1122 + }
1123 +
1124 + chunk LKM::code()
1125 + {
1126 + static void rtx_e1000_ring_init(${e1000::Ring.ref} self, ${e1000::Context} hw_ctx,
1127 + int desc_count, int desc_size)
1072 { 1128 {
1073 - return ioread32(ctx->ioaddr + reg_offset); 1129 - return ioread32(ctx->ioaddr + reg_offset);
1074 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; 1130 + BUG_ON(desc_count <= 0 || desc_size <= 0);
1075 + ${local.hw_ctx.io.init(local.ioaddr)}; 1131 + memset(self, 0, sizeof(*self));
1076 + ${local.hw_ctx.rx_ring.init(local.hw_ctx.io, config.rx_ring_size)}; 1132 + self->size = ALIGN(desc_count * desc_size, 4096);
1077 + ${local.hw_ctx.tx_ring.init(local.hw_ctx.io, config.tx_ring_size)}; 1133 + self->hw_ctx = hw_ctx;
1078 } 1134 }
1079 } 1135 }
1080 1136
1081 - chunk ::CALL() 1137 - chunk ::CALL()
1082 + chunk Ethernet::adapter_reset(Ethernet::Device rtx_ether_ctx) 1138 + method init(e1000::Context hw_ctx, Builtin::number desc_count, Builtin::number desc_size)
1083 { 1139 {
1084 - rtx_e1000_register_read32(${ctx}, ${reg_offset}); 1140 - rtx_e1000_register_read32(${ctx}, ${reg_offset});
1085 - } 1141 + rtx_e1000_ring_init(&${self}, ${hw_ctx}, ${desc_count}, ${desc_size});
1086 - } 1142 + }
1087 - 1143 +
1144 + map
1145 + {
1146 + hw_ctx: ${self}->hw_ctx;
1147 + dma: ${self}->dma;
1148 + size: ${self}->size;
1149 + descs: ${self}->descs;
1150 + buffs: ${self}->buffs;
1151 }
1152 }
1153
1088 - template sequence e1000::register_write32(e1000::Context ctx, e1000::Register reg_offset, ::number value) 1154 - template sequence e1000::register_write32(e1000::Context ctx, e1000::Register reg_offset, ::number value)
1089 - { 1155 + template type e1000::RxRing()
1156 {
1090 - chunk LKM::prototypes() 1157 - chunk LKM::prototypes()
1091 - { 1158 + decl data_types()
1159 {
1092 - /* FIXME: See issue #54 */ 1160 - /* FIXME: See issue #54 */
1093 - static void rtx_e1000_register_write32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int); 1161 - static void rtx_e1000_register_write32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int);
1094 - } 1162 + ${e1000::Ring} ring;
1095 - 1163 }
1164
1096 - chunk LKM::code() 1165 - chunk LKM::code()
1097 - { 1166 + chunk LKM::prototypes()
1167 {
1098 - /* FIXME: See issue #54 */ 1168 - /* FIXME: See issue #54 */
1099 - static void rtx_e1000_register_write32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value) 1169 - static void rtx_e1000_register_write32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value)
1170 + static int rtx_e1000_rx_ring_alloc_resources(${e1000::RxRing.ref});
1171 + static void rtx_e1000_rx_ring_configure(${e1000::RxRing.ref});
1172 + }
1173 +
1174 + chunk LKM::code()
1175 + {
1176 + static int rtx_e1000_rx_ring_alloc_resources(${e1000::RxRing.ref} self)
1100 { 1177 {
1101 - iowrite32(value, ctx->ioaddr + reg_offset); 1178 - iowrite32(value, ctx->ioaddr + reg_offset);
1102 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; 1179 + // XXX Reread & Fix everything down there (data structure changes and so on)
1103 + // XXX #46: ${local.hw_ctx.io.write32(E1000_CTRL, E1000_CMD_RST)}; 1180 +
1104 + rtx_e1000_reg_write32(hw_ctx, E1000_CTRL, E1000_CMD_RST); 1181 + // 4. Setup the receive descriptor ring
1105 + udelay(10); // TODO: abstract this too... 1182 +
1106 + ${Log::info("adapter has been reset")}; 1183 + int i;
1184 +
1185 + // Allocate the descriptors
1186 + hw_ctx->rx_ring.base = ${DMA::alloc_coherent(
1187 + local.self.hw_ctx.net_dev.device, local.self.size,
1188 + local.self.dma.dma_handle
1189 + )};
1190 + if (!hw_ctx->rx_ring.base) {
1191 + ${Log::info("adapter_init_rx: cannot allocate the descriptors for the rx ring")};
1192 + goto err_rx_ring_alloc;
1193 + }
1194 +
1195 + ${Log::info("adapter_init_rx: rx descriptors allocated")};
1196 +
1197 + // Allocate the skbuffs, map them for DMA, and write their address
1198 + // in the corresponding descriptor.
1199 +// for (i = 0; i != ${config.rx_ring_size}; ++i) {
1200 +// ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i];
1201 +// // XXX #46: ${rtx_ether_ctx.alloc_rx_skbuff(local.skbuff, config.rx_buffer_len)};
1202 +// if (rtx_ethernet_alloc_rx_skbuff(ocal.skbuff, ${config.rx_buffer_len})) {
1203 +// ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")};
1204 +// goto err_skbuffs_alloc;
1205 +// }
1206 +// /* TODO: recuperer le dma handle et le placer correctement dans le descripteur. */
1207 +// ${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)}
1208 +// if (${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)}) {
1209 +// ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")};
1210 +// goto err_skbuffs_map;
1211 +// }
1212 +// hw_ctx->rx_ring.base[i].buff_addr = cpu_to_le64(${local.skbuff.sk_buff});
1213 +// }
1214 +
1215 + // ${Log::info("adapter_init_rx: skbuffs allocated};
1216 + pr_info("rtx_e1k: adapter_init_rx: skbuffs allocated, headlen=%d", skb_headlen((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i - 1].skbuff));
1217 +
1218 + err_skbuffs_alloc:
1219 + while (i--) {
1220 + ${DMA::unmap(
1221 + local.self.hw_ctx.net_dev.device,
1222 + // XXX Leaking cast because of the array: (TODO: the data structure changed)
1223 + *((dma_addr_t *)&(self->buffs[i].dma_handle)),
1224 + ${config.rx_buffer_len},
1225 + RTX_DMA_FROM_DEVICE
1226 + )};
1227 + err_skbuffs_map:
1228 + // XXX leaking cast: (TODO: the data structure changed)
1229 + dev_kfree_skb((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff);
1230 + }
1231 +
1232 + ${DMA::free_coherent(
1233 + local.self.hw_ctx.net_dev.device, local.self.size,
1234 + local.self.descs, local.self.dma.dma_handle
1235 + )};
1236 + err_rx_ring_alloc:
1237 + return -ENOMEM;
1238 + }
1239 +
1240 + static void rtx_e1000_rx_ring_configure(${e1000::RxRing.ref} self)
1241 + {
1242 + // XXX Reread & Fix everything down there (data structure changes and so on)
1243 +
1244 + // Receive initialization (section 14.4):
1245 + //
1246 + // 1. Program the receive address, in RAL/RAH;
1247 + // 2. Initialize the Multicast Table Array;
1248 + // 3. Program the interrupt mask register (done in
1249 + // e1000::activate_device_interruption);
1250 + // 4. Allocate the receive descriptor ring and map it to make it
1251 + // accessible by the device;
1252 + // 5. Write the start address of the ring in RDBAL/RDBAH and set
1253 + // RDLEN (Receive Descriptor Length) to the size of the ring;
1254 + // 6. Set the RDH/RDT (Receive Descriptor Head/Tail) indexes to the
1255 + // beginning and end of the ring;
1256 + // 7. Make sure that RCTL.BSIZE and .BSEX are at 0 to configure the
1257 + // receive buffer size to 2048 bytes (e1000::rx_buffer_len).
1258 + // 8. Set RCTL.EN to enable the receiver.
1259 + //
1260 + // The ugly casts here are caused by the lack of CNorm unstrict.
1261 +
1262 + int i;
1263 +
1264 + // 1. Program the receive address
1265 +
1266 + // (We should use uint{32,16}_t but CNorm doesn't know them yet)
1267 + rtx_e1000_reg_write32(
1268 + ${local.self.hw_ctx}, E1000_RAL,
1269 + *(unsigned int *)(${local.self.hw_ctx.net_dev.dev_addr})
1270 + );
1271 + // The 16 upper bits of RAH also store the AS bits (which should be
1272 + // 0) and the AV bit (should be 1 to set the address as valid).
1273 + rtx_e1000_reg_write32(
1274 + ${local.self.hw_ctx}, E1000_RAH,
1275 + *(unsigned short *)(&${local.self.hw_ctx.net_dev.dev_addr}[4])
1276 + );
1277 + rtx_e1000_reg_set32(${local.self.hw_ctx}, E1000_RAH, E1000_RAH_AV);
1278 +
1279 + ${Log::info("rx_ring_configure: receive address programmed")};
1280 +
1281 + // 2. Initialize the MTA
1282 +
1283 + for (i = 0; i != 128; ++i) // TODO Remove that hardcoded 128
1284 + rtx_e1000_reg_write32(${local.self.hw_ctx}, E1000_MTA + i * 4, 0);
1285 +
1286 + ${Log::info("rx_ring_configure: MTA init done")};
1287 +
1288 + // 5. Save the emplacement and the size of the ring in RDBA/RDLEN
1289 + rtx_e1000_reg_write32(
1290 + ${local.self.hw_ctx}, E1000_RDBAL,
1291 + ${local.self.hw_ctx}->rx_ring.dma_base & 0xffffffff
1292 + );
1293 + rtx_e1000_reg_write32(
1294 + ${local.self.hw_ctx}, E1000_RDBAH,
1295 + ${local.self.hw_ctx}->rx_ring.dma_base >> 32
1296 + );
1297 + rtx_e1000_reg_write32(
1298 + ${local.self.hw_ctx}, E1000_RDLEN,
1299 + ${local.self.hw_ctx}->rx_ring.size
1300 + );
1301 +
1302 + // 6. Setup RDH/RDT
1303 + rtx_e1000_reg_write32(${local.self.hw_ctx}, E1000_RDH, 0);
1304 + rtx_e1000_reg_write32(
1305 + ${local.self.hw_ctx}, E1000_RDT,
1306 + ${config.rx_ring_size} - 1
1307 + );
1308 +
1309 + // 7. Configure the buffer size
1310 + rtx_e1000_reg_set32(
1311 + ${local.self.hw_ctx}, E1000_RCTL,
1312 + E1000_RCTL_BSIZE_${config.rx_buffer_len}
1313 + );
1314 +
1315 + // 8. Enable the receiver
1316 + rtx_e1000_reg_set32(${local.self.hw_ctx}, E1000_RCTL, E1000_RCTL_EN);
1317 +
1318 + ${Log::info("rx_ring_configure: receive registers configured and receiver enabled")};
1319 +
1320 + return 0;
1107 } 1321 }
1108 } 1322 }
1109 1323
1110 - chunk ::CALL() 1324 - chunk ::CALL()
1111 + chunk Ethernet::adapter_load_mac_address(Ethernet::Device rtx_ether_ctx) 1325 + method init(e1000::Context hw_ctx, Builtin::number desc_count)
1112 { 1326 {
1113 - rtx_e1000_register_write32(${ctx}, ${reg_offset}, ${value}); 1327 - rtx_e1000_register_write32(${ctx}, ${reg_offset}, ${value});
1114 - } 1328 + ${self.ring.init(hw_ctx, desc_count, self.desc_size)};
1115 - } 1329 + }
1116 + { 1330 +
1117 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx; 1331 + method alloc()
1118 + // Shamelessly borrowed from Minix 1332 + {
1119 + for (int i = 0; i < 3; ++i) { 1333 + rtx_e1000_rx_ring_alloc_resources(${self});
1120 + rtx_e1000_reg_write32(hw_ctx, E1000_EEPROM_READ, (i << 8) | 1); 1334 + }
1121 + int value; 1335 +
1122 + do { 1336 + method configure()
1123 + value = rtx_e1000_reg_read32(hw_ctx, E1000_EEPROM_READ); 1337 + {
1124 + } while ((value & (1 << 4)) == 0); 1338 + rtx_e1000_rx_ring_configure(${self});
1125 + value >>= 16; 1339 + }
1126 + // NOTE: I'm not sure if Ethernet::Device should be 1340 +
1127 + // accessed directly here. But since we need to take it in 1341 + map
1128 + // parameter (so we can get back our e1000::Context) it 1342 + {
1129 + // seems inadequate to set this in another way: 1343 + // TODO: fix cast to directly get the attributes from the Ring:
1130 + ${local.rtx_ether_ctx.dev_addr}[i * 2] = value & 0xff; 1344 + hw_ctx: ((int)(${self})->hw_ctx);
1131 + ${local.rtx_ether_ctx.dev_addr}[i * 2 + 1] = (value >> 8) & 0xff; 1345 + dma: ((int)(${self})->dma);
1132 + } 1346 + size: ((int)(${self})->size);
1347 + descs: ((int)(${self})->descs);
1348 + buffs: ((int)(${self})->buffs);
1349 + desc_size: sizeof(/* TODO: get the generated type... ${e1000::RxDescriptor} */int);
1350 }
1351 }
1133 1352
1134 - template sequence e1000::register_set32(e1000::Context ctx, e1000::Register reg_offset, ::number value) 1353 - template sequence e1000::register_set32(e1000::Context ctx, e1000::Register reg_offset, ::number value)
1135 - { 1354 + template type e1000::TxRing()
1355 {
1136 - chunk LKM::prototypes() 1356 - chunk LKM::prototypes()
1137 - { 1357 + decl data_types()
1358 {
1138 - /* FIXME: See issue #54 */ 1359 - /* FIXME: See issue #54 */
1139 - static void rtx_e1000_register_set32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int); 1360 - static void rtx_e1000_register_set32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int);
1140 - } 1361 + ${e1000::Ring} ring;
1141 - 1362 }
1363
1142 - chunk LKM::code() 1364 - chunk LKM::code()
1143 - { 1365 + chunk LKM::prototypes()
1366 {
1144 - /* FIXME: See issue #54 */ 1367 - /* FIXME: See issue #54 */
1145 - static void rtx_e1000_register_set32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value) 1368 - static void rtx_e1000_register_set32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value)
1146 - { 1369 + static int rtx_e1000_tx_ring_alloc_resources(${e1000::TxRing.ref});
1370 + static void rtx_e1000_tx_ring_configure(${e1000::TxRing.ref});
1371 + }
1372 +
1373 + chunk LKM::code()
1374 + {
1375 + static int rtx_e1000_tx_ring_alloc_resources(${e1000::TxRing.ref} self)
1376 {
1147 - iowrite32(rtx_e1000_register_read32(ctx, reg_offset) | value, ctx->ioaddr + reg_offset); 1377 - iowrite32(rtx_e1000_register_read32(ctx, reg_offset) | value, ctx->ioaddr + reg_offset);
1148 + ${Log::info("mac address loaded from the EEPROM")}; 1378 + return 0;
1379 + }
1380 +
1381 + static void rtx_e1000_tx_ring_configure(${e1000::TxRing.ref} self)
1382 + {
1383 + // return ; XXX wtf fails with:
1384 + // function 'rtxPH_compile(local_node : node, compile : node, node_idx : value)' hasn't been implemented
1149 } 1385 }
1150 } 1386 }
1151 1387
1152 - chunk ::CALL() 1388 - chunk ::CALL()
1153 + // For e1000, this part is documented in the Intel Gigabit Ethernet 1389 + method init(e1000::Context hw_ctx, Builtin::number desc_count)
1154 + // Controller Software Developper manual. (You can find it in the
1155 + // doc/hardware directory).
1156 + chunk Ethernet::adapter_setup_rx_tx(Ethernet::Device rtx_ether_ctx)
1157 { 1390 {
1158 - rtx_e1000_register_set32(${ctx}, ${reg_offset}, ${value}); 1391 - rtx_e1000_register_set32(${ctx}, ${reg_offset}, ${value});
1159 - } 1392 - }
1160 - } 1393 - }
1161 + { 1394 -
1162 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx;
1163
1164 - template sequence e1000::register_unset32(e1000::Context ctx, e1000::Register reg_offset, ::number value) 1395 - template sequence e1000::register_unset32(e1000::Context ctx, e1000::Register reg_offset, ::number value)
1165 - { 1396 - {
1166 - chunk LKM::prototypes() 1397 - chunk LKM::prototypes()
1167 - { 1398 - {
1168 - /* FIXME: See issue #54 */ 1399 - /* FIXME: See issue #54 */
1169 - static void rtx_e1000_register_unset32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int); 1400 - static void rtx_e1000_register_unset32(/*const*/ ${e1000::Context.ref}, unsigned int, unsigned int);
1170 - } 1401 + ${self.ring.init(hw_ctx, desc_count, self.desc_size)};
1171 + // "General Configuration" (section 14.3): 1402 }
1172 + //
1173 + // - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection &
1174 + // negociation;
1175 + // - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation;
1176 + // - CTRL.PHY_RST: Unset it;
1177 + // - CTRL.ILOS: Unset it (ILOS is Invert Loss Of Signal);
1178 + // - CTRL.VME: Make sure it's not set to disable VLAN support;
1179 + // - Set the control flow registers to 0;
1180 + // - Finally, initialize all the statistic registers from
1181 + // E1000_CRCERRS to E1000_TSCTFC.
1182 + //
1183 + // XXX #46: Use the read/write/set/unset methods on Context
1184 + rtx_e1000_reg_set32(hw_ctx, E1000_CTRL, E1000_CMD_ASDE|E1000_CMD_SLU);
1185 + rtx_e1000_reg_unset32(
1186 + hw_ctx,
1187 + E1000_CTRL,
1188 + E1000_CMD_LRST|E1000_CMD_FRCSPD|E1000_CMD_PHY_RST|
1189 + E1000_CMD_ILOS|E1000_CMD_VME
1190 + );
1191 + rtx_e1000_reg_write32(hw_ctx, E1000_FCAH, 0);
1192 + rtx_e1000_reg_write32(hw_ctx, E1000_FCAL, 0);
1193 + rtx_e1000_reg_write32(hw_ctx, E1000_FCT, 0);
1194 + rtx_e1000_reg_write32(hw_ctx, E1000_FCTTV, 0);
1195 + for (int i = 0; i != 64; ++i)
1196 + rtx_e1000_reg_write32(hw_ctx, E1000_CRCERRS + i * 4, 0);
1197 1403
1198 - chunk LKM::code() 1404 - chunk LKM::code()
1199 - { 1405 + method alloc()
1406 {
1200 - /* FIXME: See issue #54 */ 1407 - /* FIXME: See issue #54 */
1201 - static void rtx_e1000_register_unset32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value) 1408 - static void rtx_e1000_register_unset32(/*const*/ ${e1000::Context.ref} ctx, unsigned int reg_offset, unsigned int value)
1202 - { 1409 - {
1203 - iowrite32(rtx_e1000_register_read32(ctx, reg_offset) & ~value, ctx->ioaddr + reg_offset); 1410 - iowrite32(rtx_e1000_register_read32(ctx, reg_offset) & ~value, ctx->ioaddr + reg_offset);
1204 + ${Log::info("adapter_setup: general configuration done")}; 1411 - }
1205 } 1412 + rtx_e1000_tx_ring_alloc_resources(${self});
1206 } 1413 }
1207 1414
1208 - chunk ::CALL() 1415 - chunk ::CALL()
1209 + chunk Ethernet::adapter_enable_interrupts(Ethernet::Device) 1416 + method configure()
1210 { 1417 {
1211 - rtx_e1000_register_unset32(${ctx}, ${reg_offset}, ${value}); 1418 - rtx_e1000_register_unset32(${ctx}, ${reg_offset}, ${value});
1212 - } 1419 + rtx_e1000_tx_ring_configure(${self});
1213 - } 1420 }
1214 + { 1421 - }
1215 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx;
1216 + rtx_e1000_reg_write32(
1217 + hw_ctx,
1218 + E1000_IMS,
1219 + E1000_INTR_TXDW|E1000_INTR_TXQE|E1000_INTR_LSC|
1220 + E1000_INTR_RXO|E1000_INTR_RXT0
1221 + );
1222 1422
1223 - template sequence activate_device_interruption(Ethernet::Device rtx_ether_ctx) 1423 - template sequence activate_device_interruption(Ethernet::Device rtx_ether_ctx)
1224 - { 1424 - {
1225 - chunk ::CALL() 1425 - chunk ::CALL()
1226 - { 1426 + map
1427 {
1227 - rtx_e1000_register_write32(&${rtx_ether_ctx}->hw_ctx, E1000_IMS, 1428 - rtx_e1000_register_write32(&${rtx_ether_ctx}->hw_ctx, E1000_IMS,
1228 - E1000_INTR_TXDW | 1429 - E1000_INTR_TXDW |
1229 - E1000_INTR_TXQE | 1430 - E1000_INTR_TXQE |
1230 - E1000_INTR_LSC | 1431 - E1000_INTR_LSC |
1231 - E1000_INTR_RXO | 1432 - E1000_INTR_RXO |
1314 - { 1515 - {
1315 - ${Log::info("handle_interrupt: RxRing: overrun")}; 1516 - ${Log::info("handle_interrupt: RxRing: overrun")};
1316 - } 1517 - }
1317 - 1518 -
1318 - return IRQ_HANDLED; 1519 - return IRQ_HANDLED;
1319 + // XXX We should probably move that elsewhere (it just used to 1520 - }
1320 + // be done right after we enabled interrupts when this was 1521 - }
1321 + // still in lkm.rtx): 1522 - }
1322 + // XXX #46: ${local.hw_ctx.print_status()}; 1523 -
1323 + rtx_e1000_print_status(hw_ctx);
1324 }
1325 }
1326 - }
1327
1328 - template sequence e1000::xmit(Ethernet::Device rtx_ether_ctx, Socket::AbstractSKBuff kernel_skb) 1524 - template sequence e1000::xmit(Ethernet::Device rtx_ether_ctx, Socket::AbstractSKBuff kernel_skb)
1329 - { 1525 - {
1330 - chunk ::CALL() 1526 - chunk ::CALL()
1331 + chunk Ethernet::disable_interrupts(Ethernet::Device rtx_ether_ctx) 1527 - {
1332 {
1333 - /* 1528 - /*
1334 - * Put packets on the TX ring, must return NETDEV_TX_OK or 1529 - * Put packets on the TX ring, must return NETDEV_TX_OK or
1335 - * NETDEV_TX_BUSY. 1530 - * NETDEV_TX_BUSY.
1336 - */ 1531 - */
1337 + { ${Log::info("adapter_disable_interrupts: TBD...")}; } 1532 -
1338 + }
1339
1340 - ${Socket::SKBuff} skb; 1533 - ${Socket::SKBuff} skb;
1341 - ${e1000::Context.ref} hw_ctx; 1534 - ${e1000::Context.ref} hw_ctx;
1342 - ${e1000::TxRing.ref} tx_ring; 1535 - ${e1000::TxRing.ref} tx_ring;
1343 - ${Device::AbstractDevice.ref} devp; 1536 - ${Device::AbstractDevice.ref} devp;
1344 + chunk Ethernet::adapter_handle_interrupt(Ethernet::Device rtx_ether_ctx) 1537 -
1345 + {
1346 + {
1347 + ${e1000::Context.ref} hw_ctx = &${local.rtx_ether_ctx}->hw_ctx;
1348 + unsigned int icr = rtx_e1000_reg_read32(hw_ctx, E1000_ICR);
1349 + pr_info("%s: interrupt received, ICR: 0x%x", ${config.name}, icr);
1350 + if (icr) {
1351 + if (icr & E1000_INTR_LSC) {
1352 + ${Log::info("handle_interrupt: cable link status changed, dumping card status:")};
1353 + // XXX #46: ${local.hw_ctx.print_status()};
1354 + rtx_e1000_print_status(hw_ctx);
1355 + }
1356 + if (icr & (E1000_INTR_TXQE|E1000_INTR_TXDW)) {
1357 + ${Log::info("handle_interrupt: TxRing: packet(s) sent")};
1358 + }
1359 + if (icr & E1000_INTR_RXT0) {
1360 + ${Log::info("handle_interrupt: RxRing: packet(s) received")};
1361 + }
1362 + if (icr & E1000_INTR_RXO) {
1363 + ${Log::info("handle_interrupt: RxRing: overrun")};
1364 + }
1365
1366 - ${local.skb.init(kernel_skb)}; 1538 - ${local.skb.init(kernel_skb)};
1367 - hw_ctx = &${rtx_ether_ctx}->hw_ctx; 1539 - hw_ctx = &${rtx_ether_ctx}->hw_ctx;
1368 - tx_ring = &hw_ctx->tx_ring; 1540 - tx_ring = &hw_ctx->tx_ring;
1369 - devp = (${Device::AbstractDevice.ref})${rtx_ether_ctx.device}; 1541 - devp = (${Device::AbstractDevice.ref})${rtx_ether_ctx.device};
1370 + // XXX: This sucks since we don't know the pointcut context: 1542 -
1371 + return IRQ_HANDLED;
1372 + }
1373 + }
1374 + }
1375
1376 - ${Log::info("xmit: skbuff details:")}; 1543 - ${Log::info("xmit: skbuff details:")};
1377 - /* 1544 - /*
1378 - * skb does not expand on the bound C variable (should be 1545 - * skb does not expand on the bound C variable (should be
1379 - * rtx_skbuff), which is funny because it works for the 1546 - * rtx_skbuff), which is funny because it works for the
1380 - * sequence template call right after. 1547 - * sequence template call right after.
1382 - /* 1549 - /*
1383 - * XXX: doesn't work (I tried to pass self explicitely too): 1550 - * XXX: doesn't work (I tried to pass self explicitely too):
1384 - * ${local.skb.dump_infos()}; 1551 - * ${local.skb.dump_infos()};
1385 - */ 1552 - */
1386 - rtx_socket_skbuff_dump_infos(&skb); 1553 - rtx_socket_skbuff_dump_infos(&skb);
1387 + chunk Ethernet::adapter_xmit(Ethernet::Device rtx_ether_ctx, Socket::SKBuff rtx_skb) 1554 -
1388 + {
1389 + { ${Log::info("adapter_xmit: TBD...")}; }
1390 + }
1391
1392 - /* 1555 - /*
1393 - * The transmission is going to be several steps: 1556 - * The transmission is going to be several steps:
1394 - * 1. TCP Segmentation Offload & Checksum Offloading: pick a 1557 - * 1. TCP Segmentation Offload & Checksum Offloading: pick a
1395 - * descriptor from the tx ring and fill it as a context 1558 - * descriptor from the tx ring and fill it as a context
1396 - * descriptor to allow the card to slice into several packets 1559 - * descriptor to allow the card to slice into several packets
1397 - * according to the MSS; 1560 - * according to the MSS;
1398 - * 2. DMA Map the skbuff data as slices of 4096; 1561 - * 2. DMA Map the skbuff data as slices of 4096;
1399 - * 3. Signal the hardware that data is available via a tx desc. 1562 - * 3. Signal the hardware that data is available via a tx desc.
1400 - */ 1563 - */
1401 + chunk Ethernet::adapter_disable_rx(Ethernet::Device rtx_ether_ctx) 1564 -
1402 + {
1403 + { ${Log::info("adapter_disable_rx: TBD..")}; }
1404 + }
1405
1406 - /* XXX: same thing wanted to use: ${local.tx_ring.descriptors_remaining()} */ 1565 - /* XXX: same thing wanted to use: ${local.tx_ring.descriptors_remaining()} */
1407 - if (!rtx_e1000_tx_ring_descriptors_remaining(tx_ring)) 1566 - if (!rtx_e1000_tx_ring_descriptors_remaining(tx_ring))
1408 - return NETDEV_TX_BUSY; 1567 - return NETDEV_TX_BUSY;
1409 + chunk Ethernet::adpater_disable_tx(Ethernet::Device rtx_ether_ctx) 1568 -
1410 + {
1411 + { ${Log::info("adapter_disable_tx: TBD..")}; }
1412 + }
1413
1414 - /* 1. Offloading */ 1569 - /* 1. Offloading */
1415 + chunk Ethernet::adapter_free_rx_tx(Ethernet::Device rtx_ether_ctx) 1570 -
1416 + {
1417 + { ${Log::info("adapter_free_rx_tx: TBD..")}; }
1418 + }
1419
1420 - /* XXX: ${local.tx_ring.tso_cksum_offload(skb)}; */ 1571 - /* XXX: ${local.tx_ring.tso_cksum_offload(skb)}; */
1421 - if (rtx_e1000_tx_ring_tso_cksum_offload(tx_ring, &skb)) 1572 - if (rtx_e1000_tx_ring_tso_cksum_offload(tx_ring, &skb))
1422 - { 1573 - {
1423 - ${Log::info("xmit: the packet needs to be fragmented and/or checksummed but this not implemented yet!")}; 1574 - ${Log::info("xmit: the packet needs to be fragmented and/or checksummed but this not implemented yet!")};
1424 - goto err_offload; 1575 - goto err_offload;
1425 - } 1576 - }
1426 1577 -
1427 - /* 2. Map the data */ 1578 - /* 2. Map the data */
1428 + method print_status() 1579 -
1429 + {
1430 + rtx_e1000_print_status(${self});
1431 + }
1432
1433 - /* XXX: ${local.skb.map_to(devp.k_device)}; */ 1580 - /* XXX: ${local.skb.map_to(devp.k_device)}; */
1434 - if (rtx_socket_skbuff_map(&skb, ${devp.k_device}, DMA_TO_DEVICE)) 1581 - if (rtx_socket_skbuff_map(&skb, ${devp.k_device}, DMA_TO_DEVICE))
1435 - { 1582 - {
1436 - ${Log::info("xmit: can't DMA map a SKbuff")}; 1583 - ${Log::info("xmit: can't DMA map a SKbuff")};
1437 - goto err_skb_map_to; 1584 - goto err_skb_map_to;
1450 - err_offload: 1597 - err_offload:
1451 - err_skb_map_to: 1598 - err_skb_map_to:
1452 - /* XXX: ${local.skb.unmap_to_and_free(local.dev)}; */ 1599 - /* XXX: ${local.skb.unmap_to_and_free(local.dev)}; */
1453 - rtx_socket_skbuff_unmap_and_free(&skb, ${devp.k_device}, DMA_TO_DEVICE); 1600 - rtx_socket_skbuff_unmap_and_free(&skb, ${devp.k_device}, DMA_TO_DEVICE);
1454 - return NETDEV_TX_OK; 1601 - return NETDEV_TX_OK;
1455 + map 1602 + // TODO: fix cast to directly get the attributes from the Ring:
1456 + { 1603 + hw_ctx: ((int)(${self})->hw_ctx);
1457 + io: ${self}->io; 1604 + dma: ((int)(${self})->dma);
1458 + rx_ring: ${self}->rx_ring; 1605 + size: ((int)(${self})->size);
1459 + tx_ring: ${self}->tx_ring; 1606 + descs: ((int)(${self})->descs);
1607 + buffs: ((int)(${self})->buffs);
1608 + desc_size: sizeof(/* TODO: get the generated type ${e1000::TxDescriptor} */int);
1460 } 1609 }
1461 } 1610 }
1462 } 1611 }
1463 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti 1612 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti
1464 old mode 100755
1465 new mode 100644
1466 --- a/rathaxes/samples/e1000/e1000.rti 1613 --- a/rathaxes/samples/e1000/e1000.rti
1467 +++ b/rathaxes/samples/e1000/e1000.rti 1614 +++ b/rathaxes/samples/e1000/e1000.rti
1468 @@ -1,157 +1,115 @@ 1615 @@ -1,157 +1,122 @@
1469 interface e1000 : Socket, Ethernet, DMA, PCI, LKM, Builtin 1616 -interface e1000 : Socket, Ethernet, DMA, PCI, LKM, Builtin
1617 +interface e1000 : Socket, Ethernet, Device, DMA, PCI, LKM, Builtin
1470 { 1618 {
1471 - required variable Builtin::number rx_ring_size; 1619 - required variable Builtin::number rx_ring_size;
1472 - required variable Builtin::number tx_ring_size; 1620 - required variable Builtin::number tx_ring_size;
1473 - required variable Builtin::number rx_buffer_len; 1621 - required variable Builtin::number rx_buffer_len;
1474 - required variable Builtin::number tx_max_data_per_desc; 1622 - required variable Builtin::number tx_max_data_per_desc;
1496 + attribute Socket::SKBuff.ref sk_buff; 1644 + attribute Socket::SKBuff.ref sk_buff;
1497 + attribute DMA::DMAHandle.ref dma; 1645 + attribute DMA::DMAHandle.ref dma;
1498 } 1646 }
1499 1647
1500 - provided type TxDescriptor 1648 - provided type TxDescriptor
1501 + // I wish we could just leave those methods in the Context type but we also 1649 + provided type Context
1502 + // need them from the rings and that would mean a circular dependency
1503 + // between the context and the rings and Rathaxes can't handle it.
1504 + provided type MMIO
1505 { 1650 {
1506 decl data_types(); 1651 decl data_types();
1507 - method init(); 1652 - method init();
1508 + 1653 +
1654 + chunk LKM::includes();
1509 + chunk LKM::prototypes(); 1655 + chunk LKM::prototypes();
1510 + chunk LKM::code(); 1656 + chunk LKM::code();
1657 + chunk Ethernet::HardwareContext();
1658 +
1659 + // NOTE: Those callbacks/hooks should probably be in the front-end:
1660 +
1661 + chunk Ethernet::adapter_init_context(Ethernet::Device, Builtin::symbol);
1662 + chunk Ethernet::adapter_reset(Ethernet::Device);
1663 + chunk Ethernet::adapter_load_mac_address(Ethernet::Device);
1664 + chunk Ethernet::adapter_setup_rx_tx(Ethernet::Device);
1665 + chunk Ethernet::adapter_enable_interrupts(Ethernet::Device);
1666 + chunk Ethernet::adapter_disable_interrupts(Ethernet::Device);
1667 + chunk Ethernet::adapter_handle_interrupt(Ethernet::Device);
1668 + chunk Ethernet::adapter_xmit(Ethernet::Device, Socket::SKBuff);
1669 + chunk Ethernet::adapter_disable_rx(Ethernet::Device);
1670 + chunk Ethernet::adapter_disable_tx(Ethernet::Device);
1671 + chunk Ethernet::adapter_free_rx_tx(Ethernet::Device);
1511 + 1672 +
1512 + method init(Builtin::symbol); 1673 + method init(Builtin::symbol);
1513 + method read32(Register); 1674 + method print_status();
1514 + method write32(Register, Builtin::number); 1675 + method reg_read32(Register);
1515 + method set32(Register, Builtin::number); 1676 + method reg_write32(Register, Builtin::number);
1516 + method unset32(Register, Builtin::number); 1677 + method reg_set32(Register, Builtin::number);
1517 + 1678 + method reg_unset32(Register, Builtin::number);
1518 + attribute Builtin::symbol.scalar io; 1679 +
1680 + // XXX: Circular dependency with the rings, this will prevent us to
1681 + // call methods even when issue $46 is resolved, and it also forces
1682 + // us to hardcode generated types in the definition of the type:
1683 + attribute Builtin::symbol.scalar rx_ring;
1684 + attribute Builtin::symbol.scalar tx_ring;
1685 +
1686 + attribute Ethernet::Device.ref net_dev;
1519 + } 1687 + }
1520 + 1688 +
1521 + provided type Ring 1689 + provided type Ring
1522 + { 1690 + {
1523 + decl data_types(); 1691 + decl data_types();
1524 + 1692 +
1525 + chunk LKM::prototypes(); 1693 + chunk LKM::prototypes();
1526 + chunk LKM::code(); 1694 + chunk LKM::code();
1527 + 1695 +
1528 + method init(MMIO, Builtin::number, Builtin::number); 1696 + method init(e1000::Context, Builtin::number);
1529 + 1697 +
1530 + attribute MMIO.scalar io; 1698 + // Keep a backref to The context since it's going to be needed for of
1531 + attribute DMA::DMAHandle.scalar dma; 1699 + // operations involving the ethernet device, flags on the context, etc.
1700 + attribute Context.ref hw_ctx;
1701 +
1702 + attribute DMA::DMAHandle.scalar dma;
1532 + attribute Builtin::number.scalar size; // Total size in bytes 1703 + attribute Builtin::number.scalar size; // Total size in bytes
1533 + attribute Builtin::symbol.ref descs; 1704 + attribute Builtin::symbol.ref descs;
1534 + attribute Buffer.ref buffs; 1705 + attribute Buffer.ref buffs;
1535 } 1706 }
1536 1707
1543 - chunk Ethernet::adapter_init_rx(Ethernet::Device); 1714 - chunk Ethernet::adapter_init_rx(Ethernet::Device);
1544 + chunk LKM::prototypes(); 1715 + chunk LKM::prototypes();
1545 + chunk LKM::code(); 1716 + chunk LKM::code();
1546 1717
1547 - attribute DMA::DMAHandle.scalar dma_base; 1718 - attribute DMA::DMAHandle.scalar dma_base;
1548 - attribute Builtin::number.scalar size; 1719 + method init(e1000::Context, Builtin::number);
1549 + method init(MMIO, Builtin::number);
1550 + method alloc(); // Returns != 0 on failure 1720 + method alloc(); // Returns != 0 on failure
1551 + 1721 + method free();
1552 + attribute RxDescriptor.scalar descs; 1722 + method configure();
1553 + } 1723 +
1554 + 1724 + // Re-expose all the Ring attributes + the size of a single descriptor:
1555 + provided type TxRing 1725 + attribute Context.ref hw_ctx;
1556 + { 1726 + attribute DMA::DMAHandle.scalar dma;
1557 + decl data_types(); 1727 attribute Builtin::number.scalar size;
1558 + 1728 - }
1559 + chunk LKM::prototypes(); 1729 -
1560 + chunk LKM::code(); 1730 - provided type Context
1561 + 1731 - {
1562 + method init(MMIO, Builtin::number);
1563 + method alloc(); // Returns != 0 on failure
1564 +
1565 + attribute TxDescriptor.scalar descs;
1566 }
1567
1568 provided type Context
1569 {
1570 - chunk Ethernet::HardwareContext(); 1732 - chunk Ethernet::HardwareContext();
1571 decl data_types(); 1733 - decl data_types();
1572 1734 -
1573 - /* XXX: 1735 - /* XXX:
1574 - * These callbacks/Hooks which should probably be in the front-end. 1736 - * 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 1737 - * Also, I'm not too happy about the names, it's difficult to make
1576 - * the difference between the probe and open parts. 1738 - * the difference between the probe and open parts.
1577 - */ 1739 - */
1578 - chunk Ethernet::adapter_init_context(Ethernet::Device, 1740 - chunk Ethernet::adapter_init_context(Ethernet::Device,
1579 - Builtin::number, 1741 - Builtin::number,
1580 - Builtin::symbol); 1742 - Builtin::symbol);
1581 + chunk LKM::includes(); 1743 - chunk Ethernet::adapter_reset(Ethernet::Device);
1582 + chunk LKM::prototypes(); 1744 - chunk Ethernet::adapter_load_mac_address(Ethernet::Device);
1583 + chunk LKM::code();
1584 + chunk Ethernet::HardwareContext();
1585 +
1586 + // NOTE: Those callbacks/hooks should probably be in the front-end:
1587 +
1588 + chunk Ethernet::adapter_init_context(Ethernet::Device, Builtin::symbol);
1589 chunk Ethernet::adapter_reset(Ethernet::Device);
1590 chunk Ethernet::adapter_load_mac_address(Ethernet::Device);
1591 - chunk Ethernet::adapter_setup(Ethernet::Device); 1745 - chunk Ethernet::adapter_setup(Ethernet::Device);
1592 + chunk Ethernet::adapter_setup_rx_tx(Ethernet::Device); 1746 -
1593 + chunk Ethernet::adapter_enable_interrupts(Ethernet::Device); 1747 - attribute RxRing.scalar rx_ring;
1594 + chunk Ethernet::adapter_disable_interrupts(Ethernet::Device);
1595 + chunk Ethernet::adapter_handle_interrupt(Ethernet::Device);
1596 + chunk Ethernet::adapter_xmit(Ethernet::Device, Socket::SKBuff);
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
1601 + method print_status();
1602 +
1603 + attribute MMIO.scalar io;
1604 attribute RxRing.scalar rx_ring;
1605 - /* XXX: circular dependency with Contex: */ 1748 - /* XXX: circular dependency with Contex: */
1606 - //attribute TxRing.scalar tx_ring; 1749 - //attribute TxRing.scalar tx_ring;
1607 - } 1750 + attribute RxDescriptor.scalar descs;
1608 - 1751 + attribute Builtin::number.scalar desc_size;
1609 - provided type TxRing 1752 }
1610 - { 1753
1611 - chunk LKM::prototypes(); 1754 provided type TxRing
1612 - chunk LKM::code(); 1755 {
1756 + decl data_types();
1757 +
1758 chunk LKM::prototypes();
1759 chunk LKM::code();
1613 - decl data_types(); 1760 - decl data_types();
1614 - method init(); 1761 - method init();
1615 - 1762
1616 - /* XXX: Callback that should be in the front-end: */ 1763 - /* XXX: Callback that should be in the front-end: */
1617 - chunk Ethernet::adapter_init_tx(Ethernet::Device); 1764 - chunk Ethernet::adapter_init_tx(Ethernet::Device);
1618 - 1765 + method init(e1000::Context, Builtin::number);
1766 + method alloc(); // Returns != 0 on failure
1767 + method free();
1768 + method configure();
1769
1619 - /* Clean the ring (i.e: move the head closer to the tail): */ 1770 - /* Clean the ring (i.e: move the head closer to the tail): */
1620 - method clean(); 1771 - method clean();
1621 - /* Return the number of clean descriptors left in the ring: */ 1772 - /* Return the number of clean descriptors left in the ring: */
1622 - method descriptors_remaining(); 1773 - method descriptors_remaining();
1623 - method tso_cksum_offload(Socket::SKBuff); 1774 - method tso_cksum_offload(Socket::SKBuff);
1705 - provided sequence register_unset32(e1000::Context, e1000::Register, ::number) 1856 - provided sequence register_unset32(e1000::Context, e1000::Register, ::number)
1706 - { 1857 - {
1707 - provided chunk LKM::prototypes(); 1858 - provided chunk LKM::prototypes();
1708 - provided chunk LKM::code(); 1859 - provided chunk LKM::code();
1709 - provided chunk ::CALL(); 1860 - provided chunk ::CALL();
1710 + attribute TxRing.scalar tx_ring; 1861 + // Re-expose all the Ring attributes + the size of a single descriptor:
1862 + attribute Context.ref hw_ctx;
1863 + attribute DMA::DMAHandle.scalar dma;
1864 + attribute Builtin::number.scalar size;
1865 + attribute TxDescriptor.scalar descs;
1866 + attribute Builtin::number.scalar desc_size;
1711 } 1867 }
1712 } 1868 }
1713 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt 1869 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt
1714 old mode 100755
1715 new mode 100644
1716 --- a/rathaxes/samples/e1000/ethernet.blt 1870 --- a/rathaxes/samples/e1000/ethernet.blt
1717 +++ b/rathaxes/samples/e1000/ethernet.blt 1871 +++ b/rathaxes/samples/e1000/ethernet.blt
1718 @@ -1,4 +1,4 @@ 1872 @@ -1,4 +1,4 @@
1719 -with Ethernet, PCI, LKM, Log, Builtin 1873 -with Ethernet, PCI, LKM, Log, Builtin
1720 +with Ethernet, Socket, PCI, LKM, Log, Builtin 1874 +with Ethernet, Socket, PCI, LKM, Log, Builtin
1721 { 1875 {
1722 template type Ethernet::ProtocolId() 1876 template type Ethernet::ProtocolId()
1723 { 1877 {
1878 @@ -9,7 +9,7 @@
1879
1880 chunk LKM::prototypes()
1881 {
1882 - static const char *rtx_ethernet_protocol_id_to_str(unsigned short);
1883 + static const char *rtx_ethernet_protocol_id_to_str(unsigned short);
1884 }
1885
1886 chunk LKM::data()
1887 @@ -28,7 +28,7 @@
1888
1889 chunk LKM::code()
1890 {
1891 - static const char *rtx_ethernet_protocol_id_to_str(unsigned short proto_id)
1892 + static const char *rtx_ethernet_protocol_id_to_str(unsigned short proto_id)
1893 {
1894 for (int i = 0;
1895 i != sizeof(rtx_ethernet_proto_table) / sizeof(rtx_ethernet_proto_table[0]);
1724 @@ -61,7 +61,7 @@ 1896 @@ -61,7 +61,7 @@
1725 1897
1726 method init(Builtin::symbol dev) 1898 method init(Builtin::symbol dev)
1727 { 1899 {
1728 - ${self} = (${Ethernet::AbstractDevice} *)${dev}; 1900 - ${self} = (${Ethernet::AbstractDevice} *)${dev};
1753 - template sequence Ethernet::open(Ethernet::Device dev) 1925 - template sequence Ethernet::open(Ethernet::Device dev)
1754 + template sequence Ethernet::open() 1926 + template sequence Ethernet::open()
1755 { 1927 {
1756 chunk LKM::includes() 1928 chunk LKM::includes()
1757 { 1929 {
1758 @@ -164,60 +167,68 @@ 1930 @@ -157,100 +160,114 @@
1759 { 1931
1760 static int rtx_ethernet_open(struct net_device *dev) 1932 chunk LKM::prototypes()
1933 {
1934 - static int rtx_ethernet_open(struct net_device *);
1935 + static int rtx_ethernet_open(struct net_device *);
1936 }
1937
1938 chunk LKM::code()
1939 {
1940 - static int rtx_ethernet_open(struct net_device *dev)
1941 + static int rtx_ethernet_open(struct net_device *dev)
1761 { 1942 {
1762 - /* 1943 - /*
1763 - * XXX The casts are here because the compiler doesn't resolve 1944 - * XXX The casts are here because the compiler doesn't resolve
1764 - * "enclosed" type (e.g: local.var.enclosed) correctly. 1945 - * "enclosed" type (e.g: local.var.enclosed) correctly.
1765 - */ 1946 - */
1815 + template sequence Ethernet::send() 1996 + template sequence Ethernet::send()
1816 { 1997 {
1817 chunk LKM::prototypes() 1998 chunk LKM::prototypes()
1818 { 1999 {
1819 - static int rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev); 2000 - 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); 2001 + static int rtx_ethernet_xmit(struct sk_buff *skb, struct net_device *dev);
1821 } 2002 }
1822 2003
1823 chunk LKM::code() 2004 chunk LKM::code()
1824 { 2005 {
1825 - static int rtx_ethernet_xmit(struct sk_buff* kernel_skb, struct net_device *net_dev) 2006 - 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) 2007 + static int rtx_ethernet_xmit(struct sk_buff *k_skb, struct net_device *net_dev)
1827 { 2008 {
1828 ${Ethernet::Device.ref} rtx_ether_ctx = netdev_priv(net_dev); 2009 ${Ethernet::Device.ref} rtx_ether_ctx = netdev_priv(net_dev);
1829 - ${Socket::AbstractSKBuff.ref} rtx_skb = (${Socket::AbstractSKBuff.ref}) kernel_skb; 2010 - ${Socket::AbstractSKBuff.ref} rtx_skb = (${Socket::AbstractSKBuff.ref}) kernel_skb;
1830 + ${Socket::SKBuff.ref} rtx_skb; 2011 + ${Socket::SKBuff.ref} rtx_skb;
1831 2012
1847 - template sequence Ethernet::close(Ethernet::Device dev) 2028 - template sequence Ethernet::close(Ethernet::Device dev)
1848 + template sequence Ethernet::close() 2029 + template sequence Ethernet::close()
1849 { 2030 {
1850 chunk LKM::prototypes() 2031 chunk LKM::prototypes()
1851 { 2032 {
1852 @@ -226,31 +237,37 @@ 2033 - static int rtx_ethernet_close(struct net_device *);
2034 + static int rtx_ethernet_close(struct net_device *);
2035 }
1853 2036
1854 chunk LKM::code() 2037 chunk LKM::code()
1855 { 2038 {
1856 - static int rtx_ethernet_close(struct net_device *dev) 2039 - static int rtx_ethernet_close(struct net_device *dev)
1857 + static int rtx_ethernet_close(struct net_device *net_dev) 2040 + static int rtx_ethernet_close(struct net_device *net_dev)
1858 { 2041 {
1859 - ${Ethernet::AbstractDevice.ref} rtx_net_dev; 2042 - ${Ethernet::AbstractDevice.ref} rtx_net_dev;
1860 - { /* XXX: I end up with a placeholder if I don't open a scope */ 2043 - { /* XXX: I end up with a placeholder if I don't open a scope */
1861 - ${local.rtx_net_dev.init(local.dev)}; 2044 - ${local.rtx_net_dev.init(local.dev)};
1862 - } 2045 - }
1899 - template sequence Ethernet::interrupt_handler(Ethernet::Device dev) 2082 - template sequence Ethernet::interrupt_handler(Ethernet::Device dev)
1900 + template sequence Ethernet::interrupt_handler() 2083 + template sequence Ethernet::interrupt_handler()
1901 { 2084 {
1902 /* 2085 /*
1903 * We can't use the irqreturn_t type here because CNornm doesn't know 2086 * We can't use the irqreturn_t type here because CNornm doesn't know
1904 @@ -269,11 +286,16 @@ 2087 @@ -258,29 +275,34 @@
2088 */
2089 chunk LKM::prototypes()
2090 {
2091 - static enum irqreturn rtx_ethernet_interrupt_handler(int, void *);
2092 + static enum irqreturn rtx_ethernet_interrupt_handler(int, void *);
2093 }
2094
2095 chunk LKM::code()
2096 {
2097 - static enum irqreturn rtx_ethernet_interrupt_handler(int irq, void *dev_id)
2098 + static enum irqreturn rtx_ethernet_interrupt_handler(int irq, void *dev_id)
2099 {
2100 ${Ethernet::AbstractDevice.ref} rtx_net_dev = dev_id;
1905 ${Ethernet::Device.ref} rtx_ether_ctx; 2101 ${Ethernet::Device.ref} rtx_ether_ctx;
1906 rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx}; 2102 rtx_ether_ctx = ${local.rtx_net_dev.rtx_ether_ctx};
1907 2103
1908 - ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)}; 2104 - ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)};
1909 + ${pointcut Ethernet::adapter_handle_interrupt(local.rtx_ether_ctx)}; 2105 + ${pointcut Ethernet::adapter_handle_interrupt(local.rtx_ether_ctx)};
1917 + { 2113 + {
1918 + } 2114 + }
1919 } 2115 }
1920 2116
1921 template sequence Ethernet::init() 2117 template sequence Ethernet::init()
1922 @@ -342,12 +364,8 @@ 2118 {
1923 * XXX: the asssignments/casts are here to circumvent 2119 chunk LKM::data()
1924 * typing issues in the compiler (see previous XXX). 2120 {
1925 */ 2121 - static const struct net_device_ops rtx_ether_ops =
2122 + static const struct net_device_ops rtx_ether_ops =
2123 {
2124 .ndo_open = rtx_ethernet_open,
2125 .ndo_stop = rtx_ethernet_close,
2126 @@ -298,64 +320,62 @@
2127 */
2128 chunk PCI::pci_probe_hook(PCI::Device rtx_pci_dev)
2129 {
2130 - ${Ethernet::AbstractDevice.ref} rtx_net_dev;
2131 - ${Ethernet::Device.ref} rtx_ether_ctx;
2132 + {
2133 + ${Ethernet::AbstractDevice.ref} rtx_net_dev;
2134 + ${Ethernet::Device.ref} rtx_ether_ctx;
2135
2136 - rtx_net_dev = (${Ethernet::AbstractDevice.ref})alloc_etherdev(sizeof(*rtx_ether_ctx));
2137 - if (!rtx_net_dev)
2138 - {
2139 - ${Log::info("cannot allocate the ethernet device context")};
2140 - error = -ENOMEM;
2141 - goto fail;
2142 + rtx_net_dev = (${Ethernet::AbstractDevice.ref})alloc_etherdev(sizeof(*rtx_ether_ctx));
2143 + if (!rtx_net_dev)
2144 + {
2145 + ${Log::info("cannot allocate the ethernet device context")};
2146 + error = -ENOMEM;
2147 + goto fail;
2148 + }
2149 + SET_NETDEV_DEV(${local.rtx_net_dev.k_net_dev}, ${rtx_pci_dev.device});
2150 + strlcpy(${local.rtx_net_dev.k_net_dev}->name,
2151 + ${config.ifname},
2152 + sizeof(${local.rtx_net_dev.k_net_dev}->name));
2153 + ${local.rtx_net_dev.k_net_dev}->irq = ${rtx_pci_dev.irq};
2154 + ${local.rtx_net_dev.k_net_dev}->netdev_ops = &rtx_ether_ops;
2155 +
2156 + error = register_netdev(${local.rtx_net_dev.k_net_dev});
2157 + if (error)
2158 + {
2159 + ${Log::info("cannot register the driver in the net subsystem")};
2160 + goto fail;
2161 + }
2162 +
2163 + /* Initialize our context held by the net_device structure */
2164 + /*
2165 + * XXX: the cast is here because the compiler resolve the
2166 + * type of rtx_pci_dev.pci_device to the type of
2167 + * rtx_pci_dev instead of the type of rtx_pci_dev.pci_device.
2168 + */
2169 + ${PCI::AbstractDevice.ref} workaround = ${rtx_pci_dev.pci_device};
2170 + ${cast local.workaround as PCI::AbstractDevice};
2171 + { /* XXX: I end up with a placeholder if I don't open a scope */
2172 + ${local.rtx_ether_ctx.init(local.rtx_net_dev, local.workaround)};
2173 + }
2174 +
2175 + /* Register ourselves in the parent context: */
2176 + /* ${rtx_pci_dev.set_context(local.rtx_ether_ctx)}; */
2177 + ${rtx_pci_dev}->context = rtx_ether_ctx;
2178 +
2179 + /*
2180 + * XXX: the asssignments/casts are here to circumvent
2181 + * typing issues in the compiler (see previous XXX).
2182 + */
2183 + unsigned char /* __iomem */ *io_addr = ${rtx_pci_dev.ioaddr};
2184 + ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx, local.io_addr)};
2185 + ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)};
2186 + ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)};
2187 + memcpy(${local.rtx_ether_ctx.perm_addr},
2188 + ${local.rtx_ether_ctx.dev_addr},
2189 + ${local.rtx_net_dev.k_net_dev}->addr_len);
2190 }
2191 - SET_NETDEV_DEV(${local.rtx_net_dev.k_net_dev}, ${rtx_pci_dev.device});
2192 - strlcpy(${local.rtx_net_dev.k_net_dev}->name,
2193 - ${config.ifname},
2194 - sizeof(${local.rtx_net_dev.k_net_dev}->name));
2195 - ${local.rtx_net_dev.k_net_dev}->irq = ${rtx_pci_dev.irq};
2196 - ${local.rtx_net_dev.k_net_dev}->netdev_ops = &rtx_ether_ops;
2197 -
2198 - error = register_netdev(${local.rtx_net_dev.k_net_dev});
2199 - if (error)
2200 - {
2201 - ${Log::info("cannot register the driver in the net subsystem")};
2202 - goto fail;
2203 - }
2204 -
2205 - /* Initialize our context held by the net_device structure */
2206 - /*
2207 - * XXX: the cast is here because the compiler resolve the
2208 - * type of rtx_pci_dev.pci_device to the type of
2209 - * rtx_pci_dev instead of the type of rtx_pci_dev.pci_device.
2210 - */
2211 - ${PCI::AbstractDevice.ref} workaround = ${rtx_pci_dev.pci_device};
2212 - ${cast local.workaround as PCI::AbstractDevice};
2213 - { /* XXX: I end up with a placeholder if I don't open a scope */
2214 - ${local.rtx_ether_ctx.init(local.rtx_net_dev, local.workaround)};
2215 - }
2216 -
2217 - /* Register ourselves in the parent context: */
2218 - /* ${rtx_pci_dev.set_context(local.rtx_ether_ctx)}; */
2219 - ${rtx_pci_dev}->context = rtx_ether_ctx;
2220 -
2221 - /*
2222 - * XXX: the asssignments/casts are here to circumvent
2223 - * typing issues in the compiler (see previous XXX).
2224 - */
1926 - int bars = ${rtx_pci_dev.bars}; 2225 - int bars = ${rtx_pci_dev.bars};
1927 unsigned char /* __iomem */ *ioaddr = ${rtx_pci_dev.ioaddr}; 2226 - unsigned char /* __iomem */ *ioaddr = ${rtx_pci_dev.ioaddr};
1928 - ${cast local.bars as Builtin::number}; 2227 - ${cast local.bars as Builtin::number};
1929 - ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx, 2228 - ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx,
1930 - local.bars, 2229 - local.bars,
1931 - local.ioaddr)}; 2230 - local.ioaddr)};
1932 + ${pointcut Ethernet::adapter_init_context(local.rtx_ether_ctx, local.ioaddr)}; 2231 - ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)};
1933 ${pointcut Ethernet::adapter_reset(local.rtx_ether_ctx)}; 2232 - ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)};
1934 ${pointcut Ethernet::adapter_load_mac_address(local.rtx_ether_ctx)}; 2233 - memcpy(${local.rtx_ether_ctx.perm_addr},
1935 memcpy(${local.rtx_ether_ctx.perm_addr}, 2234 - ${local.rtx_ether_ctx.dev_addr},
1936 @@ -355,7 +373,7 @@ 2235 - ${local.rtx_net_dev.k_net_dev}->addr_len);
1937 ${local.rtx_net_dev.k_net_dev}->addr_len);
1938 } 2236 }
1939 2237
1940 - /* This chunk should be removed (see #26) */ 2238 - /* This chunk should be removed (see #26) */
1941 + /* XXX This chunk should be removed (see #26) */ 2239 + /* XXX This chunk should be removed (see #26) */
1942 chunk ::CALL() 2240 chunk ::CALL()
1943 { 2241 {
1944 } 2242 }
1945 @@ -377,7 +395,7 @@ 2243 @@ -369,15 +389,17 @@
1946 free_netdev(${local.rtx_net_dev.k_net_dev}); 2244 */
2245 chunk PCI::pci_remove_hook(PCI::Device rtx_pci_dev)
2246 {
2247 - ${Ethernet::Device.ref} rtx_ether_ctx = ${rtx_pci_dev.rtx_drv_context};
2248 - BUG_ON(!rtx_ether_ctx);
2249 + {
2250 + ${Ethernet::Device.ref} rtx_ether_ctx = ${rtx_pci_dev.rtx_drv_context};
2251 + BUG_ON(!rtx_ether_ctx);
2252
2253 - ${Ethernet::AbstractDevice.ref} rtx_net_dev = ${local.rtx_ether_ctx.net_device};
2254 - unregister_netdev(${local.rtx_net_dev.k_net_dev});
2255 - free_netdev(${local.rtx_net_dev.k_net_dev});
2256 + ${Ethernet::AbstractDevice.ref} rtx_net_dev = ${local.rtx_ether_ctx.net_device};
2257 + unregister_netdev(${local.rtx_net_dev.k_net_dev});
2258 + free_netdev(${local.rtx_net_dev.k_net_dev});
2259 + }
1947 } 2260 }
1948 2261
1949 - /* This chunk should be removed (see #26) */ 2262 - /* This chunk should be removed (see #26) */
1950 + /* XXX This chunk should be removed (see #26) */ 2263 + /* XXX This chunk should be removed (see #26) */
1951 chunk ::CALL() 2264 chunk ::CALL()
1952 { 2265 {
1953 } 2266 }
1954 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti 2267 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti
1955 old mode 100755
1956 new mode 100644
1957 --- a/rathaxes/samples/e1000/ethernet.rti 2268 --- a/rathaxes/samples/e1000/ethernet.rti
1958 +++ b/rathaxes/samples/e1000/ethernet.rti 2269 +++ b/rathaxes/samples/e1000/ethernet.rti
1959 @@ -2,16 +2,16 @@ 2270 @@ -2,16 +2,16 @@
1960 { 2271 {
1961 required variable Builtin::string ifname; 2272 required variable Builtin::string ifname;
2056 + // Put a packet on the tx ring and signal the device: 2367 + // Put a packet on the tx ring and signal the device:
2057 + provided pointcut Ethernet::adapter_xmit(Ethernet::Device, Socket::SKBuff); 2368 + provided pointcut Ethernet::adapter_xmit(Ethernet::Device, Socket::SKBuff);
2058 } 2369 }
2059 2370
2060 - required sequence close(Ethernet::Device) 2371 - required sequence close(Ethernet::Device)
2061 + provided sequence close() 2372 + provided sequence close()
2062 { 2373 {
2063 - provided chunk LKM::prototypes(); 2374 - provided chunk LKM::prototypes();
2064 - provided chunk LKM::code(); 2375 - provided chunk LKM::code();
2065 + provided chunk LKM::prototypes(); 2376 + provided chunk LKM::prototypes();
2066 + provided chunk LKM::code(); 2377 + provided chunk LKM::code();
2106 + // dev_addr field/attribute of Ethernet::Device: 2417 + // dev_addr field/attribute of Ethernet::Device:
2107 provided pointcut Ethernet::adapter_load_mac_address(Ethernet::Device); 2418 provided pointcut Ethernet::adapter_load_mac_address(Ethernet::Device);
2108 } 2419 }
2109 2420
2110 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx 2421 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx
2111 old mode 100755
2112 new mode 100644
2113 --- a/rathaxes/samples/e1000/lkm.rtx 2422 --- a/rathaxes/samples/e1000/lkm.rtx
2114 +++ b/rathaxes/samples/e1000/lkm.rtx 2423 +++ b/rathaxes/samples/e1000/lkm.rtx
2115 @@ -1,40 +1,5 @@ 2424 @@ -1,40 +1,5 @@
2116 device LKM use LKM, PCI, Ethernet, Log, Socket 2425 device LKM use LKM, PCI, Ethernet, Log, Socket
2117 { 2426 {
2161 + LKM::description = "Rathaxes Intel PCI Gigabit NIC sample driver"; 2470 + LKM::description = "Rathaxes Intel PCI Gigabit NIC sample driver";
2162 LKM::license = "GPL"; 2471 LKM::license = "GPL";
2163 2472
2164 /* 2473 /*
2165 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/old_e1000.blt 2474 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 2475 copy from rathaxes/samples/e1000/e1000.blt
2169 copy to rathaxes/samples/e1000/old_e1000.blt 2476 copy to rathaxes/samples/e1000/old_e1000.blt
2170 --- a/rathaxes/samples/e1000/e1000.blt 2477 --- a/rathaxes/samples/e1000/e1000.blt
2171 +++ b/rathaxes/samples/e1000/old_e1000.blt 2478 +++ b/rathaxes/samples/e1000/old_e1000.blt
2172 @@ -170,14 +170,15 @@ 2479 @@ -170,14 +170,15 @@
2188 + if (${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)}) 2495 + if (${DMA::map(local.rtx_ether_ctx.device, local.skbuff.data, local.skbuff.len, RTX_DMA_FROM_DEVICE)})
2189 { 2496 {
2190 ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")}; 2497 ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")};
2191 goto err_skbuffs_map; 2498 goto err_skbuffs_map;
2192 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/old_e1000.rti 2499 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 2500 copy from rathaxes/samples/e1000/e1000.rti
2196 copy to rathaxes/samples/e1000/old_e1000.rti 2501 copy to rathaxes/samples/e1000/old_e1000.rti
2197 diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt 2502 diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt
2198 old mode 100755
2199 new mode 100644
2200 --- a/rathaxes/samples/e1000/socket.blt 2503 --- a/rathaxes/samples/e1000/socket.blt
2201 +++ b/rathaxes/samples/e1000/socket.blt 2504 +++ b/rathaxes/samples/e1000/socket.blt
2202 @@ -22,16 +22,12 @@ 2505 @@ -22,16 +22,12 @@
2203 { 2506 {
2204 decl data_types() 2507 decl data_types()
2344 + len: ((struct sk_buff *)((${self})->sk_buff))->len; 2647 + len: ((struct sk_buff *)((${self})->sk_buff))->len;
2345 } 2648 }
2346 } 2649 }
2347 } 2650 }
2348 diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti 2651 diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti
2349 old mode 100755
2350 new mode 100644
2351 --- a/rathaxes/samples/e1000/socket.rti 2652 --- a/rathaxes/samples/e1000/socket.rti
2352 +++ b/rathaxes/samples/e1000/socket.rti 2653 +++ b/rathaxes/samples/e1000/socket.rti
2353 @@ -12,20 +12,14 @@ 2654 @@ -12,20 +12,14 @@
2354 { 2655 {
2355 chunk LKM::prototypes(); 2656 chunk LKM::prototypes();