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 unique |
169 eoe->dev->dev_addr[i] = i | (i << 4); |
197 if ((slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[0] & 0x02) != 0x02) { |
|
198 // The master MAC is unique and the NIC part can be used for the EoE interface MAC |
|
199 use_master_mac = 1; |
|
200 } |
|
201 else { |
|
202 // The master MAC is not unique, so we check for unique MAC in other interfaces |
|
203 dev = first_net_device(&init_net); |
|
204 while (dev) { |
|
205 // Check if globally unique MAC address |
|
206 if (dev->addr_len == ETH_ALEN) { |
|
207 if (memcmp(dev->dev_addr, lo_mac, ETH_ALEN) != 0) { |
|
208 if ((dev->dev_addr[0] & 0x02) != 0x02) { |
|
209 // The first globally unique MAC address has been identified |
|
210 break; |
|
211 } |
|
212 } |
|
213 } |
|
214 dev = next_net_device(dev); |
|
215 } |
|
216 if (eoe->dev->addr_len == ETH_ALEN) { |
|
217 if (dev) { |
|
218 // A unique MAC were identified in one of the other network interfaces |
|
219 // and the NIC part can be used for the EoE interface MAC. |
|
220 EC_SLAVE_INFO(slave, "%s MAC address derived from NIC part of %s MAC address", |
|
221 eoe->dev->name, dev->name); |
|
222 eoe->dev->dev_addr[1] = dev->dev_addr[3]; |
|
223 eoe->dev->dev_addr[2] = dev->dev_addr[4]; |
|
224 eoe->dev->dev_addr[3] = dev->dev_addr[5]; |
|
225 } |
|
226 else { |
|
227 use_master_mac = 1; |
|
228 } |
|
229 } |
|
230 } |
|
231 if (eoe->dev->addr_len == ETH_ALEN) { |
|
232 if (use_master_mac) { |
|
233 EC_SLAVE_INFO(slave, "%s MAC address derived from NIC part of %s MAC address", |
|
234 eoe->dev->name, slave->master->devices[EC_DEVICE_MAIN].dev->name); |
|
235 eoe->dev->dev_addr[1] = slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[3]; |
|
236 eoe->dev->dev_addr[2] = slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[4]; |
|
237 eoe->dev->dev_addr[3] = slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[5]; |
|
238 } |
|
239 eoe->dev->dev_addr[0] = 0x02; |
|
240 eoe->dev->dev_addr[4] = (uint8_t)(slave->ring_position >> 8); |
|
241 eoe->dev->dev_addr[5] = (uint8_t)(slave->ring_position); |
|
242 } |
170 |
243 |
171 // initialize private data |
244 // initialize private data |
172 priv = netdev_priv(eoe->dev); |
245 priv = netdev_priv(eoe->dev); |
173 *priv = eoe; |
246 *priv = eoe; |
174 |
247 |