1*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 2*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Ported to U-Boot by Christian Pellegrin <chri@ascensit.com> 3*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 4*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Based on sources from the Linux kernel (pcnet_cs.c, 8390.h) and 5*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eCOS(if_dp83902a.c, if_dp83902a.h). Both of these 2 wonderful world 6*2439e4bfSJean-Christophe PLAGNIOL-VILLARD are GPL, so this is, of course, GPL. 7*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 8*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 9*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ========================================================================== 10*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 11*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev/if_dp83902a.c 12*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 13*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Ethernet device driver for NS DP83902a ethernet controller 14*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 15*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ========================================================================== 16*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ####ECOSGPLCOPYRIGHTBEGIN#### 17*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ------------------------------------------- 18*2439e4bfSJean-Christophe PLAGNIOL-VILLARD This file is part of eCos, the Embedded Configurable Operating System. 19*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. 20*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 21*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eCos is free software; you can redistribute it and/or modify it under 22*2439e4bfSJean-Christophe PLAGNIOL-VILLARD the terms of the GNU General Public License as published by the Free 23*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Software Foundation; either version 2 or (at your option) any later version. 24*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 25*2439e4bfSJean-Christophe PLAGNIOL-VILLARD eCos is distributed in the hope that it will be useful, but WITHOUT ANY 26*2439e4bfSJean-Christophe PLAGNIOL-VILLARD WARRANTY; without even the implied warranty of MERCHANTABILITY or 27*2439e4bfSJean-Christophe PLAGNIOL-VILLARD FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 28*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for more details. 29*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 30*2439e4bfSJean-Christophe PLAGNIOL-VILLARD You should have received a copy of the GNU General Public License along 31*2439e4bfSJean-Christophe PLAGNIOL-VILLARD with eCos; if not, write to the Free Software Foundation, Inc., 32*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 33*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 34*2439e4bfSJean-Christophe PLAGNIOL-VILLARD As a special exception, if other files instantiate templates or use macros 35*2439e4bfSJean-Christophe PLAGNIOL-VILLARD or inline functions from this file, or you compile this file and link it 36*2439e4bfSJean-Christophe PLAGNIOL-VILLARD with other works to produce a work based on this file, this file does not 37*2439e4bfSJean-Christophe PLAGNIOL-VILLARD by itself cause the resulting work to be covered by the GNU General Public 38*2439e4bfSJean-Christophe PLAGNIOL-VILLARD License. However the source code for this file must still be made available 39*2439e4bfSJean-Christophe PLAGNIOL-VILLARD in accordance with section (3) of the GNU General Public License. 40*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 41*2439e4bfSJean-Christophe PLAGNIOL-VILLARD This exception does not invalidate any other reasons why a work based on 42*2439e4bfSJean-Christophe PLAGNIOL-VILLARD this file might be covered by the GNU General Public License. 43*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 44*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. 45*2439e4bfSJean-Christophe PLAGNIOL-VILLARD at http://sources.redhat.com/ecos/ecos-license/ 46*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ------------------------------------------- 47*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ####ECOSGPLCOPYRIGHTEND#### 48*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ####BSDCOPYRIGHTBEGIN#### 49*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 50*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ------------------------------------------- 51*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 52*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Portions of this software may have been derived from OpenBSD or other sources, 53*2439e4bfSJean-Christophe PLAGNIOL-VILLARD and are covered by the appropriate copyright disclaimers included herein. 54*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 55*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ------------------------------------------- 56*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 57*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ####BSDCOPYRIGHTEND#### 58*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ========================================================================== 59*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #####DESCRIPTIONBEGIN#### 60*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 61*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Author(s): gthomas 62*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Contributors: gthomas, jskov, rsandifo 63*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Date: 2001-06-13 64*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Purpose: 65*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Description: 66*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 67*2439e4bfSJean-Christophe PLAGNIOL-VILLARD FIXME: Will fail if pinged with large packets (1520 bytes) 68*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Add promisc config 69*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Add SNMP 70*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 71*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ####DESCRIPTIONEND#### 72*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 73*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 74*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ========================================================================== 75*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 76*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 77*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 78*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 79*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <command.h> 80*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h> 81*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <malloc.h> 82*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 83*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DRIVER_NE2000 84*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 85*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* wor around udelay resetting OCR */ 86*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void my_udelay(long us) { 87*2439e4bfSJean-Christophe PLAGNIOL-VILLARD long tmo; 88*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 89*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tmo = get_timer (0) + us * CFG_HZ / 1000000; /* will this be much greater than 0 ? */ 90*2439e4bfSJean-Christophe PLAGNIOL-VILLARD while (get_timer (0) < tmo); 91*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 92*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 93*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define mdelay(n) my_udelay((n)*1000) 94*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 95*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* forward definition of function used for the uboot interface */ 96*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void uboot_push_packet_len(int len); 97*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void uboot_push_tx_done(int key, int val); 98*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 99*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* timeout for tx/rx in s */ 100*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TOUT 5 101*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 102*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define ETHER_ADDR_LEN 6 103*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 104*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 105*2439e4bfSJean-Christophe PLAGNIOL-VILLARD ------------------------------------------------------------------------ 106*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Debugging details 107*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 108*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Set to perms of: 109*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 0 disables all debug output 110*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 1 for process debug output 111*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 2 for added data IO output: get_reg, put_reg 112*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 4 for packet allocation/free output 113*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 8 for only startup status, so we can tell we're installed OK 114*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 115*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*#define DEBUG 0xf*/ 116*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEBUG 0 117*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 118*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 1 119*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEBUG_FUNCTION() do { printf("%s\n", __FUNCTION__); } while (0) 120*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEBUG_LINE() do { printf("%d\n", __LINE__); } while (0) 121*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 122*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEBUG_FUNCTION() do {} while(0) 123*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEBUG_LINE() do {} while(0) 124*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 125*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 126*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "ne2000.h" 127*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 128*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 1 129*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PRINTK(args...) printf(args) 130*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 131*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PRINTK(args...) 132*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 133*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 134*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static dp83902a_priv_data_t nic; /* just one instance of the card supported */ 135*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 136*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static bool 137*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_init(void) 138*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 139*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_priv_data_t *dp = &nic; 140*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8* base; 141*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 142*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 143*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 144*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 145*2439e4bfSJean-Christophe PLAGNIOL-VILLARD base = dp->base; 146*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!base) return false; /* No device found */ 147*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 148*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_LINE(); 149*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 150*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Prepare ESA */ 151*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1); /* Select page 1 */ 152*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Use the address from the serial EEPROM */ 153*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 6; i++) 154*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_P1_PAR0+i, dp->esa[i]); 155*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0); /* Select page 0 */ 156*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 157*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("NE2000 - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n", 158*2439e4bfSJean-Christophe PLAGNIOL-VILLARD "eeprom", 159*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[0], 160*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[1], 161*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[2], 162*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[3], 163*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[4], 164*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[5] ); 165*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 166*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return true; 167*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 168*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 169*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 170*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_stop(void) 171*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 172*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_priv_data_t *dp = &nic; 173*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 *base = dp->base; 174*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 175*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 176*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 177*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */ 178*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, 0xFF); /* Clear any pending interrupts */ 179*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_IMR, 0x00); /* Disable all interrupts */ 180*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 181*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->running = false; 182*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 183*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 184*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 185*2439e4bfSJean-Christophe PLAGNIOL-VILLARD This function is called to "start up" the interface. It may be called 186*2439e4bfSJean-Christophe PLAGNIOL-VILLARD multiple times, even when the hardware is already running. It will be 187*2439e4bfSJean-Christophe PLAGNIOL-VILLARD called whenever something "hardware oriented" changes and should leave 188*2439e4bfSJean-Christophe PLAGNIOL-VILLARD the hardware ready to send/receive packets. 189*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 190*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 191*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start(unsigned char * enaddr) 192*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 193*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_priv_data_t *dp = &nic; 194*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 *base = dp->base; 195*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 196*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 197*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 198*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 199*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */ 200*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_DCR, DP_DCR_INIT); 201*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, 0); /* Remote byte count */ 202*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, 0); 203*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RCR, DP_RCR_MON); /* Accept no packets */ 204*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TCR, DP_TCR_LOCAL); /* Transmitter [virtually] off */ 205*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TPSR, dp->tx_buf1); /* Transmitter start page */ 206*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx1 = dp->tx2 = 0; 207*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_next = dp->tx_buf1; 208*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_started = false; 209*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_PSTART, dp->rx_buf_start); /* Receive ring start page */ 210*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); /* Receive ring boundary */ 211*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_PSTOP, dp->rx_buf_end); /* Receive ring end page */ 212*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->rx_next = dp->rx_buf_start-1; 213*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, 0xFF); /* Clear any pending interrupts */ 214*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_IMR, DP_IMR_All); /* Enable all interrupts */ 215*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1 | DP_CR_STOP); /* Select page 1 */ 216*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_P1_CURP, dp->rx_buf_start); /* Current page - next free page for Rx */ 217*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < ETHER_ADDR_LEN; i++) { 218*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_P1_PAR0+i, enaddr[i]); 219*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 220*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Enable and start device */ 221*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 222*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TCR, DP_TCR_NORMAL); /* Normal transmit operations */ 223*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RCR, DP_RCR_AB); /* Accept broadcast, no errors, no multicast */ 224*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->running = true; 225*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 226*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 227*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 228*2439e4bfSJean-Christophe PLAGNIOL-VILLARD This routine is called to start the transmitter. It is split out from the 229*2439e4bfSJean-Christophe PLAGNIOL-VILLARD data handling routine so it may be called either when data becomes first 230*2439e4bfSJean-Christophe PLAGNIOL-VILLARD available or when an Tx interrupt occurs 231*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 232*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 233*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 234*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start_xmit(int start_page, int len) 235*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 236*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *) &nic; 237*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 *base = dp->base; 238*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 239*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 240*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 241*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 1 242*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("Tx pkt %d len %d\n", start_page, len); 243*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->tx_started) 244*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("TX already started?!?\n"); 245*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 246*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 247*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, (DP_ISR_TxP | DP_ISR_TxE)); 248*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 249*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TBCL, len & 0xFF); 250*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TBCH, len >> 8); 251*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TPSR, start_page); 252*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START); 253*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 254*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_started = true; 255*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 256*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 257*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 258*2439e4bfSJean-Christophe PLAGNIOL-VILLARD This routine is called to send data to the hardware. It is known a-priori 259*2439e4bfSJean-Christophe PLAGNIOL-VILLARD that there is free buffer space (dp->tx_next). 260*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 261*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 262*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_send(unsigned char *data, int total_len, unsigned long key) 263*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 264*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 265*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 *base = dp->base; 266*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int len, start_page, pkt_len, i, isr; 267*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 268*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int dx; 269*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 270*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 271*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 272*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 273*2439e4bfSJean-Christophe PLAGNIOL-VILLARD len = pkt_len = total_len; 274*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (pkt_len < IEEE_8023_MIN_FRAME) pkt_len = IEEE_8023_MIN_FRAME; 275*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 276*2439e4bfSJean-Christophe PLAGNIOL-VILLARD start_page = dp->tx_next; 277*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->tx_next == dp->tx_buf1) { 278*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx1 = start_page; 279*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx1_len = pkt_len; 280*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx1_key = key; 281*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_next = dp->tx_buf2; 282*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 283*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx2 = start_page; 284*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx2_len = pkt_len; 285*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx2_key = key; 286*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_next = dp->tx_buf1; 287*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 288*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 289*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 5 290*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("TX prep page %d len %d\n", start_page, pkt_len); 291*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 292*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 293*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ 294*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 295*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Dummy read. The manual sez something slightly different, */ 296*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* but the code is extended a bit to do what Hitachi's monitor */ 297*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* does (i.e., also read data). */ 298*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 299*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint16 tmp; 300*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int len = 1; 301*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 302*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAL, 0x100-len); 303*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAH, (start_page-1) & 0xff); 304*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, len); 305*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, 0); 306*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START); 307*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN_DATA(dp->data, tmp); 308*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 309*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 310*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA 311*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Stall for a bit before continuing to work around random data */ 312*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* corruption problems on some platforms. */ 313*2439e4bfSJean-Christophe PLAGNIOL-VILLARD CYGACC_CALL_IF_DELAY_US(1); 314*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 315*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 316*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Send data to device buffer(s) */ 317*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAL, 0); 318*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAH, start_page); 319*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, pkt_len & 0xFF); 320*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, pkt_len >> 8); 321*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_WDMA | DP_CR_START); 322*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 323*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Put data into buffer */ 324*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 325*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf(" sg buf %08lx len %08x\n ", (unsigned long) data, len); 326*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dx = 0; 327*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 328*2439e4bfSJean-Christophe PLAGNIOL-VILLARD while (len > 0) { 329*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 330*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf(" %02x", *data); 331*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (0 == (++dx % 16)) printf("\n "); 332*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 333*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT_DATA(dp->data, *data++); 334*2439e4bfSJean-Christophe PLAGNIOL-VILLARD len--; 335*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 336*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 337*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("\n"); 338*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 339*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (total_len < pkt_len) { 340*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 341*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf(" + %d bytes of padding\n", pkt_len - total_len); 342*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 343*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Padding to 802.3 length was required */ 344*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = total_len; i < pkt_len;) { 345*2439e4bfSJean-Christophe PLAGNIOL-VILLARD i++; 346*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT_DATA(dp->data, 0); 347*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 348*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 349*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 350*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA 351*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* After last data write, delay for a bit before accessing the */ 352*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* device again, or we may get random data corruption in the last */ 353*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* datum (on some platforms). */ 354*2439e4bfSJean-Christophe PLAGNIOL-VILLARD CYGACC_CALL_IF_DELAY_US(1); 355*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 356*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 357*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for DMA to complete */ 358*2439e4bfSJean-Christophe PLAGNIOL-VILLARD do { 359*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_ISR, isr); 360*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } while ((isr & DP_ISR_RDC) == 0); 361*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Then disable DMA */ 362*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 363*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 364*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Start transmit if not already going */ 365*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!dp->tx_started) { 366*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (start_page == dp->tx1) { 367*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_int = 1; /* Expecting interrupt from BUF1 */ 368*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 369*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_int = 2; /* Expecting interrupt from BUF2 */ 370*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 371*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start_xmit(start_page, pkt_len); 372*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 373*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 374*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 375*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 376*2439e4bfSJean-Christophe PLAGNIOL-VILLARD This function is called when a packet has been received. It's job is 377*2439e4bfSJean-Christophe PLAGNIOL-VILLARD to prepare to unload the packet from the hardware. Once the length of 378*2439e4bfSJean-Christophe PLAGNIOL-VILLARD the packet is known, the upper layer of the driver can be told. When 379*2439e4bfSJean-Christophe PLAGNIOL-VILLARD the upper layer is ready to unload the packet, the internal function 380*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 'dp83902a_recv' will be called to actually fetch it from the hardware. 381*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 382*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 383*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_RxEvent(void) 384*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 385*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 386*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 *base = dp->base; 387*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char rsr; 388*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char rcv_hdr[4]; 389*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, len, pkt, cur; 390*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 391*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 392*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 393*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_RSR, rsr); 394*2439e4bfSJean-Christophe PLAGNIOL-VILLARD while (true) { 395*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read incoming packet header */ 396*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE1 | DP_CR_NODMA | DP_CR_START); 397*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_P1_CURP, cur); 398*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_P1_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 399*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_BNDRY, pkt); 400*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 401*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pkt += 1; 402*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (pkt == dp->rx_buf_end) 403*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pkt = dp->rx_buf_start; 404*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 405*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (pkt == cur) { 406*2439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 407*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 408*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, sizeof(rcv_hdr)); 409*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, 0); 410*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAL, 0); 411*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAH, pkt); 412*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->rx_next == pkt) { 413*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (cur == dp->rx_buf_start) 414*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); 415*2439e4bfSJean-Christophe PLAGNIOL-VILLARD else 416*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_BNDRY, cur-1); /* Update pointer */ 417*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return; 418*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 419*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->rx_next = pkt; 420*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ 421*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START); 422*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA 423*2439e4bfSJean-Christophe PLAGNIOL-VILLARD CYGACC_CALL_IF_DELAY_US(10); 424*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 425*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 426*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < sizeof(rcv_hdr);) { 427*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN_DATA(dp->data, rcv_hdr[i++]); 428*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 429*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 430*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 5 431*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx hdr %02x %02x %02x %02x\n", 432*2439e4bfSJean-Christophe PLAGNIOL-VILLARD rcv_hdr[0], rcv_hdr[1], rcv_hdr[2], rcv_hdr[3]); 433*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 434*2439e4bfSJean-Christophe PLAGNIOL-VILLARD len = ((rcv_hdr[3] << 8) | rcv_hdr[2]) - sizeof(rcv_hdr); 435*2439e4bfSJean-Christophe PLAGNIOL-VILLARD uboot_push_packet_len(len); 436*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (rcv_hdr[1] == dp->rx_buf_start) 437*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); 438*2439e4bfSJean-Christophe PLAGNIOL-VILLARD else 439*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_BNDRY, rcv_hdr[1]-1); /* Update pointer */ 440*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 441*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 442*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 443*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 444*2439e4bfSJean-Christophe PLAGNIOL-VILLARD This function is called as a result of the "eth_drv_recv()" call above. 445*2439e4bfSJean-Christophe PLAGNIOL-VILLARD It's job is to actually fetch data for a packet from the hardware once 446*2439e4bfSJean-Christophe PLAGNIOL-VILLARD memory buffers have been allocated for the packet. Note that the buffers 447*2439e4bfSJean-Christophe PLAGNIOL-VILLARD may come in pieces, using a scatter-gather list. This allows for more 448*2439e4bfSJean-Christophe PLAGNIOL-VILLARD efficient processing in the upper layers of the stack. 449*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 450*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 451*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_recv(unsigned char *data, int len) 452*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 453*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 454*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 *base = dp->base; 455*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, mlen; 456*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 saved_char = 0; 457*2439e4bfSJean-Christophe PLAGNIOL-VILLARD bool saved; 458*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 459*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int dx; 460*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 461*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 462*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 463*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 464*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 5 465*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("Rx packet %d length %d\n", dp->rx_next, len); 466*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 467*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 468*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read incoming packet data */ 469*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 470*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, len & 0xFF); 471*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, len >> 8); 472*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAL, 4); /* Past header */ 473*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAH, dp->rx_next); 474*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ 475*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START); 476*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA 477*2439e4bfSJean-Christophe PLAGNIOL-VILLARD CYGACC_CALL_IF_DELAY_US(10); 478*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 479*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 480*2439e4bfSJean-Christophe PLAGNIOL-VILLARD saved = false; 481*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 1; i++) { 482*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (data) { 483*2439e4bfSJean-Christophe PLAGNIOL-VILLARD mlen = len; 484*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 485*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf(" sg buf %08lx len %08x \n", (unsigned long) data, mlen); 486*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dx = 0; 487*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 488*2439e4bfSJean-Christophe PLAGNIOL-VILLARD while (0 < mlen) { 489*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Saved byte from previous loop? */ 490*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (saved) { 491*2439e4bfSJean-Christophe PLAGNIOL-VILLARD *data++ = saved_char; 492*2439e4bfSJean-Christophe PLAGNIOL-VILLARD mlen--; 493*2439e4bfSJean-Christophe PLAGNIOL-VILLARD saved = false; 494*2439e4bfSJean-Christophe PLAGNIOL-VILLARD continue; 495*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 496*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 497*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 498*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 tmp; 499*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN_DATA(dp->data, tmp); 500*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 501*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf(" %02x", tmp); 502*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (0 == (++dx % 16)) printf("\n "); 503*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 504*2439e4bfSJean-Christophe PLAGNIOL-VILLARD *data++ = tmp;; 505*2439e4bfSJean-Christophe PLAGNIOL-VILLARD mlen--; 506*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 507*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 508*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 509*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("\n"); 510*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 511*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 512*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 513*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 514*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 515*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 516*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_TxEvent(void) 517*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 518*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 519*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 *base = dp->base; 520*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char tsr; 521*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long key; 522*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 523*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 524*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 525*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_TSR, tsr); 526*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->tx_int == 1) { 527*2439e4bfSJean-Christophe PLAGNIOL-VILLARD key = dp->tx1_key; 528*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx1 = 0; 529*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 530*2439e4bfSJean-Christophe PLAGNIOL-VILLARD key = dp->tx2_key; 531*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx2 = 0; 532*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 533*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Start next packet if one is ready */ 534*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_started = false; 535*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->tx1) { 536*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start_xmit(dp->tx1, dp->tx1_len); 537*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_int = 1; 538*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } else if (dp->tx2) { 539*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start_xmit(dp->tx2, dp->tx2_len); 540*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_int = 2; 541*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 542*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_int = 0; 543*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 544*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Tell higher level we sent this packet */ 545*2439e4bfSJean-Christophe PLAGNIOL-VILLARD uboot_push_tx_done(key, 0); 546*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 547*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 548*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the tally counters to clear them. Called in response to a CNT */ 549*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* interrupt. */ 550*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 551*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_ClearCounters(void) 552*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 553*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 554*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 *base = dp->base; 555*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 cnt1, cnt2, cnt3; 556*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 557*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_FER, cnt1); 558*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_CER, cnt2); 559*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_MISSED, cnt3); 560*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_CNT); 561*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 562*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 563*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Deal with an overflow condition. This code follows the procedure set */ 564*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* out in section 7.0 of the datasheet. */ 565*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 566*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_Overflow(void) 567*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 568*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)&nic; 569*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 *base = dp->base; 570*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 isr; 571*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 572*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Issue a stop command and wait 1.6ms for it to complete. */ 573*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_STOP | DP_CR_NODMA); 574*2439e4bfSJean-Christophe PLAGNIOL-VILLARD CYGACC_CALL_IF_DELAY_US(1600); 575*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 576*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear the remote byte counter registers. */ 577*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, 0); 578*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, 0); 579*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 580*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Enter loopback mode while we clear the buffer. */ 581*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TCR, DP_TCR_LOCAL); 582*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_START | DP_CR_NODMA); 583*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 584*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read in as many packets as we can and acknowledge any and receive */ 585*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* interrupts. Since the buffer has overflowed, a receive event of */ 586*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* some kind will have occured. */ 587*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_RxEvent(); 588*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_RxP|DP_ISR_RxE); 589*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 590*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear the overflow condition and leave loopback mode. */ 591*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_OFLW); 592*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TCR, DP_TCR_NORMAL); 593*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 594*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If a transmit command was issued, but no transmit event has occured, */ 595*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* restart it here. */ 596*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_ISR, isr); 597*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->tx_started && !(isr & (DP_ISR_TxP|DP_ISR_TxE))) { 598*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START); 599*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 600*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 601*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 602*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 603*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_poll(void) 604*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 605*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 606*2439e4bfSJean-Christophe PLAGNIOL-VILLARD cyg_uint8 *base = dp->base; 607*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char isr; 608*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 609*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0 | DP_CR_START); 610*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_ISR, isr); 611*2439e4bfSJean-Christophe PLAGNIOL-VILLARD while (0 != isr) { 612*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The CNT interrupt triggers when the MSB of one of the error */ 613*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* counters is set. We don't much care about these counters, but */ 614*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* we should read their values to reset them. */ 615*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (isr & DP_ISR_CNT) { 616*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_ClearCounters(); 617*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 618*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check for overflow. It's a special case, since there's a */ 619*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* particular procedure that must be followed to get back into */ 620*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* a running state.a */ 621*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (isr & DP_ISR_OFLW) { 622*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_Overflow(); 623*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 624*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Other kinds of interrupts can be acknowledged simply by */ 625*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* clearing the relevant bits of the ISR. Do that now, then */ 626*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* handle the interrupts we care about. */ 627*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, isr); /* Clear set bits */ 628*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!dp->running) break; /* Is this necessary? */ 629*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check for tx_started on TX event since these may happen */ 630*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* spuriously it seems. */ 631*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (isr & (DP_ISR_TxP|DP_ISR_TxE) && dp->tx_started) { 632*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_TxEvent(); 633*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 634*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (isr & (DP_ISR_RxP|DP_ISR_RxE)) { 635*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_RxEvent(); 636*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 637*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 638*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_ISR, isr); 639*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 640*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 641*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 642*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* find prom (taken from pc_net_cs.c from Linux) */ 643*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 644*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "8390.h" 645*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 646*2439e4bfSJean-Christophe PLAGNIOL-VILLARD typedef struct hw_info_t { 647*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u_int offset; 648*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u_char a0, a1, a2; 649*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u_int flags; 650*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } hw_info_t; 651*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 652*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DELAY_OUTPUT 0x01 653*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define HAS_MISC_REG 0x02 654*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define USE_BIG_BUF 0x04 655*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define HAS_IBM_MISC 0x08 656*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define IS_DL10019 0x10 657*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define IS_DL10022 0x20 658*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define HAS_MII 0x40 659*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define USE_SHMEM 0x80 /* autodetected */ 660*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 661*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define AM79C9XX_HOME_PHY 0x00006B90 /* HomePNA PHY */ 662*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define AM79C9XX_ETH_PHY 0x00006B70 /* 10baseT PHY */ 663*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_PHYID_REV_MASK 0xfffffff0 664*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_PHYID_REG1 0x02 665*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_PHYID_REG2 0x03 666*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 667*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static hw_info_t hw_info[] = { 668*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT }, 669*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 }, 670*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 }, 671*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94, 672*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DELAY_OUTPUT | HAS_IBM_MISC }, 673*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 }, 674*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 }, 675*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 }, 676*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 }, 677*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 }, 678*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 }, 679*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48, 680*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 681*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 }, 682*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 }, 683*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a, 684*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 685*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac, 686*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 687*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29, 688*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 689*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a, 690*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 691*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac, 692*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 693*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87, 694*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 695*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17, 696*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 697*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8, 698*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 699*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0, 700*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 701*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0, 702*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 703*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 }, 704*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 }, 705*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0, 706*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 707*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f, 708*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 709*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 }, 710*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 }, 711*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 }, 712*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 }, 713*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65, 714*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 715*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45, 716*2439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 717*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 }, 718*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 }, 719*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 }, 720*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b, 721*2439e4bfSJean-Christophe PLAGNIOL-VILLARD DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF }, 722*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 }, 723*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 }, 724*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 }, 725*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 }, 726*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }, 727*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Qemu */ 0x0, 0x52, 0x54, 0x00, 0 } 728*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 729*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 730*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t)) 731*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 732*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static hw_info_t default_info = { 0, 0, 0, 0, 0 }; 733*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 734*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char dev_addr[6]; 735*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 736*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PCNET_CMD 0x00 737*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PCNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */ 738*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PCNET_RESET 0x1f /* Issue a read to reset, a write to clear. */ 739*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PCNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */ 740*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 741*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long nic_base; 742*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 743*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void pcnet_reset_8390(void) 744*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 745*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, r; 746*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 747*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("nic base is %lx\n", nic_base); 748*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 749*2439e4bfSJean-Christophe PLAGNIOL-VILLARD n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); 750*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD)); 751*2439e4bfSJean-Christophe PLAGNIOL-VILLARD n2k_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, E8390_CMD); 752*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD)); 753*2439e4bfSJean-Christophe PLAGNIOL-VILLARD n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); 754*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("cmd (at %lx) is %x\n", nic_base+ E8390_CMD, n2k_inb(E8390_CMD)); 755*2439e4bfSJean-Christophe PLAGNIOL-VILLARD n2k_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); 756*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 757*2439e4bfSJean-Christophe PLAGNIOL-VILLARD n2k_outb(n2k_inb(PCNET_RESET), PCNET_RESET); 758*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 759*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 100; i++) { 760*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((r = (n2k_inb(EN0_ISR) & ENISR_RESET)) != 0) 761*2439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 762*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("got %x in reset\n", r); 763*2439e4bfSJean-Christophe PLAGNIOL-VILLARD my_udelay(100); 764*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 765*2439e4bfSJean-Christophe PLAGNIOL-VILLARD n2k_outb(ENISR_RESET, EN0_ISR); /* Ack intr. */ 766*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 767*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i == 100) 768*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("pcnet_reset_8390() did not complete.\n"); 769*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } /* pcnet_reset_8390 */ 770*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 771*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static hw_info_t * get_prom(void ) { 772*2439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char prom[32]; 773*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, j; 774*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct { 775*2439e4bfSJean-Christophe PLAGNIOL-VILLARD u_char value, offset; 776*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } program_seq[] = { 777*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ 778*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */ 779*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {0x00, EN0_RCNTLO}, /* Clear the count regs. */ 780*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {0x00, EN0_RCNTHI}, 781*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {0x00, EN0_IMR}, /* Mask completion irq. */ 782*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {0xFF, EN0_ISR}, 783*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ 784*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ 785*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {32, EN0_RCNTLO}, 786*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {0x00, EN0_RCNTHI}, 787*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ 788*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {0x00, EN0_RSARHI}, 789*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {E8390_RREAD+E8390_START, E8390_CMD}, 790*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 791*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 792*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("trying to get MAC via prom reading\n"); 793*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 794*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pcnet_reset_8390(); 795*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 796*2439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(10); 797*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 798*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) 799*2439e4bfSJean-Christophe PLAGNIOL-VILLARD n2k_outb(program_seq[i].value, program_seq[i].offset); 800*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 801*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("PROM:"); 802*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 32; i++) { 803*2439e4bfSJean-Christophe PLAGNIOL-VILLARD prom[i] = n2k_inb(PCNET_DATAPORT); 804*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK(" %02x", prom[i]); 805*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 806*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("\n"); 807*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < NR_INFO; i++) { 808*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((prom[0] == hw_info[i].a0) && 809*2439e4bfSJean-Christophe PLAGNIOL-VILLARD (prom[2] == hw_info[i].a1) && 810*2439e4bfSJean-Christophe PLAGNIOL-VILLARD (prom[4] == hw_info[i].a2)) { 811*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("matched board %d\n", i); 812*2439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 813*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 814*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 815*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) { 816*2439e4bfSJean-Christophe PLAGNIOL-VILLARD for (j = 0; j < 6; j++) 817*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev_addr[j] = prom[j<<1]; 818*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("on exit i is %d/%ld\n", i, NR_INFO); 819*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("MAC address is %02x:%02x:%02x:%02x:%02x:%02x\n", 820*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev_addr[0],dev_addr[1],dev_addr[2],dev_addr[3],dev_addr[4],dev_addr[5]); 821*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return (i < NR_INFO) ? hw_info+i : &default_info; 822*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 823*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return NULL; 824*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 825*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 826*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* U-boot specific routines */ 827*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 828*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 829*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned char *pbuf = NULL; 830*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 831*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int pkey = -1; 832*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int initialized=0; 833*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 834*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void uboot_push_packet_len(int len) { 835*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("pushed len = %d\n", len); 836*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (len>=2000) { 837*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("NE2000: packet too big\n"); 838*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return; 839*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 840*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_recv(&pbuf[0], len); 841*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 842*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*Just pass it to the upper layer*/ 843*2439e4bfSJean-Christophe PLAGNIOL-VILLARD NetReceive(&pbuf[0], len); 844*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 845*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 846*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void uboot_push_tx_done(int key, int val) { 847*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("pushed key = %d\n", key); 848*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pkey = key; 849*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 850*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 851*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_init(bd_t *bd) { 852*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static hw_info_t * r; 853*2439e4bfSJean-Christophe PLAGNIOL-VILLARD char ethaddr[20]; 854*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 855*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("### eth_init\n"); 856*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 857*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!pbuf) { 858*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pbuf = malloc(2000); 859*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!pbuf) { 860*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("Cannot allocate rx buffer\n"); 861*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 862*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 863*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 864*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 865*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DRIVER_NE2000_CCR 866*2439e4bfSJean-Christophe PLAGNIOL-VILLARD { 867*2439e4bfSJean-Christophe PLAGNIOL-VILLARD volatile unsigned char *p = (volatile unsigned char *) CONFIG_DRIVER_NE2000_CCR; 868*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 869*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("CCR before is %x\n", *p); 870*2439e4bfSJean-Christophe PLAGNIOL-VILLARD *p = CONFIG_DRIVER_NE2000_VAL; 871*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("CCR after is %x\n", *p); 872*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 873*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 874*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 875*2439e4bfSJean-Christophe PLAGNIOL-VILLARD nic_base = CONFIG_DRIVER_NE2000_BASE; 876*2439e4bfSJean-Christophe PLAGNIOL-VILLARD nic.base = (cyg_uint8 *) CONFIG_DRIVER_NE2000_BASE; 877*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 878*2439e4bfSJean-Christophe PLAGNIOL-VILLARD r = get_prom(); 879*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!r) 880*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 881*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 882*2439e4bfSJean-Christophe PLAGNIOL-VILLARD sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", 883*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev_addr[0], dev_addr[1], 884*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev_addr[2], dev_addr[3], 885*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dev_addr[4], dev_addr[5]) ; 886*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("Set environment from HW MAC addr = \"%s\"\n", ethaddr); 887*2439e4bfSJean-Christophe PLAGNIOL-VILLARD setenv ("ethaddr", ethaddr); 888*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 889*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 890*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DP_DATA 0x10 891*2439e4bfSJean-Christophe PLAGNIOL-VILLARD nic.data = nic.base + DP_DATA; 892*2439e4bfSJean-Christophe PLAGNIOL-VILLARD nic.tx_buf1 = 0x40; 893*2439e4bfSJean-Christophe PLAGNIOL-VILLARD nic.tx_buf2 = 0x48; 894*2439e4bfSJean-Christophe PLAGNIOL-VILLARD nic.rx_buf_start = 0x50; 895*2439e4bfSJean-Christophe PLAGNIOL-VILLARD nic.rx_buf_end = 0x80; 896*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 897*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp83902a_init() == false) 898*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 899*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start(dev_addr); 900*2439e4bfSJean-Christophe PLAGNIOL-VILLARD initialized=1; 901*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 902*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 903*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 904*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void eth_halt() { 905*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 906*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("### eth_halt\n"); 907*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if(initialized) 908*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_stop(); 909*2439e4bfSJean-Christophe PLAGNIOL-VILLARD initialized=0; 910*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 911*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 912*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_rx() { 913*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_poll(); 914*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1; 915*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 916*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 917*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_send(volatile void *packet, int length) { 918*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int tmo; 919*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 920*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("### eth_send\n"); 921*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 922*2439e4bfSJean-Christophe PLAGNIOL-VILLARD pkey = -1; 923*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 924*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_send((unsigned char *) packet, length, 666); 925*2439e4bfSJean-Christophe PLAGNIOL-VILLARD tmo = get_timer (0) + TOUT * CFG_HZ; 926*2439e4bfSJean-Christophe PLAGNIOL-VILLARD while(1) { 927*2439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_poll(); 928*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (pkey != -1) { 929*2439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("Packet sucesfully sent\n"); 930*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 931*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 932*2439e4bfSJean-Christophe PLAGNIOL-VILLARD if (get_timer (0) >= tmo) { 933*2439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("transmission error (timoeut)\n"); 934*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 935*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 936*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 937*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 938*2439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 939*2439e4bfSJean-Christophe PLAGNIOL-VILLARD } 940*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 941