diff options
Diffstat (limited to 'cfe/cfe/usb/usbeth.c')
-rw-r--r-- | cfe/cfe/usb/usbeth.c | 850 |
1 files changed, 850 insertions, 0 deletions
diff --git a/cfe/cfe/usb/usbeth.c b/cfe/cfe/usb/usbeth.c new file mode 100644 index 0000000..bc5aeb0 --- /dev/null +++ b/cfe/cfe/usb/usbeth.c @@ -0,0 +1,850 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * USB Ethernet File: usbeth.c + * + * Driver for USB Ethernet devices. + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + +/* ********************************************************************* + * USB-Ethernet driver - CFE Network Layer Interfaces + * NOTE: Some of the device setup for the Admtek & Realtek devices + * was derived from reverse engineering! So these interfaces + * assume proper device operation. + ********************************************************************* */ + +#include "lib_types.h" +#include "lib_malloc.h" +#include "lib_string.h" +#include "lib_printf.h" + +#include "cfe_iocb.h" +#include "cfe_ioctl.h" +#include "cfe_timer.h" +#include "cfe_device.h" +#include "cfe_devfuncs.h" +#include "cfe_error.h" + +#include "usbd.h" +#include "usbeth.h" + +#if 0 +#define USBETH_TRACE( x, y ... ) xprintf( x, ##y ) +#else +#define USBETH_TRACE( x, y ... ) +#endif + +#define FAIL -1 + +static int Dev_cnt = 0; + + +/****************************************************************************** + Debug functions +******************************************************************************/ + +//#define DATA_DUMP +#ifdef DATA_DUMP +static void hexdump( unsigned char * src, int srclen, int rowlen, int rows ) +{ + unsigned char * rowptr; + unsigned char * srcstp; + unsigned char * byteptr; + + srcstp = src + srclen; + + for( rowptr = src; rowptr < src + rowlen * rows; rowptr += rowlen ) { + for( byteptr = rowptr; byteptr < rowptr + rowlen && byteptr < srcstp; byteptr++ ) { + xprintf( "%2X ", *byteptr ); + } + xprintf( "\n" ); + } + xprintf( "\n" ); +} +#endif + + +/* ********************************************************************* + * Interface functions for USB-Ethernet adapters + ********************************************************************* */ + +enum { PEGASUS, PEGASUS_II, NETMATE, REALTEK }; +enum { VEN_NONE, _3_COM, LINKSYS, LINKSYS_10, LINKSYS_100, + CATC_NM, BELKIN_CATC, LINKSYS_100M }; +static char * VENDOR_NAMES[] = +{ + "?", "3-COM", "LinkSys", "LinkSys-10TX", "LinkSys-100TX", + "CATC-Netmate", "Belkin/CATC", "Linksys-100M", "Yikes!" +}; + +typedef struct usbeth_softc_s +{ + usbdev_t *dev; + int bulk_inpipe; + int bulk_outpipe; + int dev_id; + int ven_code; + int embed_tx_len; + uint8_t mac_addr[6]; + usbreq_t *rx_ur; + uint8_t rxbuf[1600]; //artbitrary but enough for ethernet packet +} usbeth_softc_t; + + +/* ************************************** + * CATC I/F Functions + ************************************** */ + +#if 0 +static int catc_get_reg( usbdev_t *dev, int16_t reg, uint8_t *val ) +{ + return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_IN), + CATC_GET_REG, 0, reg, val, 1 ); +} +#endif + +static int catc_set_reg( usbdev_t *dev, int16_t reg, int16_t val ) +{ + return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_OUT), + CATC_SET_REG, val, reg, NULL, 0 ); +} + +static int catc_set_mem( usbdev_t *dev, int16_t addr, + uint8_t *data, int16_t len ) +{ + return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_OUT), + CATC_SET_MEM, 0, addr, data, len ); +} + +static int catc_get_mac_addr( usbdev_t *dev, uint8_t *mac_addr ) +{ + int status; + + status = usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_IN), + CATC_GET_MAC_ADDR, 0, 0, mac_addr, 6 ); + return( status ); +} + +static void catc_init_device( usbeth_softc_t * softc ) +{ + usbdev_t *dev = softc->dev; + unsigned char *mcast_tbl; + + usb_std_request( dev, (USBREQ_TYPE_STD | USBREQ_REC_INTERFACE), + USB_REQUEST_SET_INTERFACE, + 1, //alt setting 1 + 0, NULL, 0 ); + + catc_set_reg(dev, CATC_TX_BUF_CNT_REG, 0x04 ); + catc_set_reg(dev, CATC_RX_BUF_CNT_REG, 0x10 ); + catc_set_reg(dev, CATC_ADV_OP_MODES_REG, 0x01 ); + catc_set_reg(dev, CATC_LED_CTRL_REG, 0x08 ); + + /* Enable broadcast rx via bit in mutlicast table */ + mcast_tbl = KMALLOC(64, 0); + memset( mcast_tbl, 0, 64 ); + mcast_tbl[31] = 0x80; //i.e. broadcast bit + catc_set_mem( dev, CATC_MCAST_TBL_ADDR, mcast_tbl, 64 ); + KFREE(mcast_tbl); + + //Read the adapter's MAC addr + catc_get_mac_addr( dev, softc->mac_addr ); +} + +static void catc_close_device( usbdev_t *dev ) +{ + // Now disable adapter from receiving packets + catc_set_reg( dev, CATC_ETH_CTRL_REG, 0 ); +} + +static void catc_open_device( usbeth_softc_t * softc ) +{ + int i; + + for(i = 0; i < 6; ++i) + catc_set_reg( softc->dev, (CATC_ETH_ADDR_0_REG - i), softc->mac_addr[i] ); + + // Now enable adapter to receive packets + catc_set_reg( softc->dev, CATC_ETH_CTRL_REG, 0x09 ); +} + +/* ************************************** + * PEGASUS I/F Functions + ************************************** */ + +static int peg_get_reg( usbdev_t *dev, int16_t reg, uint8_t *val, int16_t len ) +{ + return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_IN), + PEG_GET_REG, 0, reg, val, len ); +} + +static int peg_set_reg( usbdev_t *dev, int16_t reg, int16_t val ) +{ + unsigned char data = (uint8_t) val & 0xff; + + return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_OUT), + PEG_SET_REG, val, reg, &data, 1 ); +} + +static int peg_set_regs( usbdev_t *dev, int16_t reg, int8_t *vals, int16_t len ) +{ + return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_OUT), + PEG_SET_REG, 0, reg, vals, len ); +} + +static int peg_get_eep_word( usbdev_t *dev, int16_t ofs, uint8_t *val ) +{ + int status=0, tries=20; + uint8_t data[2]; + + if( peg_set_reg( dev, PEG_EEPROM_CTL_REG, 0 ) == FAIL ) + return FAIL; + if( peg_set_reg( dev, PEG_EEPROM_OFS_REG, ofs ) == FAIL ) + return FAIL; + if( peg_set_reg( dev, PEG_EEPROM_CTL_REG, 0x02 ) == FAIL ) //read + return FAIL; + while( --tries ) + { + if( peg_get_reg( dev, PEG_EEPROM_CTL_REG, data, 1 ) == FAIL ) + return FAIL; + if( data[0] & 0x04 ) + break; //eeprom data ready + } + if( !tries ) + { + xprintf( "Pegasus Eeprom read failed!\n" ); + return FAIL; + } + if( peg_get_reg( dev, PEG_EEPROM_DATA_REG, data, 2 ) == FAIL ) + return FAIL; + val[0] = data[0]; + val[1] = data[1]; + + return( status ); +} + +static int peg_get_mac_addr( usbdev_t *dev, uint8_t *mac_addr ) +{ + int i, status; + + for( i = 0; i < 3; ++i ) + { + status = peg_get_eep_word( dev, i, &mac_addr[i*2] ); + } + return( status ); +} + +static void peg_init_phy( usbdev_t *dev ) +{ //needed for earlier versions (before Rev B) of the USB-100TX adapters + static uint8_t phy_magic_wr[] = { 0, 4, 0, 0x1b }; + static uint8_t read_status[] = { 0, 0, 0, 1 }; + uint8_t data[4]; + + //reset the MAC ans set up GPIOs + peg_set_reg( dev, PEG_ETH_CTL1_REG, 0x08 ); + peg_get_reg( dev, PEG_ETH_CTL1_REG, data, 1 ); + + //do following steps to enable link activitiy LED + peg_set_reg( dev, PEG_GPIO1_REG, 0x26 ); + peg_set_reg( dev, PEG_GPIO0_REG, 0x24 ); + peg_set_reg( dev, PEG_GPIO0_REG, 0x26 ); + + //do following set of steps to enable LINK LED + memcpy( data, phy_magic_wr, 4 ); + peg_set_regs( dev, PEG_PHY_ADDR_REG, data, 4); //set up for magic word + peg_set_reg( dev, PEG_PHY_CTRL_REG, (0x1b|PHY_WRITE) ); + peg_get_reg( dev, PEG_PHY_CTRL_REG, data, 1 ); //read status of write + memcpy( data, read_status, 4 ); + peg_set_regs( dev, PEG_PHY_ADDR_REG, data, 4); //set up for phy status reg + peg_set_reg( dev, PEG_PHY_CTRL_REG, (1|PHY_READ) ); + peg_get_reg( dev, PEG_PHY_CTRL_REG, data, 1 ); //read status of read + peg_get_reg( dev, PEG_PHY_DATA_REG, data, 2 ); //read status regs +} + +static void peg_init_device( usbeth_softc_t * softc ) +{ + usbdev_t *dev = softc->dev; + + if( softc->dev_id == PEGASUS_II ) + peg_set_reg( dev, PEG_INT_PHY_REG, 0x02 ); //enable internal PHY + else + peg_init_phy( dev ); + + //Read the adapter's MAC addr + peg_get_mac_addr( dev, softc->mac_addr ); +} + +static void peg_close_device( usbdev_t *dev ) +{ + //Now disable adapter from receiving or transmitting packets + peg_set_reg( dev, PEG_ETH_CTL1_REG, 0 ); +} + +static void peg_open_device( usbeth_softc_t * softc ) +{ + usbdev_t *dev = softc->dev; + + //Now setup adapter's receiver with MAC address + peg_set_regs( dev, PEG_MAC_ADDR_0_REG, softc->mac_addr, 6 ); + + //Now enable adapter to receive and transmit packets + peg_set_reg( dev, PEG_ETH_CTL0_REG, 0xc1 ); + peg_set_reg( dev, PEG_ETH_CTL1_REG, 0x30 ); +} + +/* ************************************** + * REALTEK I/F Functions + ************************************** */ + +// +// ********** NOT FULLY WORKING YET!!!!!!!!!! *************** +// + +static int rtek_get_reg( usbdev_t *dev, int16_t reg, uint8_t *val, int16_t len ) +{ + return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_IN), + RTEK_REG_ACCESS, reg, 0, val, len ); +} + +static int rtek_set_reg( usbdev_t *dev, int16_t reg, int16_t val ) +{ + unsigned char data = (uint8_t) val & 0xff; + + return usb_std_request( dev, (USBREQ_TYPE_VENDOR | USBREQ_DIR_OUT), + RTEK_REG_ACCESS, reg, 0, &data, 1 ); +} + +static int rtek_get_mac_addr( usbdev_t *dev, uint8_t *mac_addr ) +{ + int status; + + status = rtek_get_reg( dev, RTEK_MAC_REG, mac_addr, 6 ); + + return( status ); +} + +static void rtek_init_device( usbeth_softc_t * softc ) +{ + int i; + usbdev_t *dev = softc->dev; + uint8_t val; + + //Reset the adapter + rtek_set_reg( dev, RTEK_CMD_REG, RTEK_RESET ); + for( i = 0; i < 10; ++i ) + { + rtek_get_reg( dev, RTEK_CMD_REG, &val, 1 ); + if( !(val & RTEK_RESET) ) + break; + usb_delay_ms( NULL, 1 ); + } + + //autoload the internal registers + rtek_set_reg( dev, RTEK_CMD_REG, RTEK_AUTOLOAD ); + for( i = 0; i < 50; ++i ) + { + rtek_get_reg( dev, RTEK_CMD_REG, &val, 1 ); + if( !(val & RTEK_AUTOLOAD) ) + break; + usb_delay_ms( NULL, 1 ); + } + + //Read the adapter's MAC addr + rtek_get_mac_addr( dev, softc->mac_addr ); +} + +static void rtek_close_device( usbdev_t *dev ) +{ + //Now disable adapter from receiving or transmitting packets + rtek_set_reg( dev, RTEK_CMD_REG, 0 ); +} + +static void rtek_open_device( usbeth_softc_t * softc ) +{ + //accept broadcast & own packets + rtek_set_reg( softc->dev, RTEK_RXCFG_REG, 0x0c ); + + //Now enable adapter to receive and transmit packets + rtek_set_reg( softc->dev, RTEK_CMD_REG, 0x0c ); +} + +//*********************** USB-ETH I/F Functions **************************** + +static const int ID_TBL[] = +{ + 0x0506, 0x4601, PEGASUS_II, _3_COM, //3-Com + 0x066b, 0x2202, PEGASUS_II, LINKSYS_10, //LinkSys + 0x066b, 0x2203, PEGASUS, LINKSYS_100, + 0x066b, 0x2204, PEGASUS, LINKSYS_100, + 0x066b, 0x2206, PEGASUS, LINKSYS, + 0x066b, 0x400b, PEGASUS_II, LINKSYS_10, + 0x066b, 0x200c, PEGASUS_II, LINKSYS_10, + 0x0bda, 0x8150, REALTEK, LINKSYS_100M, + 0x0423, 0x000a, NETMATE, CATC_NM, //CATC (Netmate I) + 0x0423, 0x000c, NETMATE, BELKIN_CATC, //Belkin & CATC (Netmate II) + -1 +}; + +static int usbeth_init_device( usbeth_softc_t * softc ) +{ + int i; + usb_device_descr_t dev_desc; + uint16_t vendor_id, device_id; + const int *ptr=ID_TBL; + + //find out which device is connected + usb_get_device_descriptor( softc->dev, &dev_desc, 0 ); + vendor_id = (dev_desc.idVendorHigh << 8) + dev_desc.idVendorLow; + device_id = (dev_desc.idProductHigh << 8) + dev_desc.idProductLow; + xprintf( "USB device: vendor id %04x, device id %04x\n", + vendor_id, device_id ); + + while( *ptr != -1 ) + { + if( (vendor_id == ptr[0]) && (device_id == ptr[1]) ) + { + softc->dev_id = ptr[2]; + softc->ven_code = ptr[3]; + break; + } + ptr += 4; + } + if( *ptr == -1 ) + { + xprintf( "Unrecognized USB-Ethernet device\n" ); + return -1; + } + + //init the adapter + if( softc->dev_id == NETMATE ) + { + catc_init_device( softc ); + softc->embed_tx_len = 1; + } + else + { + if( softc->dev_id == REALTEK ) + { + rtek_init_device( softc ); + softc->embed_tx_len = 0; + } + else + { + peg_init_device( softc ); + softc->embed_tx_len = 1; + } + } + + //display adapter info + xprintf( "%s USB-Ethernet Adapter (", VENDOR_NAMES[softc->ven_code] ); + for( i = 0; i < 6; ++i ) + xprintf( "%02x%s", softc->mac_addr[i], (i == 5) ? ")\n" : ":" ); + + return 0; +} + +static int usbeth_get_dev_addr( usbeth_softc_t * softc, uint8_t *mac_addr ) +{ + memcpy( mac_addr, softc->mac_addr, 6 ); + return 0; +} + +static void usbeth_queue_rx( usbeth_softc_t * softc ) +{ + softc->rx_ur = usb_make_request(softc->dev, softc->bulk_inpipe, + softc->rxbuf, sizeof(softc->rxbuf), + (UR_FLAG_IN | UR_FLAG_SHORTOK)); + usb_queue_request(softc->rx_ur); +} + +static void usbeth_close_device( usbeth_softc_t * softc ) +{ + if( softc->dev_id == NETMATE ) + catc_close_device( softc->dev ); + else if( softc->dev_id == REALTEK ) + rtek_close_device( softc->dev ); + else + peg_close_device( softc->dev ); +} + +static void usbeth_open_device( usbeth_softc_t * softc ) +{ + if( softc->dev_id == NETMATE ) + catc_open_device( softc ); + else if( softc->dev_id == REALTEK ) + rtek_open_device( softc ); + else + peg_open_device( softc ); + + //kick start the receive + usbeth_queue_rx( softc ); +} + +static int usbeth_data_rx( usbeth_softc_t * softc ) +{ + usb_poll(softc->dev->ud_bus); + return( !softc->rx_ur->ur_inprogress ); +} + +static int usbeth_get_eth_frame( usbeth_softc_t * softc, unsigned char * buf ) +{ + int len = 0; + + if( !softc->rx_ur->ur_inprogress ) + { + len = softc->rx_ur->ur_xferred; + memcpy( buf, softc->rxbuf, len ); + usb_free_request(softc->rx_ur); + usbeth_queue_rx( softc ); + } + else + xprintf( "Bulk data is not available yet!\n" ); + + return( len ); +} + +static int usbeth_send_eth_frame( usbeth_softc_t * softc, unsigned char * buf, int len ) +{ + usbreq_t *ur; + int txlen = len; + unsigned char * txbuf; + + if(softc->embed_tx_len) + { + txbuf = KMALLOC((len+2), 0); + txbuf[0] = txlen & 0xff; + txbuf[1] = (txlen >> 8) & 0xff; //1st two bytes...little endian + memcpy( &txbuf[2], buf, txlen ); + txlen += 2; + } + else + { + if( softc->dev_id == REALTEK ) + { + //Now for some Realtek chip workarounds + if( txlen < 60 ) //some strange limitation + txlen = 60; + else if( !(txlen % 64) ) //to handle module 64 packets + ++txlen; + } + txbuf = KMALLOC(txlen, 0); + memcpy( txbuf, buf, txlen ); + } + ur = usb_make_request(softc->dev, softc->bulk_outpipe, + txbuf, txlen, UR_FLAG_OUT); + usb_sync_request(ur); + usb_free_request(ur); + KFREE(txbuf); + + return( len ); +} + + +/* ********************************************************************* + * CFE-USB interfaces + ********************************************************************* */ + +/* ********************************************************************* + * usbeth_attach(dev,drv) + * + * This routine is called when the bus scan stuff finds a usb-ethernet + * device. We finish up the initialization by configuring the + * device and allocating our softc here. + * + * Input parameters: + * dev - usb device, in the "addressed" state. + * drv - the driver table entry that matched + * + * Return value: + * 0 + ********************************************************************* */ + +const cfe_driver_t usbethdrv; //forward declaration + +static int usbeth_attach(usbdev_t *dev,usb_driver_t *drv) +{ + usb_config_descr_t *cfgdscr = dev->ud_cfgdescr; + usb_endpoint_descr_t *epdscr; + usb_endpoint_descr_t *indscr = NULL; + usb_endpoint_descr_t *outdscr = NULL; + usb_interface_descr_t *ifdscr; + usbeth_softc_t *softc; + int idx; + + dev->ud_drv = drv; + + softc = (usbeth_softc_t *) KMALLOC( sizeof(usbeth_softc_t), 0 ); + if( softc == NULL ) + { + xprintf( "Failed to allocate softc memory.\n" ); + return -1; + } + memset( softc, 0, sizeof(usbeth_softc_t) ); + dev->ud_private = softc; + softc->dev = dev; + + ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0); + if (ifdscr == NULL) + { + xprintf("USBETH: ERROR...no interace descriptor\n"); + return -1; + } + + + for (idx = 0; idx < 2; idx++) + { + epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,idx); + if (USB_ENDPOINT_DIR_OUT(epdscr->bEndpointAddress)) + outdscr = epdscr; + else + indscr = epdscr; + } + + if (!indscr || !outdscr) + { + /* + * Could not get descriptors, something is very wrong. + * Leave device addressed but not configured. + */ + xprintf("USBETH: ERROR...no endpoint descriptors\n"); + return -1; + } + + /* + * Choose the standard configuration. + */ + + usb_set_configuration(dev,cfgdscr->bConfigurationValue); + + // Quit if not able to initialize the device + if (usbeth_init_device(softc) < 0) + return -1; + + /* + * Open the pipes. + */ + + softc->bulk_inpipe = usb_open_pipe(dev,indscr); + softc->bulk_outpipe = usb_open_pipe(dev,outdscr); + + //Now attach this device as a CFE Ethernet device + cfe_attach( (cfe_driver_t *) &usbethdrv, softc, NULL, + usbethdrv.drv_description ); + + ++Dev_cnt; + + return 0; +} + +/* ********************************************************************* + * usbeth_detach(dev) + * + * This routine is called when the bus scanner notices that + * this device has been removed from the system. We should + * do any cleanup that is required. The pending requests + * will be cancelled automagically. + * + * Input parameters: + * dev - usb device + * + * Return value: + * 0 + ********************************************************************* */ + +static int usbeth_detach(usbdev_t *dev) +{ + usbeth_softc_t *softc = (usbeth_softc_t *) dev->ud_private; + + --Dev_cnt; + KFREE(softc); + + //*** SHOULD DETACH THE ETHERNET DEVICE TOO...LATER + + return 0; +} + +// CFE USB device interface structure +usb_driver_t usbeth_driver = +{ + "Ethernet Device", + usbeth_attach, + usbeth_detach +}; + + + +/* ********************************************************************* + * CFE-Ethernet device interfaces + ********************************************************************* */ + + +static int usbeth_ether_open(cfe_devctx_t *ctx) +{ + if( !Dev_cnt ) + return CFE_ERR_NOTREADY; + + USBETH_TRACE( "%s called.\n", __FUNCTION__ ); + usbeth_open_device( (usbeth_softc_t *) ctx->dev_softc ); + + return 0; +} + +static int usbeth_ether_read( cfe_devctx_t * ctx, iocb_buffer_t * buffer ) +{ + if( !Dev_cnt ) + return CFE_ERR_NOTREADY; + + buffer->buf_retlen = usbeth_get_eth_frame( (usbeth_softc_t *)ctx->dev_softc, + buffer->buf_ptr ); + +#ifdef DATA_DUMP + xprintf( "Incoming packet :\n" ); + hexdump( buffer->buf_ptr, buffer->buf_retlen, 16, + buffer->buf_retlen / 16 + 1 ); +#endif + + return 0; +} + + +static int usbeth_ether_inpstat( cfe_devctx_t * ctx, iocb_inpstat_t * inpstat ) +{ + if( !Dev_cnt ) + return CFE_ERR_NOTREADY; + + inpstat->inp_status = usbeth_data_rx( (usbeth_softc_t *) ctx->dev_softc ); + + return 0; +} + + +static int usbeth_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + if( !Dev_cnt ) + return CFE_ERR_NOTREADY; + + // Block until hw notifies you data is sent. + usbeth_send_eth_frame( (usbeth_softc_t *) ctx->dev_softc, buffer->buf_ptr, + buffer->buf_length ); + + return 0; +} + + +static int usbeth_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) +{ + int retval = 0; + + if( !Dev_cnt ) + return CFE_ERR_NOTREADY; + + switch( (int)buffer->buf_ioctlcmd ) { + case IOCTL_ETHER_GETHWADDR: + USBETH_TRACE( "IOCTL_ETHER_GETHWADDR called.\n" ); + usbeth_get_dev_addr( (usbeth_softc_t *) ctx->dev_softc, + buffer->buf_ptr ); + break; + case IOCTL_ETHER_SETHWADDR: + xprintf( "IOCTL_ETHER_SETHWADDR not implemented.\n" ); + break; +#if 0 + case IOCTL_ETHER_GETSPEED: + xprintf( "GETSPEED not implemented.\n" ); + retval = -1; + break; + case IOCTL_ETHER_SETSPEED: + xprintf( "SETSPEED not implemented.\n" ); + retval = -1; + break; + case IOCTL_ETHER_GETLINK: + xprintf( "GETLINK not implemented.\n" ); + retval = -1; + break; + case IOCTL_ETHER_GETLOOPBACK: + xprintf( "GETLOOPBACK not implemented.\n" ); + retval = -1; + break; + case IOCTL_ETHER_SETLOOPBACK: + xprintf( "SETLOOPBACK not implemented.\n" ); + retval = -1; + break; +#endif + default: + xprintf( "Invalid IOCTL to usbeth_ether_ioctl.\n" ); + retval = -1; + } + + return retval; +} + + +static int usbeth_ether_close(cfe_devctx_t *ctx) +{ + if( !Dev_cnt ) + return CFE_ERR_NOTREADY; + + USBETH_TRACE( "%s called.\n", __FUNCTION__ ); + usbeth_close_device( (usbeth_softc_t *) ctx->dev_softc ); + + return 0; +} + + +// CFE ethernet device interface structures +const static cfe_devdisp_t usbeth_ether_dispatch = +{ + usbeth_ether_open, + usbeth_ether_read, + usbeth_ether_inpstat, + usbeth_ether_write, + usbeth_ether_ioctl, + usbeth_ether_close, + NULL, + NULL +}; + +const cfe_driver_t usbethdrv = +{ + "USB-Ethernet Device", + "eth", + CFE_DEV_NETWORK, + &usbeth_ether_dispatch, + NULL, //probe...not needed +}; + |