00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00035
00036
00037 #include <linux/module.h>
00038 #include <linux/skbuff.h>
00039 #include <linux/if_ether.h>
00040 #include <linux/netdevice.h>
00041
00042 #include "device.h"
00043 #include "master.h"
00044
00045 #ifdef EC_DEBUG_RING
00046 #define timersub(a, b, result) \
00047 do { \
00048 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
00049 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
00050 if ((result)->tv_usec < 0) { \
00051 --(result)->tv_sec; \
00052 (result)->tv_usec += 1000000; \
00053 } \
00054 } while (0)
00055 #endif
00056
00057
00058
00063 int ec_device_init(
00064 ec_device_t *device,
00065 ec_master_t *master
00066 )
00067 {
00068 int ret;
00069 unsigned int i;
00070 struct ethhdr *eth;
00071 #ifdef EC_DEBUG_IF
00072 char ifname[10];
00073 char mb = 'x';
00074 #endif
00075
00076 device->master = master;
00077 device->dev = NULL;
00078 device->poll = NULL;
00079 device->module = NULL;
00080 device->open = 0;
00081 device->link_state = 0;
00082 for (i = 0; i < EC_TX_RING_SIZE; i++) {
00083 device->tx_skb[i] = NULL;
00084 }
00085 device->tx_ring_index = 0;
00086 #ifdef EC_HAVE_CYCLES
00087 device->cycles_poll = 0;
00088 #endif
00089 #ifdef EC_DEBUG_RING
00090 device->timeval_poll.tv_sec = 0;
00091 device->timeval_poll.tv_usec = 0;
00092 #endif
00093 device->jiffies_poll = 0;
00094
00095 ec_device_clear_stats(device);
00096
00097 #ifdef EC_DEBUG_RING
00098 for (i = 0; i < EC_DEBUG_RING_SIZE; i++) {
00099 ec_debug_frame_t *df = &device->debug_frames[i];
00100 df->dir = TX;
00101 df->t.tv_sec = 0;
00102 df->t.tv_usec = 0;
00103 memset(df->data, 0, EC_MAX_DATA_SIZE);
00104 df->data_size = 0;
00105 }
00106 #endif
00107 #ifdef EC_DEBUG_RING
00108 device->debug_frame_index = 0;
00109 device->debug_frame_count = 0;
00110 #endif
00111
00112 #ifdef EC_DEBUG_IF
00113 if (device == &master->devices[EC_DEVICE_MAIN]) {
00114 mb = 'm';
00115 }
00116 else {
00117 mb = 'b';
00118 }
00119
00120 sprintf(ifname, "ecdbg%c%u", mb, master->index);
00121
00122 ret = ec_debug_init(&device->dbg, device, ifname);
00123 if (ret < 0) {
00124 EC_MASTER_ERR(master, "Failed to init debug device!\n");
00125 goto out_return;
00126 }
00127 #endif
00128
00129 for (i = 0; i < EC_TX_RING_SIZE; i++) {
00130 if (!(device->tx_skb[i] = dev_alloc_skb(ETH_FRAME_LEN))) {
00131 EC_MASTER_ERR(master, "Error allocating device socket buffer!\n");
00132 ret = -ENOMEM;
00133 goto out_tx_ring;
00134 }
00135
00136
00137 skb_reserve(device->tx_skb[i], ETH_HLEN);
00138 eth = (struct ethhdr *) skb_push(device->tx_skb[i], ETH_HLEN);
00139 eth->h_proto = htons(0x88A4);
00140 memset(eth->h_dest, 0xFF, ETH_ALEN);
00141 }
00142
00143 return 0;
00144
00145 out_tx_ring:
00146 for (i = 0; i < EC_TX_RING_SIZE; i++) {
00147 if (device->tx_skb[i]) {
00148 dev_kfree_skb(device->tx_skb[i]);
00149 }
00150 }
00151 #ifdef EC_DEBUG_IF
00152 ec_debug_clear(&device->dbg);
00153 out_return:
00154 #endif
00155 return ret;
00156 }
00157
00158
00159
00162 void ec_device_clear(
00163 ec_device_t *device
00164 )
00165 {
00166 unsigned int i;
00167
00168 if (device->open) {
00169 ec_device_close(device);
00170 }
00171 for (i = 0; i < EC_TX_RING_SIZE; i++)
00172 dev_kfree_skb(device->tx_skb[i]);
00173 #ifdef EC_DEBUG_IF
00174 ec_debug_clear(&device->dbg);
00175 #endif
00176 }
00177
00178
00179
00182 void ec_device_attach(
00183 ec_device_t *device,
00184 struct net_device *net_dev,
00185 ec_pollfunc_t poll,
00186 struct module *module
00187 )
00188 {
00189 unsigned int i;
00190 struct ethhdr *eth;
00191
00192 ec_device_detach(device);
00193
00194 device->dev = net_dev;
00195 device->poll = poll;
00196 device->module = module;
00197
00198 for (i = 0; i < EC_TX_RING_SIZE; i++) {
00199 device->tx_skb[i]->dev = net_dev;
00200 eth = (struct ethhdr *) (device->tx_skb[i]->data);
00201 memcpy(eth->h_source, net_dev->dev_addr, ETH_ALEN);
00202 }
00203
00204 #ifdef EC_DEBUG_IF
00205 ec_debug_register(&device->dbg, net_dev);
00206 #endif
00207 }
00208
00209
00210
00213 void ec_device_detach(
00214 ec_device_t *device
00215 )
00216 {
00217 unsigned int i;
00218
00219 #ifdef EC_DEBUG_IF
00220 ec_debug_unregister(&device->dbg);
00221 #endif
00222
00223 device->dev = NULL;
00224 device->poll = NULL;
00225 device->module = NULL;
00226 device->open = 0;
00227 device->link_state = 0;
00228
00229 ec_device_clear_stats(device);
00230
00231 for (i = 0; i < EC_TX_RING_SIZE; i++) {
00232 device->tx_skb[i]->dev = NULL;
00233 }
00234 }
00235
00236
00237
00242 int ec_device_open(
00243 ec_device_t *device
00244 )
00245 {
00246 int ret;
00247
00248 if (!device->dev) {
00249 EC_MASTER_ERR(device->master, "No net_device to open!\n");
00250 return -ENODEV;
00251 }
00252
00253 if (device->open) {
00254 EC_MASTER_WARN(device->master, "Device already opened!\n");
00255 return 0;
00256 }
00257
00258 device->link_state = 0;
00259
00260 ec_device_clear_stats(device);
00261
00262 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
00263 ret = device->dev->netdev_ops->ndo_open(device->dev);
00264 #else
00265 ret = device->dev->open(device->dev);
00266 #endif
00267 if (!ret)
00268 device->open = 1;
00269
00270 return ret;
00271 }
00272
00273
00274
00279 int ec_device_close(
00280 ec_device_t *device
00281 )
00282 {
00283 int ret;
00284
00285 if (!device->dev) {
00286 EC_MASTER_ERR(device->master, "No device to close!\n");
00287 return -ENODEV;
00288 }
00289
00290 if (!device->open) {
00291 EC_MASTER_WARN(device->master, "Device already closed!\n");
00292 return 0;
00293 }
00294
00295 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
00296 ret = device->dev->netdev_ops->ndo_stop(device->dev);
00297 #else
00298 ret = device->dev->stop(device->dev);
00299 #endif
00300 if (!ret)
00301 device->open = 0;
00302
00303 return ret;
00304 }
00305
00306
00307
00312 uint8_t *ec_device_tx_data(
00313 ec_device_t *device
00314 )
00315 {
00316
00317
00318
00319 device->tx_ring_index++;
00320 device->tx_ring_index %= EC_TX_RING_SIZE;
00321 return device->tx_skb[device->tx_ring_index]->data + ETH_HLEN;
00322 }
00323
00324
00325
00331 void ec_device_send(
00332 ec_device_t *device,
00333 size_t size
00334 )
00335 {
00336 struct sk_buff *skb = device->tx_skb[device->tx_ring_index];
00337
00338
00339 skb->len = ETH_HLEN + size;
00340
00341 if (unlikely(device->master->debug_level > 1)) {
00342 EC_MASTER_DBG(device->master, 2, "Sending frame:\n");
00343 ec_print_data(skb->data, ETH_HLEN + size);
00344 }
00345
00346
00347 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
00348 if (device->dev->netdev_ops->ndo_start_xmit(skb, device->dev) ==
00349 NETDEV_TX_OK)
00350 #else
00351 if (device->dev->hard_start_xmit(skb, device->dev) == NETDEV_TX_OK)
00352 #endif
00353 {
00354 device->tx_count++;
00355 device->master->device_stats.tx_count++;
00356 device->tx_bytes += ETH_HLEN + size;
00357 device->master->device_stats.tx_bytes += ETH_HLEN + size;
00358 #ifdef EC_DEBUG_IF
00359 ec_debug_send(&device->dbg, skb->data, ETH_HLEN + size);
00360 #endif
00361 #ifdef EC_DEBUG_RING
00362 ec_device_debug_ring_append(
00363 device, TX, skb->data + ETH_HLEN, size);
00364 #endif
00365 } else {
00366 device->tx_errors++;
00367 }
00368 }
00369
00370
00371
00374 void ec_device_clear_stats(
00375 ec_device_t *device
00376 )
00377 {
00378 unsigned int i;
00379
00380
00381 device->tx_count = 0;
00382 device->last_tx_count = 0;
00383 device->rx_count = 0;
00384 device->last_rx_count = 0;
00385 device->tx_bytes = 0;
00386 device->last_tx_bytes = 0;
00387 device->rx_bytes = 0;
00388 device->last_rx_bytes = 0;
00389 device->tx_errors = 0;
00390
00391 for (i = 0; i < EC_RATE_COUNT; i++) {
00392 device->tx_frame_rates[i] = 0;
00393 device->rx_frame_rates[i] = 0;
00394 device->tx_byte_rates[i] = 0;
00395 device->rx_byte_rates[i] = 0;
00396 }
00397 }
00398
00399
00400
00401 #ifdef EC_DEBUG_RING
00402
00404 void ec_device_debug_ring_append(
00405 ec_device_t *device,
00406 ec_debug_frame_dir_t dir,
00407 const void *data,
00408 size_t size
00409 )
00410 {
00411 ec_debug_frame_t *df = &device->debug_frames[device->debug_frame_index];
00412
00413 df->dir = dir;
00414 if (dir == TX) {
00415 do_gettimeofday(&df->t);
00416 }
00417 else {
00418 df->t = device->timeval_poll;
00419 }
00420 memcpy(df->data, data, size);
00421 df->data_size = size;
00422
00423 device->debug_frame_index++;
00424 device->debug_frame_index %= EC_DEBUG_RING_SIZE;
00425 if (unlikely(device->debug_frame_count < EC_DEBUG_RING_SIZE))
00426 device->debug_frame_count++;
00427 }
00428
00429
00430
00433 void ec_device_debug_ring_print(
00434 const ec_device_t *device
00435 )
00436 {
00437 int i;
00438 unsigned int ring_index;
00439 const ec_debug_frame_t *df;
00440 struct timeval t0, diff;
00441
00442
00443 ring_index = (device->debug_frame_index + EC_DEBUG_RING_SIZE - 1)
00444 % EC_DEBUG_RING_SIZE;
00445 t0 = device->debug_frames[ring_index].t;
00446
00447 EC_MASTER_DBG(device->master, 1, "Debug ring %u:\n", ring_index);
00448
00449
00450 ring_index = (device->debug_frame_index + EC_DEBUG_RING_SIZE
00451 - device->debug_frame_count) % EC_DEBUG_RING_SIZE;
00452
00453 for (i = 0; i < device->debug_frame_count; i++) {
00454 df = &device->debug_frames[ring_index];
00455 timersub(&t0, &df->t, &diff);
00456
00457 EC_MASTER_DBG(device->master, 1, "Frame %u, dt=%u.%06u s, %s:\n",
00458 i + 1 - device->debug_frame_count,
00459 (unsigned int) diff.tv_sec,
00460 (unsigned int) diff.tv_usec,
00461 (df->dir == TX) ? "TX" : "RX");
00462 ec_print_data(df->data, df->data_size);
00463
00464 ring_index++;
00465 ring_index %= EC_DEBUG_RING_SIZE;
00466 }
00467 }
00468 #endif
00469
00470
00471
00478 void ec_device_poll(
00479 ec_device_t *device
00480 )
00481 {
00482 #ifdef EC_HAVE_CYCLES
00483 device->cycles_poll = get_cycles();
00484 #endif
00485 device->jiffies_poll = jiffies;
00486 #ifdef EC_DEBUG_RING
00487 do_gettimeofday(&device->timeval_poll);
00488 #endif
00489 device->poll(device->dev);
00490 }
00491
00492
00493
00496 void ec_device_update_stats(
00497 ec_device_t *device
00498 )
00499 {
00500 unsigned int i;
00501
00502 s32 tx_frame_rate = (device->tx_count - device->last_tx_count) * 1000;
00503 s32 rx_frame_rate = (device->rx_count - device->last_rx_count) * 1000;
00504 s32 tx_byte_rate = (device->tx_bytes - device->last_tx_bytes);
00505 s32 rx_byte_rate = (device->rx_bytes - device->last_rx_bytes);
00506
00507
00508
00509
00510
00511 for (i = 0; i < EC_RATE_COUNT; i++) {
00512 s32 n = rate_intervals[i];
00513 device->tx_frame_rates[i] +=
00514 (tx_frame_rate - device->tx_frame_rates[i]) / n;
00515 device->rx_frame_rates[i] +=
00516 (rx_frame_rate - device->rx_frame_rates[i]) / n;
00517 device->tx_byte_rates[i] +=
00518 (tx_byte_rate - device->tx_byte_rates[i]) / n;
00519 device->rx_byte_rates[i] +=
00520 (rx_byte_rate - device->rx_byte_rates[i]) / n;
00521 }
00522
00523 device->last_tx_count = device->tx_count;
00524 device->last_rx_count = device->rx_count;
00525 device->last_tx_bytes = device->tx_bytes;
00526 device->last_rx_bytes = device->rx_bytes;
00527 }
00528
00529
00530
00531
00532
00543 void ecdev_withdraw(ec_device_t *device )
00544 {
00545 ec_master_t *master = device->master;
00546 char dev_str[20], mac_str[20];
00547
00548 ec_mac_print(device->dev->dev_addr, mac_str);
00549
00550 if (device == &master->devices[EC_DEVICE_MAIN]) {
00551 sprintf(dev_str, "main");
00552 } else if (device == &master->devices[EC_DEVICE_BACKUP]) {
00553 sprintf(dev_str, "backup");
00554 } else {
00555 EC_MASTER_WARN(master, "%s() called with unknown device %s!\n",
00556 __func__, mac_str);
00557 sprintf(dev_str, "UNKNOWN");
00558 }
00559
00560 EC_MASTER_INFO(master, "Releasing %s device %s.\n", dev_str, mac_str);
00561
00562 down(&master->device_sem);
00563 ec_device_detach(device);
00564 up(&master->device_sem);
00565 }
00566
00567
00568
00574 int ecdev_open(ec_device_t *device )
00575 {
00576 int ret;
00577 ec_master_t *master = device->master;
00578 unsigned int all_open = 1, dev_idx;
00579
00580 ret = ec_device_open(device);
00581 if (ret) {
00582 EC_MASTER_ERR(master, "Failed to open device!\n");
00583 return ret;
00584 }
00585
00586 for (dev_idx = EC_DEVICE_MAIN;
00587 dev_idx < ec_master_num_devices(device->master); dev_idx++) {
00588 if (!master->devices[dev_idx].open) {
00589 all_open = 0;
00590 break;
00591 }
00592 }
00593
00594 if (all_open) {
00595 ret = ec_master_enter_idle_phase(device->master);
00596 if (ret) {
00597 EC_MASTER_ERR(device->master, "Failed to enter IDLE phase!\n");
00598 return ret;
00599 }
00600 }
00601
00602 return 0;
00603 }
00604
00605
00606
00612 void ecdev_close(ec_device_t *device )
00613 {
00614 ec_master_t *master = device->master;
00615
00616 if (master->phase == EC_IDLE) {
00617 ec_master_leave_idle_phase(master);
00618 }
00619
00620 if (ec_device_close(device)) {
00621 EC_MASTER_WARN(master, "Failed to close device!\n");
00622 }
00623 }
00624
00625
00626
00634 void ecdev_receive(
00635 ec_device_t *device,
00636 const void *data,
00637 size_t size
00638 )
00639 {
00640 const void *ec_data = data + ETH_HLEN;
00641 size_t ec_size = size - ETH_HLEN;
00642
00643 if (unlikely(!data)) {
00644 EC_MASTER_WARN(device->master, "%s() called with NULL data.\n",
00645 __func__);
00646 return;
00647 }
00648
00649 device->rx_count++;
00650 device->master->device_stats.rx_count++;
00651 device->rx_bytes += size;
00652 device->master->device_stats.rx_bytes += size;
00653
00654 if (unlikely(device->master->debug_level > 1)) {
00655 EC_MASTER_DBG(device->master, 2, "Received frame:\n");
00656 ec_print_data(data, size);
00657 }
00658
00659 #ifdef EC_DEBUG_IF
00660 ec_debug_send(&device->dbg, data, size);
00661 #endif
00662 #ifdef EC_DEBUG_RING
00663 ec_device_debug_ring_append(device, RX, ec_data, ec_size);
00664 #endif
00665
00666 ec_master_receive_datagrams(device->master, device, ec_data, ec_size);
00667 }
00668
00669
00670
00678 void ecdev_set_link(
00679 ec_device_t *device,
00680 uint8_t state
00681 )
00682 {
00683 if (unlikely(!device)) {
00684 EC_WARN("ecdev_set_link() called with null device!\n");
00685 return;
00686 }
00687
00688 if (likely(state != device->link_state)) {
00689 device->link_state = state;
00690 EC_MASTER_INFO(device->master,
00691 "Link state of %s changed to %s.\n",
00692 device->dev->name, (state ? "UP" : "DOWN"));
00693 }
00694 }
00695
00696
00697
00704 uint8_t ecdev_get_link(
00705 const ec_device_t *device
00706 )
00707 {
00708 if (unlikely(!device)) {
00709 EC_WARN("ecdev_get_link() called with null device!\n");
00710 return 0;
00711 }
00712
00713 return device->link_state;
00714 }
00715
00716
00717
00720 EXPORT_SYMBOL(ecdev_withdraw);
00721 EXPORT_SYMBOL(ecdev_open);
00722 EXPORT_SYMBOL(ecdev_close);
00723 EXPORT_SYMBOL(ecdev_receive);
00724 EXPORT_SYMBOL(ecdev_get_link);
00725 EXPORT_SYMBOL(ecdev_set_link);
00726
00729