⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ecos_usbeth.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================////      ecos_usbeth.c////      Linux device driver for eCos-based USB ethernet peripherals.////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####                                             //// Author(s):           bartv// Contributors:        bartv// Date:                2000-11-12////####DESCRIPTIONEND####//==========================================================================#include <linux/module.h>#include <linux/init.h>#include <linux/usb.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#ifdef MODULEMODULE_AUTHOR("Bart Veer <bartv@redhat.com>");MODULE_DESCRIPTION("USB ethernet driver for eCos-based peripherals");#endif// This array identifies specific implementations of eCos USB-ethernet// devices. All implementations should add their vendor and device// details.typedef struct ecos_usbeth_impl {    const char* name;    __u16       vendor;    __u16       id;} ecos_usbeth_impl;const static ecos_usbeth_impl ecos_usbeth_implementations[] = {    { "eCos ether",     0x4242, 0x4242 },    { (const char*) 0,       0,      0 }};// Constants. These have to be kept in sync with the target-side// code.#define ECOS_USBETH_MAXTU                           1516#define ECOS_USBETH_MAX_CONTROL_TU                     8#define ECOS_USBETH_CONTROL_GET_MAC_ADDRESS         0x01#define ECOS_USBETH_CONTROL_SET_PROMISCUOUS_MODE    0x02// The main data structure. It keeps track of both the USB// and network side of things, and provides buffers for// the various operations.//// NOTE: currently this driver only supports a single// plugged-in device. Theoretically multiple eCos-based// USB ethernet devices could be plugged in to a single// host and each one would require an ecos_usbeth// structure.typedef struct ecos_usbeth {    spinlock_t                  usb_lock;    int                         target_promiscuous;    struct usb_device*          usb_dev;    struct net_device*          net_dev;    struct net_device_stats     stats;    struct urb                  rx_urb;    struct urb                  tx_urb;    unsigned char               rx_buffer[ECOS_USBETH_MAXTU];    unsigned char               tx_buffer[ECOS_USBETH_MAXTU];} ecos_usbeth;// open()// Invoked by the TCP/IP stack when the interface is brought up.// This just starts a receive operation.static intecos_usbeth_open(struct net_device* net){    ecos_usbeth* usbeth = (ecos_usbeth*) net->priv;    int          res;    netif_start_queue(net);    res = usb_submit_urb(&(usbeth->rx_urb));    if (0 != res) {        printk("ecos_usbeth: failed to start USB receives, %d\n", res);    }    MOD_INC_USE_COUNT;    return 0;}// close()// Invoked by the TCP/IP stack when the interface is taken down.// Any active USB operations need to be cancelled. During// a disconnect this may get called twice, once for the// disconnect and once for the network interface being// brought down.static intecos_usbeth_close(struct net_device* net){    ecos_usbeth* usbeth = (ecos_usbeth*) net->priv;    if (0 != netif_running(net)) {        netif_stop_queue(net);        net->start = 0;        if (-EINPROGRESS == usbeth->rx_urb.status) {            usb_unlink_urb(&(usbeth->rx_urb));        }        if (-EINPROGRESS == usbeth->tx_urb.status) {            usb_unlink_urb(&(usbeth->tx_urb));        }        MOD_DEC_USE_COUNT;    }        return 0;}// Reception.// probe() fills in an rx_urb. When the net device is brought up// the urb is activated, and this callback gets run for incoming// data.static voidecos_usbeth_rx_callback(struct urb* urb){    ecos_usbeth*        usbeth  = (ecos_usbeth*) urb->context;    struct net_device*  net     = usbeth->net_dev;    struct sk_buff*     skb;    int                 len;    int                 res;    if (0 != urb->status) {        // This happens numerous times during a disconnect. Do not        // issue a warning, but do clear the status field or things        // get confused when resubmitting.        //        // Some host hardware does not distinguish between CRC errors        // (very rare) and timeouts (perfectly normal). Do not        // increment the error count if it might have been a timeout.        if (USB_ST_CRC != urb->status) {            usbeth->stats.rx_errors++;        }        urb->status = 0;    } else if (2 > urb->actual_length) {        // With some hardware the target may have to send a bogus        // first packet. Just ignore those.    } else {        len = usbeth->rx_buffer[0] + (usbeth->rx_buffer[1] << 8);        if (len > (urb->actual_length - 2)) {            usbeth->stats.rx_errors++;            usbeth->stats.rx_length_errors++;            printk("ecos_usbeth: warning, packet size mismatch, got %d bytes, expected %d\n",                   urb->actual_length, len);        } else {            skb = dev_alloc_skb(len + 2);            if ((struct sk_buff*)0 == skb) {                printk("ecos_usbeth: failed to alloc skb, dropping packet\n");                usbeth->stats.rx_dropped++;            } else {#if 0                {                    int i;                    printk("--------------------------------------------------------------\n");                    printk("ecos_usbeth RX: total size %d\n", len);                    for (i = 0; (i < len) && (i < 128); i+= 8) {                        printk("rx  %x %x %x %x %x %x %x %x\n",                               usbeth->rx_buffer[i+0], usbeth->rx_buffer[i+1], usbeth->rx_buffer[i+2], usbeth->rx_buffer[i+3],                               usbeth->rx_buffer[i+4], usbeth->rx_buffer[i+5], usbeth->rx_buffer[i+6], usbeth->rx_buffer[i+7]);                    }                    printk("--------------------------------------------------------------\n");                }#endif                skb->dev        = net;                eth_copy_and_sum(skb, &(usbeth->rx_buffer[2]), len, 0);                skb_put(skb, len);                skb->protocol   = eth_type_trans(skb, net);                netif_rx(skb);                usbeth->stats.rx_packets++;                usbeth->stats.rx_bytes += len;            }        }    }    if (0 != netif_running(net)) {        res = usb_submit_urb(&(usbeth->rx_urb));        if (0 != res) {            printk("ecos_usbeth: failed to restart USB receives after packet, %d\n", res);        }    }}// start_tx().// Transmit a single packet. The relevant USB protocol requires a// 2-byte length field at the start, the incoming buffer has no space// for this, and the URB API does not support any form of// scatter/gather. Therefore unfortunately the whole packet has to be// copied. The callback function is specified when the URB is filled// in by probe().static voidecos_usbeth_tx_callback(struct urb* urb){    ecos_usbeth* usbeth = (ecos_usbeth*) urb->context;    spin_lock(&usbeth->usb_lock);    if (0 != netif_running(usbeth->net_dev)) {        netif_wake_queue(usbeth->net_dev);    }    spin_unlock(&usbeth->usb_lock);}static intecos_usbeth_start_tx(struct sk_buff* skb, struct net_device* net){    ecos_usbeth* usbeth = (ecos_usbeth*) net->priv;    int          res;    if ((skb->len + 2) > ECOS_USBETH_MAXTU) {        printk("ecos_usbeth: oversized packet of %d bytes\n", skb->len);        return 0;    }    if (netif_queue_stopped(net)) {        // Another transmission already in progress.        // USB bulk operations should complete within 5s.        int current_delay = jiffies - net->trans_start;        if (current_delay < (5 * HZ)) {            return 1;        } else {            // There has been a timeout. Discard this message.            //printk("transmission timed out\n");            usbeth->stats.tx_errors++;            dev_kfree_skb(skb);            return 0;        }    }    spin_lock(&usbeth->usb_lock);    usbeth->tx_buffer[0]        = skb->len & 0x00FF;    usbeth->tx_buffer[1]        = (skb->len >> 8) & 0x00FF;    memcpy(&(usbeth->tx_buffer[2]), skb->data, skb->len);    usbeth->tx_urb.transfer_buffer_length = skb->len + 2;    // Some targets are unhappy about receiving 0-length packets, not    // just sending them.    if (0 == (usbeth->tx_urb.transfer_buffer_length % 64)) {        usbeth->tx_urb.transfer_buffer_length++;    }#if 0    {        int i;        printk("--------------------------------------------------------------\n");        printk("ecos_usbeth start_tx: len %d\n", skb->len + 2);        for (i = 0; (i < (skb->len + 2)) && (i < 128); i+= 8) {            printk("tx  %x %x %x %x %x %x %x %x\n",                   usbeth->tx_buffer[i], usbeth->tx_buffer[i+1], usbeth->tx_buffer[i+2], usbeth->tx_buffer[i+3],

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -