77 // net_device functions |
77 // net_device functions |
78 int ec_eoedev_open(struct net_device *); |
78 int ec_eoedev_open(struct net_device *); |
79 int ec_eoedev_stop(struct net_device *); |
79 int ec_eoedev_stop(struct net_device *); |
80 int ec_eoedev_tx(struct sk_buff *, struct net_device *); |
80 int ec_eoedev_tx(struct sk_buff *, struct net_device *); |
81 struct net_device_stats *ec_eoedev_stats(struct net_device *); |
81 struct net_device_stats *ec_eoedev_stats(struct net_device *); |
|
82 static int ec_eoedev_set_mac(struct net_device *netdev, void *p); |
82 |
83 |
83 /*****************************************************************************/ |
84 /*****************************************************************************/ |
84 |
85 |
85 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) |
86 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) |
86 /** Device operations for EoE interfaces. |
87 /** Device operations for EoE interfaces. |
88 static const struct net_device_ops ec_eoedev_ops = { |
89 static const struct net_device_ops ec_eoedev_ops = { |
89 .ndo_open = ec_eoedev_open, |
90 .ndo_open = ec_eoedev_open, |
90 .ndo_stop = ec_eoedev_stop, |
91 .ndo_stop = ec_eoedev_stop, |
91 .ndo_start_xmit = ec_eoedev_tx, |
92 .ndo_start_xmit = ec_eoedev_tx, |
92 .ndo_get_stats = ec_eoedev_stats, |
93 .ndo_get_stats = ec_eoedev_stats, |
|
94 .ndo_set_mac_address = ec_eoedev_set_mac, |
93 }; |
95 }; |
94 #endif |
96 #endif |
|
97 |
|
98 /*****************************************************************************/ |
|
99 |
|
100 /** |
|
101 * ec_eoedev_set_mac - Change the Ethernet Address of the NIC |
|
102 * @netdev: network interface device structure |
|
103 * @p: pointer to an address structure |
|
104 * |
|
105 * Returns 0 on success, negative on failure |
|
106 **/ |
|
107 static int |
|
108 ec_eoedev_set_mac(struct net_device *netdev, void *p) |
|
109 { |
|
110 struct sockaddr *addr = p; |
|
111 |
|
112 if (!is_valid_ether_addr(addr->sa_data)) |
|
113 return -EADDRNOTAVAIL; |
|
114 |
|
115 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); |
|
116 |
|
117 return 0; |
|
118 } |
95 |
119 |
96 /*****************************************************************************/ |
120 /*****************************************************************************/ |
97 |
121 |
98 /** EoE constructor. |
122 /** EoE constructor. |
99 * |
123 * |
105 ec_eoe_t *eoe, /**< EoE handler */ |
129 ec_eoe_t *eoe, /**< EoE handler */ |
106 ec_slave_t *slave /**< EtherCAT slave */ |
130 ec_slave_t *slave /**< EtherCAT slave */ |
107 ) |
131 ) |
108 { |
132 { |
109 ec_eoe_t **priv; |
133 ec_eoe_t **priv; |
110 int i, ret = 0; |
134 int ret = 0; |
111 char name[EC_DATAGRAM_NAME_SIZE]; |
135 char name[EC_DATAGRAM_NAME_SIZE]; |
|
136 |
|
137 struct net_device *dev; |
|
138 unsigned char lo_mac[ETH_ALEN] = {0}; |
|
139 unsigned int use_master_mac = 0; |
112 |
140 |
113 eoe->slave = slave; |
141 eoe->slave = slave; |
114 |
142 |
115 ec_datagram_init(&eoe->datagram); |
143 ec_datagram_init(&eoe->datagram); |
116 eoe->queue_datagram = 0; |
144 eoe->queue_datagram = 0; |
163 eoe->dev->stop = ec_eoedev_stop; |
191 eoe->dev->stop = ec_eoedev_stop; |
164 eoe->dev->hard_start_xmit = ec_eoedev_tx; |
192 eoe->dev->hard_start_xmit = ec_eoedev_tx; |
165 eoe->dev->get_stats = ec_eoedev_stats; |
193 eoe->dev->get_stats = ec_eoedev_stats; |
166 #endif |
194 #endif |
167 |
195 |
168 for (i = 0; i < ETH_ALEN; i++) |
196 // First check if the MAC address assigned to the master is globally |
169 eoe->dev->dev_addr[i] = i | (i << 4); |
197 // unique |
|
198 if ((slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[0] & 0x02) != |
|
199 0x02) { |
|
200 // The master MAC is unique and the NIC part can be used for the EoE |
|
201 // interface MAC |
|
202 use_master_mac = 1; |
|
203 } |
|
204 else { |
|
205 // The master MAC is not unique, so we check for unique MAC in other |
|
206 // interfaces |
|
207 dev = first_net_device(&init_net); |
|
208 while (dev) { |
|
209 // Check if globally unique MAC address |
|
210 if (dev->addr_len == ETH_ALEN) { |
|
211 if (memcmp(dev->dev_addr, lo_mac, ETH_ALEN) != 0) { |
|
212 if ((dev->dev_addr[0] & 0x02) != 0x02) { |
|
213 // The first globally unique MAC address has been |
|
214 // identified |
|
215 break; |
|
216 } |
|
217 } |
|
218 } |
|
219 dev = next_net_device(dev); |
|
220 } |
|
221 if (eoe->dev->addr_len == ETH_ALEN) { |
|
222 if (dev) { |
|
223 // A unique MAC were identified in one of the other network |
|
224 // interfaces and the NIC part can be used for the EoE |
|
225 // interface MAC. |
|
226 EC_SLAVE_INFO(slave, "%s MAC address derived from" |
|
227 " NIC part of %s MAC address", |
|
228 eoe->dev->name, dev->name); |
|
229 eoe->dev->dev_addr[1] = dev->dev_addr[3]; |
|
230 eoe->dev->dev_addr[2] = dev->dev_addr[4]; |
|
231 eoe->dev->dev_addr[3] = dev->dev_addr[5]; |
|
232 } |
|
233 else { |
|
234 use_master_mac = 1; |
|
235 } |
|
236 } |
|
237 } |
|
238 if (eoe->dev->addr_len == ETH_ALEN) { |
|
239 if (use_master_mac) { |
|
240 EC_SLAVE_INFO(slave, "%s MAC address derived" |
|
241 " from NIC part of %s MAC address", |
|
242 eoe->dev->name, |
|
243 slave->master->devices[EC_DEVICE_MAIN].dev->name); |
|
244 eoe->dev->dev_addr[1] = |
|
245 slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[3]; |
|
246 eoe->dev->dev_addr[2] = |
|
247 slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[4]; |
|
248 eoe->dev->dev_addr[3] = |
|
249 slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[5]; |
|
250 } |
|
251 eoe->dev->dev_addr[0] = 0x02; |
|
252 eoe->dev->dev_addr[4] = (uint8_t)(slave->ring_position >> 8); |
|
253 eoe->dev->dev_addr[5] = (uint8_t)(slave->ring_position); |
|
254 } |
170 |
255 |
171 // initialize private data |
256 // initialize private data |
172 priv = netdev_priv(eoe->dev); |
257 priv = netdev_priv(eoe->dev); |
173 *priv = eoe; |
258 *priv = eoe; |
174 |
259 |
264 |
347 |
265 if (remaining_size <= eoe->slave->configured_tx_mailbox_size - 10) { |
348 if (remaining_size <= eoe->slave->configured_tx_mailbox_size - 10) { |
266 current_size = remaining_size; |
349 current_size = remaining_size; |
267 last_fragment = 1; |
350 last_fragment = 1; |
268 } else { |
351 } else { |
269 current_size = ((eoe->slave->configured_tx_mailbox_size - 10) / 32) * 32; |
352 current_size = |
|
353 ((eoe->slave->configured_tx_mailbox_size - 10) / 32) * 32; |
270 last_fragment = 0; |
354 last_fragment = 0; |
271 } |
355 } |
272 |
356 |
273 if (eoe->tx_fragment_number) { |
357 if (eoe->tx_fragment_number) { |
274 complete_offset = eoe->tx_offset / 32; |
358 complete_offset = eoe->tx_offset / 32; |