Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

device.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  *  $Id: device.c 682 2006-11-07 12:13:30Z fp $
00004  *
00005  *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
00006  *
00007  *  This file is part of the IgH EtherCAT Master.
00008  *
00009  *  The IgH EtherCAT Master is free software; you can redistribute it
00010  *  and/or modify it under the terms of the GNU General Public License
00011  *  as published by the Free Software Foundation; either version 2 of the
00012  *  License, or (at your option) any later version.
00013  *
00014  *  The IgH EtherCAT Master is distributed in the hope that it will be
00015  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with the IgH EtherCAT Master; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  *  The right to use EtherCAT Technology is granted and comes free of
00024  *  charge under condition of compatibility of product made by
00025  *  Licensee. People intending to distribute/sell products based on the
00026  *  code, have to sign an agreement to guarantee that products using
00027  *  software based on IgH EtherCAT master stay compatible with the actual
00028  *  EtherCAT specification (which are released themselves as an open
00029  *  standard) as the (only) precondition to have the right to use EtherCAT
00030  *  Technology, IP and trade marks.
00031  *
00032  *****************************************************************************/
00033 
00039 /*****************************************************************************/
00040 
00041 #include <linux/module.h>
00042 #include <linux/skbuff.h>
00043 #include <linux/if_ether.h>
00044 #include <linux/netdevice.h>
00045 #include <linux/delay.h>
00046 
00047 #include "device.h"
00048 #include "master.h"
00049 
00050 /*****************************************************************************/
00051 
00057 int ec_device_init(ec_device_t *device, 
00058                    ec_master_t *master, 
00059                    struct net_device *net_dev, 
00060                    ec_isr_t isr, 
00061                    struct module *module 
00062                    )
00063 {
00064     struct ethhdr *eth;
00065 
00066     device->master = master;
00067     device->dev = net_dev;
00068     device->isr = isr;
00069     device->module = module;
00070 
00071     device->open = 0;
00072     device->link_state = 0; // down
00073 
00074 #ifdef EC_DBG_IF
00075     if (ec_debug_init(&device->dbg)) {
00076         EC_ERR("Failed to init debug device!\n");
00077         goto out_return;
00078     }
00079 #endif
00080 
00081     if (!(device->tx_skb = dev_alloc_skb(ETH_FRAME_LEN))) {
00082         EC_ERR("Error allocating device socket buffer!\n");
00083 #ifdef EC_DBG_IF
00084         goto out_debug;
00085 #else
00086         goto out_return;
00087 #endif
00088     }
00089 
00090     device->tx_skb->dev = net_dev;
00091 
00092     // add Ethernet-II-header
00093     skb_reserve(device->tx_skb, ETH_HLEN);
00094     eth = (struct ethhdr *) skb_push(device->tx_skb, ETH_HLEN);
00095     eth->h_proto = htons(0x88A4);
00096     memcpy(eth->h_source, net_dev->dev_addr, net_dev->addr_len);
00097     memset(eth->h_dest, 0xFF, net_dev->addr_len);
00098 
00099     return 0;
00100 
00101 #ifdef EC_DBG_IF
00102  out_debug:
00103     ec_debug_clear(&device->dbg);
00104 #endif
00105  out_return:
00106     return -1;
00107 }
00108 
00109 /*****************************************************************************/
00110 
00115 void ec_device_clear(ec_device_t *device )
00116 {
00117     if (device->open) ec_device_close(device);
00118     if (device->tx_skb) dev_kfree_skb(device->tx_skb);
00119 #ifdef EC_DBG_IF
00120     ec_debug_clear(&device->dbg);
00121 #endif
00122 }
00123 
00124 /*****************************************************************************/
00125 
00131 int ec_device_open(ec_device_t *device )
00132 {
00133     unsigned int i;
00134 
00135     if (!device->dev) {
00136         EC_ERR("No net_device to open!\n");
00137         return -1;
00138     }
00139 
00140     if (device->open) {
00141         EC_WARN("Device already opened!\n");
00142         return 0;
00143     }
00144 
00145     // device could have received frames before
00146     for (i = 0; i < 4; i++) ec_device_call_isr(device);
00147 
00148     device->link_state = 0;
00149 
00150     if (device->dev->open(device->dev) == 0) device->open = 1;
00151 
00152     return device->open ? 0 : -1;
00153 }
00154 
00155 /*****************************************************************************/
00156 
00162 int ec_device_close(ec_device_t *device )
00163 {
00164     if (!device->dev) {
00165         EC_ERR("No device to close!\n");
00166         return -1;
00167     }
00168 
00169     if (!device->open) {
00170         EC_WARN("Device already closed!\n");
00171         return 0;
00172     }
00173 
00174     if (device->dev->stop(device->dev) == 0) device->open = 0;
00175 
00176     return !device->open ? 0 : -1;
00177 }
00178 
00179 /*****************************************************************************/
00180 
00186 uint8_t *ec_device_tx_data(ec_device_t *device )
00187 {
00188     return device->tx_skb->data + ETH_HLEN;
00189 }
00190 
00191 /*****************************************************************************/
00192 
00199 void ec_device_send(ec_device_t *device, 
00200                     size_t size 
00201                     )
00202 {
00203     if (unlikely(!device->link_state)) // Link down
00204         return;
00205 
00206     // set the right length for the data
00207     device->tx_skb->len = ETH_HLEN + size;
00208 
00209     if (unlikely(device->master->debug_level > 1)) {
00210         EC_DBG("sending frame:\n");
00211         ec_print_data(device->tx_skb->data + ETH_HLEN, size);
00212     }
00213 
00214 #ifdef EC_DBG_IF
00215     ec_debug_send(&device->dbg, device->tx_skb->data, ETH_HLEN + size);
00216 #endif
00217 
00218     // start sending
00219     device->dev->hard_start_xmit(device->tx_skb, device->dev);
00220 }
00221 
00222 /*****************************************************************************/
00223 
00231 void ec_device_call_isr(ec_device_t *device )
00232 {
00233     device->cycles_isr = get_cycles();
00234     device->jiffies_isr = jiffies;
00235     if (likely(device->isr)) device->isr(0, device->dev, NULL);
00236 }
00237 
00238 /******************************************************************************
00239  *  Device interface
00240  *****************************************************************************/
00241 
00249 void ecdev_receive(ec_device_t *device, 
00250                    const void *data, 
00251                    size_t size 
00252                    )
00253 {
00254     if (unlikely(device->master->debug_level > 1)) {
00255         EC_DBG("Received frame:\n");
00256         ec_print_data_diff(device->tx_skb->data + ETH_HLEN,
00257                            data + ETH_HLEN, size - ETH_HLEN);
00258     }
00259 
00260 #ifdef EC_DBG_IF
00261     ec_debug_send(&device->dbg, data, size);
00262 #endif
00263 
00264     ec_master_receive_datagrams(device->master,
00265                                 data + ETH_HLEN,
00266                                 size - ETH_HLEN);
00267 }
00268 
00269 /*****************************************************************************/
00270 
00278 void ecdev_link_state(ec_device_t *device, 
00279                       uint8_t state 
00280                       )
00281 {
00282     if (unlikely(!device)) {
00283         EC_WARN("ecdev_link_state: no device!\n");
00284         return;
00285     }
00286 
00287     if (likely(state != device->link_state)) {
00288         device->link_state = state;
00289         EC_INFO("Link state changed to %s.\n", (state ? "UP" : "DOWN"));
00290     }
00291 }
00292 
00293 /*****************************************************************************/
00294 
00297 EXPORT_SYMBOL(ecdev_receive);
00298 EXPORT_SYMBOL(ecdev_link_state);
00299 
00302 /*****************************************************************************/

Generated on Tue Nov 7 15:03:35 2006 for IgH EtherCAT master by  doxygen 1.4.4