12439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 22439e4bfSJean-Christophe PLAGNIOL-VILLARD Ported to U-Boot by Christian Pellegrin <chri@ascensit.com> 32439e4bfSJean-Christophe PLAGNIOL-VILLARD 42439e4bfSJean-Christophe PLAGNIOL-VILLARD Based on sources from the Linux kernel (pcnet_cs.c, 8390.h) and 52439e4bfSJean-Christophe PLAGNIOL-VILLARD eCOS(if_dp83902a.c, if_dp83902a.h). Both of these 2 wonderful world 62439e4bfSJean-Christophe PLAGNIOL-VILLARD are GPL, so this is, of course, GPL. 72439e4bfSJean-Christophe PLAGNIOL-VILLARD 82439e4bfSJean-Christophe PLAGNIOL-VILLARD 92439e4bfSJean-Christophe PLAGNIOL-VILLARD ========================================================================== 102439e4bfSJean-Christophe PLAGNIOL-VILLARD 112439e4bfSJean-Christophe PLAGNIOL-VILLARD dev/if_dp83902a.c 122439e4bfSJean-Christophe PLAGNIOL-VILLARD 132439e4bfSJean-Christophe PLAGNIOL-VILLARD Ethernet device driver for NS DP83902a ethernet controller 142439e4bfSJean-Christophe PLAGNIOL-VILLARD 152439e4bfSJean-Christophe PLAGNIOL-VILLARD ========================================================================== 162439e4bfSJean-Christophe PLAGNIOL-VILLARD ####ECOSGPLCOPYRIGHTBEGIN#### 172439e4bfSJean-Christophe PLAGNIOL-VILLARD ------------------------------------------- 182439e4bfSJean-Christophe PLAGNIOL-VILLARD This file is part of eCos, the Embedded Configurable Operating System. 192439e4bfSJean-Christophe PLAGNIOL-VILLARD Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. 202439e4bfSJean-Christophe PLAGNIOL-VILLARD 212439e4bfSJean-Christophe PLAGNIOL-VILLARD eCos is free software; you can redistribute it and/or modify it under 222439e4bfSJean-Christophe PLAGNIOL-VILLARD the terms of the GNU General Public License as published by the Free 232439e4bfSJean-Christophe PLAGNIOL-VILLARD Software Foundation; either version 2 or (at your option) any later version. 242439e4bfSJean-Christophe PLAGNIOL-VILLARD 252439e4bfSJean-Christophe PLAGNIOL-VILLARD eCos is distributed in the hope that it will be useful, but WITHOUT ANY 262439e4bfSJean-Christophe PLAGNIOL-VILLARD WARRANTY; without even the implied warranty of MERCHANTABILITY or 272439e4bfSJean-Christophe PLAGNIOL-VILLARD FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 282439e4bfSJean-Christophe PLAGNIOL-VILLARD for more details. 292439e4bfSJean-Christophe PLAGNIOL-VILLARD 302439e4bfSJean-Christophe PLAGNIOL-VILLARD You should have received a copy of the GNU General Public License along 312439e4bfSJean-Christophe PLAGNIOL-VILLARD with eCos; if not, write to the Free Software Foundation, Inc., 322439e4bfSJean-Christophe PLAGNIOL-VILLARD 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 332439e4bfSJean-Christophe PLAGNIOL-VILLARD 342439e4bfSJean-Christophe PLAGNIOL-VILLARD As a special exception, if other files instantiate templates or use macros 352439e4bfSJean-Christophe PLAGNIOL-VILLARD or inline functions from this file, or you compile this file and link it 362439e4bfSJean-Christophe PLAGNIOL-VILLARD with other works to produce a work based on this file, this file does not 372439e4bfSJean-Christophe PLAGNIOL-VILLARD by itself cause the resulting work to be covered by the GNU General Public 382439e4bfSJean-Christophe PLAGNIOL-VILLARD License. However the source code for this file must still be made available 392439e4bfSJean-Christophe PLAGNIOL-VILLARD in accordance with section (3) of the GNU General Public License. 402439e4bfSJean-Christophe PLAGNIOL-VILLARD 412439e4bfSJean-Christophe PLAGNIOL-VILLARD This exception does not invalidate any other reasons why a work based on 422439e4bfSJean-Christophe PLAGNIOL-VILLARD this file might be covered by the GNU General Public License. 432439e4bfSJean-Christophe PLAGNIOL-VILLARD 442439e4bfSJean-Christophe PLAGNIOL-VILLARD Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. 452439e4bfSJean-Christophe PLAGNIOL-VILLARD at http://sources.redhat.com/ecos/ecos-license/ 462439e4bfSJean-Christophe PLAGNIOL-VILLARD ------------------------------------------- 472439e4bfSJean-Christophe PLAGNIOL-VILLARD ####ECOSGPLCOPYRIGHTEND#### 482439e4bfSJean-Christophe PLAGNIOL-VILLARD ####BSDCOPYRIGHTBEGIN#### 492439e4bfSJean-Christophe PLAGNIOL-VILLARD 502439e4bfSJean-Christophe PLAGNIOL-VILLARD ------------------------------------------- 512439e4bfSJean-Christophe PLAGNIOL-VILLARD 522439e4bfSJean-Christophe PLAGNIOL-VILLARD Portions of this software may have been derived from OpenBSD or other sources, 532439e4bfSJean-Christophe PLAGNIOL-VILLARD and are covered by the appropriate copyright disclaimers included herein. 542439e4bfSJean-Christophe PLAGNIOL-VILLARD 552439e4bfSJean-Christophe PLAGNIOL-VILLARD ------------------------------------------- 562439e4bfSJean-Christophe PLAGNIOL-VILLARD 572439e4bfSJean-Christophe PLAGNIOL-VILLARD ####BSDCOPYRIGHTEND#### 582439e4bfSJean-Christophe PLAGNIOL-VILLARD ========================================================================== 592439e4bfSJean-Christophe PLAGNIOL-VILLARD #####DESCRIPTIONBEGIN#### 602439e4bfSJean-Christophe PLAGNIOL-VILLARD 612439e4bfSJean-Christophe PLAGNIOL-VILLARD Author(s): gthomas 622439e4bfSJean-Christophe PLAGNIOL-VILLARD Contributors: gthomas, jskov, rsandifo 632439e4bfSJean-Christophe PLAGNIOL-VILLARD Date: 2001-06-13 642439e4bfSJean-Christophe PLAGNIOL-VILLARD Purpose: 652439e4bfSJean-Christophe PLAGNIOL-VILLARD Description: 662439e4bfSJean-Christophe PLAGNIOL-VILLARD 672439e4bfSJean-Christophe PLAGNIOL-VILLARD FIXME: Will fail if pinged with large packets (1520 bytes) 682439e4bfSJean-Christophe PLAGNIOL-VILLARD Add promisc config 692439e4bfSJean-Christophe PLAGNIOL-VILLARD Add SNMP 702439e4bfSJean-Christophe PLAGNIOL-VILLARD 712439e4bfSJean-Christophe PLAGNIOL-VILLARD ####DESCRIPTIONEND#### 722439e4bfSJean-Christophe PLAGNIOL-VILLARD 732439e4bfSJean-Christophe PLAGNIOL-VILLARD 742439e4bfSJean-Christophe PLAGNIOL-VILLARD ========================================================================== 752439e4bfSJean-Christophe PLAGNIOL-VILLARD 762439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 772439e4bfSJean-Christophe PLAGNIOL-VILLARD 782439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 792439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <command.h> 802439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h> 812439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <malloc.h> 822439e4bfSJean-Christophe PLAGNIOL-VILLARD 832439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DRIVER_NE2000 842439e4bfSJean-Christophe PLAGNIOL-VILLARD 85*e710185aSgoda.yusuke #define mdelay(n) udelay((n)*1000) 862439e4bfSJean-Christophe PLAGNIOL-VILLARD /* forward definition of function used for the uboot interface */ 872439e4bfSJean-Christophe PLAGNIOL-VILLARD void uboot_push_packet_len(int len); 882439e4bfSJean-Christophe PLAGNIOL-VILLARD void uboot_push_tx_done(int key, int val); 892439e4bfSJean-Christophe PLAGNIOL-VILLARD 902439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 912439e4bfSJean-Christophe PLAGNIOL-VILLARD ------------------------------------------------------------------------ 922439e4bfSJean-Christophe PLAGNIOL-VILLARD Debugging details 932439e4bfSJean-Christophe PLAGNIOL-VILLARD 942439e4bfSJean-Christophe PLAGNIOL-VILLARD Set to perms of: 952439e4bfSJean-Christophe PLAGNIOL-VILLARD 0 disables all debug output 962439e4bfSJean-Christophe PLAGNIOL-VILLARD 1 for process debug output 972439e4bfSJean-Christophe PLAGNIOL-VILLARD 2 for added data IO output: get_reg, put_reg 982439e4bfSJean-Christophe PLAGNIOL-VILLARD 4 for packet allocation/free output 992439e4bfSJean-Christophe PLAGNIOL-VILLARD 8 for only startup status, so we can tell we're installed OK 1002439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1012439e4bfSJean-Christophe PLAGNIOL-VILLARD /*#define DEBUG 0xf*/ 1022439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEBUG 0 1032439e4bfSJean-Christophe PLAGNIOL-VILLARD 1042439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 1 1052439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEBUG_FUNCTION() do { printf("%s\n", __FUNCTION__); } while (0) 1062439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEBUG_LINE() do { printf("%d\n", __LINE__); } while (0) 107*e710185aSgoda.yusuke #define PRINTK(args...) printf(args) 1082439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 1092439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEBUG_FUNCTION() do {} while(0) 1102439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEBUG_LINE() do {} while(0) 1112439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PRINTK(args...) 1122439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 1132439e4bfSJean-Christophe PLAGNIOL-VILLARD 114*e710185aSgoda.yusuke /* NE2000 base header file */ 115*e710185aSgoda.yusuke #include "ne2000_base.h" 116*e710185aSgoda.yusuke 117*e710185aSgoda.yusuke /* Basic NE2000 chip support */ 118*e710185aSgoda.yusuke #include "ne2000.h" 119*e710185aSgoda.yusuke 1202439e4bfSJean-Christophe PLAGNIOL-VILLARD static dp83902a_priv_data_t nic; /* just one instance of the card supported */ 1212439e4bfSJean-Christophe PLAGNIOL-VILLARD 1222439e4bfSJean-Christophe PLAGNIOL-VILLARD static bool 1232439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_init(void) 1242439e4bfSJean-Christophe PLAGNIOL-VILLARD { 1252439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_priv_data_t *dp = &nic; 126*e710185aSgoda.yusuke u8* base; 1272439e4bfSJean-Christophe PLAGNIOL-VILLARD 1282439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 1292439e4bfSJean-Christophe PLAGNIOL-VILLARD 1302439e4bfSJean-Christophe PLAGNIOL-VILLARD base = dp->base; 1312439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!base) return false; /* No device found */ 1322439e4bfSJean-Christophe PLAGNIOL-VILLARD 1332439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_LINE(); 1342439e4bfSJean-Christophe PLAGNIOL-VILLARD 135*e710185aSgoda.yusuke #if defined(NE2000_BASIC_INIT) 1362439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Prepare ESA */ 1372439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1); /* Select page 1 */ 1382439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Use the address from the serial EEPROM */ 1392439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 6; i++) 1402439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_P1_PAR0+i, dp->esa[i]); 1412439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0); /* Select page 0 */ 1422439e4bfSJean-Christophe PLAGNIOL-VILLARD 1432439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("NE2000 - %s ESA: %02x:%02x:%02x:%02x:%02x:%02x\n", 1442439e4bfSJean-Christophe PLAGNIOL-VILLARD "eeprom", 1452439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[0], 1462439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[1], 1472439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[2], 1482439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[3], 1492439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[4], 1502439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->esa[5] ); 1512439e4bfSJean-Christophe PLAGNIOL-VILLARD 152*e710185aSgoda.yusuke #endif /* NE2000_BASIC_INIT */ 1532439e4bfSJean-Christophe PLAGNIOL-VILLARD return true; 1542439e4bfSJean-Christophe PLAGNIOL-VILLARD } 1552439e4bfSJean-Christophe PLAGNIOL-VILLARD 1562439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 1572439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_stop(void) 1582439e4bfSJean-Christophe PLAGNIOL-VILLARD { 1592439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_priv_data_t *dp = &nic; 160*e710185aSgoda.yusuke u8 *base = dp->base; 1612439e4bfSJean-Christophe PLAGNIOL-VILLARD 1622439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 1632439e4bfSJean-Christophe PLAGNIOL-VILLARD 1642439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */ 1652439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, 0xFF); /* Clear any pending interrupts */ 1662439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_IMR, 0x00); /* Disable all interrupts */ 1672439e4bfSJean-Christophe PLAGNIOL-VILLARD 1682439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->running = false; 1692439e4bfSJean-Christophe PLAGNIOL-VILLARD } 1702439e4bfSJean-Christophe PLAGNIOL-VILLARD 1712439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 1722439e4bfSJean-Christophe PLAGNIOL-VILLARD This function is called to "start up" the interface. It may be called 1732439e4bfSJean-Christophe PLAGNIOL-VILLARD multiple times, even when the hardware is already running. It will be 1742439e4bfSJean-Christophe PLAGNIOL-VILLARD called whenever something "hardware oriented" changes and should leave 1752439e4bfSJean-Christophe PLAGNIOL-VILLARD the hardware ready to send/receive packets. 1762439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1772439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 178*e710185aSgoda.yusuke dp83902a_start(u8 * enaddr) 1792439e4bfSJean-Christophe PLAGNIOL-VILLARD { 1802439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_priv_data_t *dp = &nic; 181*e710185aSgoda.yusuke u8 *base = dp->base; 1822439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 1832439e4bfSJean-Christophe PLAGNIOL-VILLARD 1842439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 1852439e4bfSJean-Christophe PLAGNIOL-VILLARD 1862439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_STOP); /* Brutal */ 1872439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_DCR, DP_DCR_INIT); 1882439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, 0); /* Remote byte count */ 1892439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, 0); 1902439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RCR, DP_RCR_MON); /* Accept no packets */ 1912439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TCR, DP_TCR_LOCAL); /* Transmitter [virtually] off */ 1922439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TPSR, dp->tx_buf1); /* Transmitter start page */ 1932439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx1 = dp->tx2 = 0; 1942439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_next = dp->tx_buf1; 1952439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_started = false; 196*e710185aSgoda.yusuke dp->running = true; 1972439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_PSTART, dp->rx_buf_start); /* Receive ring start page */ 1982439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); /* Receive ring boundary */ 1992439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_PSTOP, dp->rx_buf_end); /* Receive ring end page */ 2002439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->rx_next = dp->rx_buf_start-1; 201*e710185aSgoda.yusuke dp->running = true; 2022439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, 0xFF); /* Clear any pending interrupts */ 2032439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_IMR, DP_IMR_All); /* Enable all interrupts */ 2042439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1 | DP_CR_STOP); /* Select page 1 */ 2052439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_P1_CURP, dp->rx_buf_start); /* Current page - next free page for Rx */ 206*e710185aSgoda.yusuke dp->running = true; 2072439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < ETHER_ADDR_LEN; i++) { 208*e710185aSgoda.yusuke /* FIXME */ 209*e710185aSgoda.yusuke //*((vu_short*)( base + ((DP_P1_PAR0 + i) * 2) + 0x1400)) = enaddr[i]; 2102439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_P1_PAR0+i, enaddr[i]); 2112439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2122439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Enable and start device */ 2132439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 2142439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TCR, DP_TCR_NORMAL); /* Normal transmit operations */ 2152439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RCR, DP_RCR_AB); /* Accept broadcast, no errors, no multicast */ 2162439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->running = true; 217*e710185aSgoda.yusuke 2182439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2192439e4bfSJean-Christophe PLAGNIOL-VILLARD 2202439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 2212439e4bfSJean-Christophe PLAGNIOL-VILLARD This routine is called to start the transmitter. It is split out from the 2222439e4bfSJean-Christophe PLAGNIOL-VILLARD data handling routine so it may be called either when data becomes first 2232439e4bfSJean-Christophe PLAGNIOL-VILLARD available or when an Tx interrupt occurs 2242439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 2252439e4bfSJean-Christophe PLAGNIOL-VILLARD 2262439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 2272439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start_xmit(int start_page, int len) 2282439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2292439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_priv_data_t *dp = (dp83902a_priv_data_t *) &nic; 230*e710185aSgoda.yusuke u8 *base = dp->base; 2312439e4bfSJean-Christophe PLAGNIOL-VILLARD 2322439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 2332439e4bfSJean-Christophe PLAGNIOL-VILLARD 2342439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 1 2352439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("Tx pkt %d len %d\n", start_page, len); 2362439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->tx_started) 2372439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("TX already started?!?\n"); 2382439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 2392439e4bfSJean-Christophe PLAGNIOL-VILLARD 2402439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, (DP_ISR_TxP | DP_ISR_TxE)); 2412439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 2422439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TBCL, len & 0xFF); 2432439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TBCH, len >> 8); 2442439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TPSR, start_page); 2452439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START); 2462439e4bfSJean-Christophe PLAGNIOL-VILLARD 2472439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_started = true; 2482439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2492439e4bfSJean-Christophe PLAGNIOL-VILLARD 2502439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 2512439e4bfSJean-Christophe PLAGNIOL-VILLARD This routine is called to send data to the hardware. It is known a-priori 2522439e4bfSJean-Christophe PLAGNIOL-VILLARD that there is free buffer space (dp->tx_next). 2532439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 2542439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 255*e710185aSgoda.yusuke dp83902a_send(u8 *data, int total_len, u32 key) 2562439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2572439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 258*e710185aSgoda.yusuke u8 *base = dp->base; 2592439e4bfSJean-Christophe PLAGNIOL-VILLARD int len, start_page, pkt_len, i, isr; 2602439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 2612439e4bfSJean-Christophe PLAGNIOL-VILLARD int dx; 2622439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 2632439e4bfSJean-Christophe PLAGNIOL-VILLARD 2642439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 2652439e4bfSJean-Christophe PLAGNIOL-VILLARD 2662439e4bfSJean-Christophe PLAGNIOL-VILLARD len = pkt_len = total_len; 2672439e4bfSJean-Christophe PLAGNIOL-VILLARD if (pkt_len < IEEE_8023_MIN_FRAME) pkt_len = IEEE_8023_MIN_FRAME; 2682439e4bfSJean-Christophe PLAGNIOL-VILLARD 2692439e4bfSJean-Christophe PLAGNIOL-VILLARD start_page = dp->tx_next; 2702439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->tx_next == dp->tx_buf1) { 2712439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx1 = start_page; 2722439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx1_len = pkt_len; 2732439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx1_key = key; 2742439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_next = dp->tx_buf2; 2752439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 2762439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx2 = start_page; 2772439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx2_len = pkt_len; 2782439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx2_key = key; 2792439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_next = dp->tx_buf1; 2802439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2812439e4bfSJean-Christophe PLAGNIOL-VILLARD 2822439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 5 2832439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("TX prep page %d len %d\n", start_page, pkt_len); 2842439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 2852439e4bfSJean-Christophe PLAGNIOL-VILLARD 2862439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ 2872439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2882439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Dummy read. The manual sez something slightly different, */ 2892439e4bfSJean-Christophe PLAGNIOL-VILLARD /* but the code is extended a bit to do what Hitachi's monitor */ 2902439e4bfSJean-Christophe PLAGNIOL-VILLARD /* does (i.e., also read data). */ 2912439e4bfSJean-Christophe PLAGNIOL-VILLARD 292*e710185aSgoda.yusuke u16 tmp; 2932439e4bfSJean-Christophe PLAGNIOL-VILLARD int len = 1; 2942439e4bfSJean-Christophe PLAGNIOL-VILLARD 2952439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAL, 0x100-len); 2962439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAH, (start_page-1) & 0xff); 2972439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, len); 2982439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, 0); 2992439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START); 3002439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN_DATA(dp->data, tmp); 3012439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3022439e4bfSJean-Christophe PLAGNIOL-VILLARD 3032439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA 3042439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Stall for a bit before continuing to work around random data */ 3052439e4bfSJean-Christophe PLAGNIOL-VILLARD /* corruption problems on some platforms. */ 3062439e4bfSJean-Christophe PLAGNIOL-VILLARD CYGACC_CALL_IF_DELAY_US(1); 3072439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 3082439e4bfSJean-Christophe PLAGNIOL-VILLARD 3092439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Send data to device buffer(s) */ 3102439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAL, 0); 3112439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAH, start_page); 3122439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, pkt_len & 0xFF); 3132439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, pkt_len >> 8); 3142439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_WDMA | DP_CR_START); 3152439e4bfSJean-Christophe PLAGNIOL-VILLARD 3162439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Put data into buffer */ 3172439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 318*e710185aSgoda.yusuke printf(" sg buf %08lx len %08x\n ", (u32)data, len); 3192439e4bfSJean-Christophe PLAGNIOL-VILLARD dx = 0; 3202439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 3212439e4bfSJean-Christophe PLAGNIOL-VILLARD while (len > 0) { 3222439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 3232439e4bfSJean-Christophe PLAGNIOL-VILLARD printf(" %02x", *data); 3242439e4bfSJean-Christophe PLAGNIOL-VILLARD if (0 == (++dx % 16)) printf("\n "); 3252439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 326*e710185aSgoda.yusuke 3272439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT_DATA(dp->data, *data++); 3282439e4bfSJean-Christophe PLAGNIOL-VILLARD len--; 3292439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3302439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 3312439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("\n"); 3322439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 3332439e4bfSJean-Christophe PLAGNIOL-VILLARD if (total_len < pkt_len) { 3342439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 3352439e4bfSJean-Christophe PLAGNIOL-VILLARD printf(" + %d bytes of padding\n", pkt_len - total_len); 3362439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 3372439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Padding to 802.3 length was required */ 3382439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = total_len; i < pkt_len;) { 3392439e4bfSJean-Christophe PLAGNIOL-VILLARD i++; 3402439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT_DATA(dp->data, 0); 3412439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3422439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3432439e4bfSJean-Christophe PLAGNIOL-VILLARD 3442439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA 3452439e4bfSJean-Christophe PLAGNIOL-VILLARD /* After last data write, delay for a bit before accessing the */ 3462439e4bfSJean-Christophe PLAGNIOL-VILLARD /* device again, or we may get random data corruption in the last */ 3472439e4bfSJean-Christophe PLAGNIOL-VILLARD /* datum (on some platforms). */ 3482439e4bfSJean-Christophe PLAGNIOL-VILLARD CYGACC_CALL_IF_DELAY_US(1); 3492439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 3502439e4bfSJean-Christophe PLAGNIOL-VILLARD 3512439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for DMA to complete */ 3522439e4bfSJean-Christophe PLAGNIOL-VILLARD do { 3532439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_ISR, isr); 3542439e4bfSJean-Christophe PLAGNIOL-VILLARD } while ((isr & DP_ISR_RDC) == 0); 355*e710185aSgoda.yusuke 3562439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Then disable DMA */ 3572439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 3582439e4bfSJean-Christophe PLAGNIOL-VILLARD 3592439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Start transmit if not already going */ 3602439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!dp->tx_started) { 3612439e4bfSJean-Christophe PLAGNIOL-VILLARD if (start_page == dp->tx1) { 3622439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_int = 1; /* Expecting interrupt from BUF1 */ 3632439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 3642439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_int = 2; /* Expecting interrupt from BUF2 */ 3652439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3662439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start_xmit(start_page, pkt_len); 3672439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3682439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3692439e4bfSJean-Christophe PLAGNIOL-VILLARD 3702439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 3712439e4bfSJean-Christophe PLAGNIOL-VILLARD This function is called when a packet has been received. It's job is 3722439e4bfSJean-Christophe PLAGNIOL-VILLARD to prepare to unload the packet from the hardware. Once the length of 3732439e4bfSJean-Christophe PLAGNIOL-VILLARD the packet is known, the upper layer of the driver can be told. When 3742439e4bfSJean-Christophe PLAGNIOL-VILLARD the upper layer is ready to unload the packet, the internal function 3752439e4bfSJean-Christophe PLAGNIOL-VILLARD 'dp83902a_recv' will be called to actually fetch it from the hardware. 3762439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 3772439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 3782439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_RxEvent(void) 3792439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3802439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 381*e710185aSgoda.yusuke u8 *base = dp->base; 382*e710185aSgoda.yusuke u8 rsr; 383*e710185aSgoda.yusuke u8 rcv_hdr[4]; 3842439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, len, pkt, cur; 3852439e4bfSJean-Christophe PLAGNIOL-VILLARD 3862439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 3872439e4bfSJean-Christophe PLAGNIOL-VILLARD 3882439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_RSR, rsr); 3892439e4bfSJean-Christophe PLAGNIOL-VILLARD while (true) { 3902439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read incoming packet header */ 3912439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE1 | DP_CR_NODMA | DP_CR_START); 3922439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_P1_CURP, cur); 3932439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_P1_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 3942439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_BNDRY, pkt); 3952439e4bfSJean-Christophe PLAGNIOL-VILLARD 3962439e4bfSJean-Christophe PLAGNIOL-VILLARD pkt += 1; 3972439e4bfSJean-Christophe PLAGNIOL-VILLARD if (pkt == dp->rx_buf_end) 3982439e4bfSJean-Christophe PLAGNIOL-VILLARD pkt = dp->rx_buf_start; 3992439e4bfSJean-Christophe PLAGNIOL-VILLARD 4002439e4bfSJean-Christophe PLAGNIOL-VILLARD if (pkt == cur) { 4012439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 4022439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4032439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, sizeof(rcv_hdr)); 4042439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, 0); 4052439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAL, 0); 4062439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAH, pkt); 4072439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->rx_next == pkt) { 4082439e4bfSJean-Christophe PLAGNIOL-VILLARD if (cur == dp->rx_buf_start) 4092439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); 4102439e4bfSJean-Christophe PLAGNIOL-VILLARD else 4112439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_BNDRY, cur-1); /* Update pointer */ 4122439e4bfSJean-Christophe PLAGNIOL-VILLARD return; 4132439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4142439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->rx_next = pkt; 4152439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ 4162439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START); 4172439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA 4182439e4bfSJean-Christophe PLAGNIOL-VILLARD CYGACC_CALL_IF_DELAY_US(10); 4192439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 4202439e4bfSJean-Christophe PLAGNIOL-VILLARD 421*e710185aSgoda.yusuke /* read header (get data size)*/ 4222439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < sizeof(rcv_hdr);) { 4232439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN_DATA(dp->data, rcv_hdr[i++]); 4242439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4252439e4bfSJean-Christophe PLAGNIOL-VILLARD 4262439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 5 4272439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx hdr %02x %02x %02x %02x\n", 4282439e4bfSJean-Christophe PLAGNIOL-VILLARD rcv_hdr[0], rcv_hdr[1], rcv_hdr[2], rcv_hdr[3]); 4292439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 4302439e4bfSJean-Christophe PLAGNIOL-VILLARD len = ((rcv_hdr[3] << 8) | rcv_hdr[2]) - sizeof(rcv_hdr); 431*e710185aSgoda.yusuke 432*e710185aSgoda.yusuke /* data read */ 4332439e4bfSJean-Christophe PLAGNIOL-VILLARD uboot_push_packet_len(len); 434*e710185aSgoda.yusuke 4352439e4bfSJean-Christophe PLAGNIOL-VILLARD if (rcv_hdr[1] == dp->rx_buf_start) 4362439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1); 4372439e4bfSJean-Christophe PLAGNIOL-VILLARD else 4382439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_BNDRY, rcv_hdr[1]-1); /* Update pointer */ 4392439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4402439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4412439e4bfSJean-Christophe PLAGNIOL-VILLARD 4422439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 4432439e4bfSJean-Christophe PLAGNIOL-VILLARD This function is called as a result of the "eth_drv_recv()" call above. 4442439e4bfSJean-Christophe PLAGNIOL-VILLARD It's job is to actually fetch data for a packet from the hardware once 4452439e4bfSJean-Christophe PLAGNIOL-VILLARD memory buffers have been allocated for the packet. Note that the buffers 4462439e4bfSJean-Christophe PLAGNIOL-VILLARD may come in pieces, using a scatter-gather list. This allows for more 4472439e4bfSJean-Christophe PLAGNIOL-VILLARD efficient processing in the upper layers of the stack. 4482439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 4492439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 450*e710185aSgoda.yusuke dp83902a_recv(u8 *data, int len) 4512439e4bfSJean-Christophe PLAGNIOL-VILLARD { 4522439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 453*e710185aSgoda.yusuke u8 *base = dp->base; 4542439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, mlen; 455*e710185aSgoda.yusuke u8 saved_char = 0; 4562439e4bfSJean-Christophe PLAGNIOL-VILLARD bool saved; 4572439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 4582439e4bfSJean-Christophe PLAGNIOL-VILLARD int dx; 4592439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 4602439e4bfSJean-Christophe PLAGNIOL-VILLARD 4612439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 4622439e4bfSJean-Christophe PLAGNIOL-VILLARD 4632439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 5 4642439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("Rx packet %d length %d\n", dp->rx_next, len); 4652439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 4662439e4bfSJean-Christophe PLAGNIOL-VILLARD 4672439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read incoming packet data */ 4682439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); 4692439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, len & 0xFF); 4702439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, len >> 8); 4712439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAL, 4); /* Past header */ 4722439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RSAH, dp->rx_next); 4732439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ 4742439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START); 4752439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA 4762439e4bfSJean-Christophe PLAGNIOL-VILLARD CYGACC_CALL_IF_DELAY_US(10); 4772439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 4782439e4bfSJean-Christophe PLAGNIOL-VILLARD 4792439e4bfSJean-Christophe PLAGNIOL-VILLARD saved = false; 4802439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 1; i++) { 4812439e4bfSJean-Christophe PLAGNIOL-VILLARD if (data) { 4822439e4bfSJean-Christophe PLAGNIOL-VILLARD mlen = len; 4832439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 484*e710185aSgoda.yusuke printf(" sg buf %08lx len %08x \n", (u32) data, mlen); 4852439e4bfSJean-Christophe PLAGNIOL-VILLARD dx = 0; 4862439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 4872439e4bfSJean-Christophe PLAGNIOL-VILLARD while (0 < mlen) { 4882439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Saved byte from previous loop? */ 4892439e4bfSJean-Christophe PLAGNIOL-VILLARD if (saved) { 4902439e4bfSJean-Christophe PLAGNIOL-VILLARD *data++ = saved_char; 4912439e4bfSJean-Christophe PLAGNIOL-VILLARD mlen--; 4922439e4bfSJean-Christophe PLAGNIOL-VILLARD saved = false; 4932439e4bfSJean-Christophe PLAGNIOL-VILLARD continue; 4942439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4952439e4bfSJean-Christophe PLAGNIOL-VILLARD 4962439e4bfSJean-Christophe PLAGNIOL-VILLARD { 497*e710185aSgoda.yusuke u8 tmp; 4982439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN_DATA(dp->data, tmp); 4992439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 5002439e4bfSJean-Christophe PLAGNIOL-VILLARD printf(" %02x", tmp); 5012439e4bfSJean-Christophe PLAGNIOL-VILLARD if (0 == (++dx % 16)) printf("\n "); 5022439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 5032439e4bfSJean-Christophe PLAGNIOL-VILLARD *data++ = tmp;; 5042439e4bfSJean-Christophe PLAGNIOL-VILLARD mlen--; 5052439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5062439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5072439e4bfSJean-Christophe PLAGNIOL-VILLARD #if DEBUG & 4 5082439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("\n"); 5092439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 5102439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5112439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5122439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5132439e4bfSJean-Christophe PLAGNIOL-VILLARD 5142439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 5152439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_TxEvent(void) 5162439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5172439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 518*e710185aSgoda.yusuke u8 *base = dp->base; 519*e710185aSgoda.yusuke u8 tsr; 520*e710185aSgoda.yusuke u32 key; 5212439e4bfSJean-Christophe PLAGNIOL-VILLARD 5222439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUG_FUNCTION(); 5232439e4bfSJean-Christophe PLAGNIOL-VILLARD 5242439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_TSR, tsr); 5252439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->tx_int == 1) { 5262439e4bfSJean-Christophe PLAGNIOL-VILLARD key = dp->tx1_key; 5272439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx1 = 0; 5282439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 5292439e4bfSJean-Christophe PLAGNIOL-VILLARD key = dp->tx2_key; 5302439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx2 = 0; 5312439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5322439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Start next packet if one is ready */ 5332439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_started = false; 5342439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->tx1) { 5352439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start_xmit(dp->tx1, dp->tx1_len); 5362439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_int = 1; 5372439e4bfSJean-Christophe PLAGNIOL-VILLARD } else if (dp->tx2) { 5382439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start_xmit(dp->tx2, dp->tx2_len); 5392439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_int = 2; 5402439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 5412439e4bfSJean-Christophe PLAGNIOL-VILLARD dp->tx_int = 0; 5422439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5432439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Tell higher level we sent this packet */ 5442439e4bfSJean-Christophe PLAGNIOL-VILLARD uboot_push_tx_done(key, 0); 5452439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5462439e4bfSJean-Christophe PLAGNIOL-VILLARD 5472439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the tally counters to clear them. Called in response to a CNT */ 5482439e4bfSJean-Christophe PLAGNIOL-VILLARD /* interrupt. */ 5492439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 5502439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_ClearCounters(void) 5512439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5522439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 553*e710185aSgoda.yusuke u8 *base = dp->base; 554*e710185aSgoda.yusuke u8 cnt1, cnt2, cnt3; 5552439e4bfSJean-Christophe PLAGNIOL-VILLARD 5562439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_FER, cnt1); 5572439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_CER, cnt2); 5582439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_MISSED, cnt3); 5592439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_CNT); 5602439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5612439e4bfSJean-Christophe PLAGNIOL-VILLARD 5622439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Deal with an overflow condition. This code follows the procedure set */ 5632439e4bfSJean-Christophe PLAGNIOL-VILLARD /* out in section 7.0 of the datasheet. */ 5642439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 5652439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_Overflow(void) 5662439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5672439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *)&nic; 568*e710185aSgoda.yusuke u8 *base = dp->base; 569*e710185aSgoda.yusuke u8 isr; 5702439e4bfSJean-Christophe PLAGNIOL-VILLARD 5712439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Issue a stop command and wait 1.6ms for it to complete. */ 5722439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_STOP | DP_CR_NODMA); 5732439e4bfSJean-Christophe PLAGNIOL-VILLARD CYGACC_CALL_IF_DELAY_US(1600); 5742439e4bfSJean-Christophe PLAGNIOL-VILLARD 5752439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear the remote byte counter registers. */ 5762439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCL, 0); 5772439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_RBCH, 0); 5782439e4bfSJean-Christophe PLAGNIOL-VILLARD 5792439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Enter loopback mode while we clear the buffer. */ 5802439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TCR, DP_TCR_LOCAL); 5812439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_START | DP_CR_NODMA); 5822439e4bfSJean-Christophe PLAGNIOL-VILLARD 5832439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read in as many packets as we can and acknowledge any and receive */ 5842439e4bfSJean-Christophe PLAGNIOL-VILLARD /* interrupts. Since the buffer has overflowed, a receive event of */ 5852439e4bfSJean-Christophe PLAGNIOL-VILLARD /* some kind will have occured. */ 5862439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_RxEvent(); 5872439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_RxP|DP_ISR_RxE); 5882439e4bfSJean-Christophe PLAGNIOL-VILLARD 5892439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear the overflow condition and leave loopback mode. */ 5902439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, DP_ISR_OFLW); 5912439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_TCR, DP_TCR_NORMAL); 5922439e4bfSJean-Christophe PLAGNIOL-VILLARD 5932439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If a transmit command was issued, but no transmit event has occured, */ 5942439e4bfSJean-Christophe PLAGNIOL-VILLARD /* restart it here. */ 5952439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_ISR, isr); 5962439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp->tx_started && !(isr & (DP_ISR_TxP|DP_ISR_TxE))) { 5972439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_TXPKT | DP_CR_START); 5982439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5992439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6002439e4bfSJean-Christophe PLAGNIOL-VILLARD 6012439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 6022439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_poll(void) 6032439e4bfSJean-Christophe PLAGNIOL-VILLARD { 6042439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; 605*e710185aSgoda.yusuke u8 *base = dp->base; 606*e710185aSgoda.yusuke u8 isr; 6072439e4bfSJean-Christophe PLAGNIOL-VILLARD 6082439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0 | DP_CR_START); 6092439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_ISR, isr); 6102439e4bfSJean-Christophe PLAGNIOL-VILLARD while (0 != isr) { 6112439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The CNT interrupt triggers when the MSB of one of the error */ 6122439e4bfSJean-Christophe PLAGNIOL-VILLARD /* counters is set. We don't much care about these counters, but */ 6132439e4bfSJean-Christophe PLAGNIOL-VILLARD /* we should read their values to reset them. */ 6142439e4bfSJean-Christophe PLAGNIOL-VILLARD if (isr & DP_ISR_CNT) { 6152439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_ClearCounters(); 6162439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6172439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check for overflow. It's a special case, since there's a */ 6182439e4bfSJean-Christophe PLAGNIOL-VILLARD /* particular procedure that must be followed to get back into */ 6192439e4bfSJean-Christophe PLAGNIOL-VILLARD /* a running state.a */ 6202439e4bfSJean-Christophe PLAGNIOL-VILLARD if (isr & DP_ISR_OFLW) { 6212439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_Overflow(); 6222439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 6232439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Other kinds of interrupts can be acknowledged simply by */ 6242439e4bfSJean-Christophe PLAGNIOL-VILLARD /* clearing the relevant bits of the ISR. Do that now, then */ 6252439e4bfSJean-Christophe PLAGNIOL-VILLARD /* handle the interrupts we care about. */ 6262439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_OUT(base, DP_ISR, isr); /* Clear set bits */ 6272439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!dp->running) break; /* Is this necessary? */ 6282439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check for tx_started on TX event since these may happen */ 6292439e4bfSJean-Christophe PLAGNIOL-VILLARD /* spuriously it seems. */ 6302439e4bfSJean-Christophe PLAGNIOL-VILLARD if (isr & (DP_ISR_TxP|DP_ISR_TxE) && dp->tx_started) { 6312439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_TxEvent(); 6322439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6332439e4bfSJean-Christophe PLAGNIOL-VILLARD if (isr & (DP_ISR_RxP|DP_ISR_RxE)) { 6342439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_RxEvent(); 6352439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6362439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6372439e4bfSJean-Christophe PLAGNIOL-VILLARD DP_IN(base, DP_ISR, isr); 6382439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6392439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6402439e4bfSJean-Christophe PLAGNIOL-VILLARD 6412439e4bfSJean-Christophe PLAGNIOL-VILLARD /* find prom (taken from pc_net_cs.c from Linux) */ 6422439e4bfSJean-Christophe PLAGNIOL-VILLARD 6432439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "8390.h" 644*e710185aSgoda.yusuke /* 6452439e4bfSJean-Christophe PLAGNIOL-VILLARD typedef struct hw_info_t { 6462439e4bfSJean-Christophe PLAGNIOL-VILLARD u_int offset; 6472439e4bfSJean-Christophe PLAGNIOL-VILLARD u_char a0, a1, a2; 6482439e4bfSJean-Christophe PLAGNIOL-VILLARD u_int flags; 6492439e4bfSJean-Christophe PLAGNIOL-VILLARD } hw_info_t; 650*e710185aSgoda.yusuke */ 6512439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DELAY_OUTPUT 0x01 6522439e4bfSJean-Christophe PLAGNIOL-VILLARD #define HAS_MISC_REG 0x02 6532439e4bfSJean-Christophe PLAGNIOL-VILLARD #define USE_BIG_BUF 0x04 6542439e4bfSJean-Christophe PLAGNIOL-VILLARD #define HAS_IBM_MISC 0x08 6552439e4bfSJean-Christophe PLAGNIOL-VILLARD #define IS_DL10019 0x10 6562439e4bfSJean-Christophe PLAGNIOL-VILLARD #define IS_DL10022 0x20 6572439e4bfSJean-Christophe PLAGNIOL-VILLARD #define HAS_MII 0x40 6582439e4bfSJean-Christophe PLAGNIOL-VILLARD #define USE_SHMEM 0x80 /* autodetected */ 6592439e4bfSJean-Christophe PLAGNIOL-VILLARD 6602439e4bfSJean-Christophe PLAGNIOL-VILLARD #define AM79C9XX_HOME_PHY 0x00006B90 /* HomePNA PHY */ 6612439e4bfSJean-Christophe PLAGNIOL-VILLARD #define AM79C9XX_ETH_PHY 0x00006B70 /* 10baseT PHY */ 6622439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_PHYID_REV_MASK 0xfffffff0 6632439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_PHYID_REG1 0x02 6642439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_PHYID_REG2 0x03 6652439e4bfSJean-Christophe PLAGNIOL-VILLARD 6662439e4bfSJean-Christophe PLAGNIOL-VILLARD static hw_info_t hw_info[] = { 6672439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT }, 6682439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 }, 6692439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 }, 6702439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94, 6712439e4bfSJean-Christophe PLAGNIOL-VILLARD DELAY_OUTPUT | HAS_IBM_MISC }, 6722439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 }, 6732439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 }, 6742439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 }, 6752439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 }, 6762439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 }, 6772439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 }, 6782439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48, 6792439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 6802439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 }, 6812439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 }, 6822439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a, 6832439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 6842439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac, 6852439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 6862439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29, 6872439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 6882439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a, 6892439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 6902439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac, 6912439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 6922439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87, 6932439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 6942439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17, 6952439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 6962439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8, 6972439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 6982439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0, 6992439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 7002439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0, 7012439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 7022439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 }, 7032439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 }, 7042439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0, 7052439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 7062439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f, 7072439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 7082439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 }, 7092439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 }, 7102439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 }, 7112439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 }, 7122439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65, 7132439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 7142439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45, 7152439e4bfSJean-Christophe PLAGNIOL-VILLARD HAS_MISC_REG | HAS_IBM_MISC }, 7162439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 }, 7172439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 }, 7182439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 }, 7192439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b, 7202439e4bfSJean-Christophe PLAGNIOL-VILLARD DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF }, 7212439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 }, 7222439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 }, 7232439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 }, 7242439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 }, 7252439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }, 7262439e4bfSJean-Christophe PLAGNIOL-VILLARD { /* Qemu */ 0x0, 0x52, 0x54, 0x00, 0 } 7272439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 7282439e4bfSJean-Christophe PLAGNIOL-VILLARD 7292439e4bfSJean-Christophe PLAGNIOL-VILLARD #define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t)) 7302439e4bfSJean-Christophe PLAGNIOL-VILLARD 7312439e4bfSJean-Christophe PLAGNIOL-VILLARD static hw_info_t default_info = { 0, 0, 0, 0, 0 }; 7322439e4bfSJean-Christophe PLAGNIOL-VILLARD 733*e710185aSgoda.yusuke u8 dev_addr[6]; 7342439e4bfSJean-Christophe PLAGNIOL-VILLARD 7352439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PCNET_CMD 0x00 7362439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PCNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */ 7372439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PCNET_RESET 0x1f /* Issue a read to reset, a write to clear. */ 7382439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PCNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */ 7392439e4bfSJean-Christophe PLAGNIOL-VILLARD 740*e710185aSgoda.yusuke u32 nic_base; 7412439e4bfSJean-Christophe PLAGNIOL-VILLARD 7422439e4bfSJean-Christophe PLAGNIOL-VILLARD /* U-boot specific routines */ 743*e710185aSgoda.yusuke static u8 *pbuf = NULL; 7442439e4bfSJean-Christophe PLAGNIOL-VILLARD 7452439e4bfSJean-Christophe PLAGNIOL-VILLARD static int pkey = -1; 7462439e4bfSJean-Christophe PLAGNIOL-VILLARD static int initialized=0; 7472439e4bfSJean-Christophe PLAGNIOL-VILLARD 7482439e4bfSJean-Christophe PLAGNIOL-VILLARD void uboot_push_packet_len(int len) { 7492439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("pushed len = %d\n", len); 7502439e4bfSJean-Christophe PLAGNIOL-VILLARD if (len>=2000) { 7512439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("NE2000: packet too big\n"); 7522439e4bfSJean-Christophe PLAGNIOL-VILLARD return; 7532439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7542439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_recv(&pbuf[0], len); 7552439e4bfSJean-Christophe PLAGNIOL-VILLARD 7562439e4bfSJean-Christophe PLAGNIOL-VILLARD /*Just pass it to the upper layer*/ 7572439e4bfSJean-Christophe PLAGNIOL-VILLARD NetReceive(&pbuf[0], len); 7582439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7592439e4bfSJean-Christophe PLAGNIOL-VILLARD 7602439e4bfSJean-Christophe PLAGNIOL-VILLARD void uboot_push_tx_done(int key, int val) { 7612439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("pushed key = %d\n", key); 7622439e4bfSJean-Christophe PLAGNIOL-VILLARD pkey = key; 7632439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7642439e4bfSJean-Christophe PLAGNIOL-VILLARD 7652439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_init(bd_t *bd) { 7662439e4bfSJean-Christophe PLAGNIOL-VILLARD static hw_info_t * r; 7672439e4bfSJean-Christophe PLAGNIOL-VILLARD char ethaddr[20]; 7682439e4bfSJean-Christophe PLAGNIOL-VILLARD 7692439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("### eth_init\n"); 7702439e4bfSJean-Christophe PLAGNIOL-VILLARD 7712439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!pbuf) { 7722439e4bfSJean-Christophe PLAGNIOL-VILLARD pbuf = malloc(2000); 7732439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!pbuf) { 7742439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("Cannot allocate rx buffer\n"); 7752439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 7762439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7772439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7782439e4bfSJean-Christophe PLAGNIOL-VILLARD 7792439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DRIVER_NE2000_CCR 7802439e4bfSJean-Christophe PLAGNIOL-VILLARD { 781*e710185aSgoda.yusuke vu_char *p = (vu_char *) CONFIG_DRIVER_NE2000_CCR; 7822439e4bfSJean-Christophe PLAGNIOL-VILLARD 7832439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("CCR before is %x\n", *p); 7842439e4bfSJean-Christophe PLAGNIOL-VILLARD *p = CONFIG_DRIVER_NE2000_VAL; 7852439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("CCR after is %x\n", *p); 7862439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7872439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 7882439e4bfSJean-Christophe PLAGNIOL-VILLARD 7892439e4bfSJean-Christophe PLAGNIOL-VILLARD nic_base = CONFIG_DRIVER_NE2000_BASE; 790*e710185aSgoda.yusuke nic.base = (u8 *) CONFIG_DRIVER_NE2000_BASE; 7912439e4bfSJean-Christophe PLAGNIOL-VILLARD 792*e710185aSgoda.yusuke r = get_prom(dev_addr); 7932439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!r) 7942439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 7952439e4bfSJean-Christophe PLAGNIOL-VILLARD 7962439e4bfSJean-Christophe PLAGNIOL-VILLARD sprintf (ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", 7972439e4bfSJean-Christophe PLAGNIOL-VILLARD dev_addr[0], dev_addr[1], 7982439e4bfSJean-Christophe PLAGNIOL-VILLARD dev_addr[2], dev_addr[3], 7992439e4bfSJean-Christophe PLAGNIOL-VILLARD dev_addr[4], dev_addr[5]) ; 8002439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("Set environment from HW MAC addr = \"%s\"\n", ethaddr); 8012439e4bfSJean-Christophe PLAGNIOL-VILLARD setenv ("ethaddr", ethaddr); 8022439e4bfSJean-Christophe PLAGNIOL-VILLARD 8032439e4bfSJean-Christophe PLAGNIOL-VILLARD nic.data = nic.base + DP_DATA; 804*e710185aSgoda.yusuke nic.tx_buf1 = START_PG; 805*e710185aSgoda.yusuke nic.tx_buf2 = START_PG2; 806*e710185aSgoda.yusuke nic.rx_buf_start = RX_START; 807*e710185aSgoda.yusuke nic.rx_buf_end = RX_END; 8082439e4bfSJean-Christophe PLAGNIOL-VILLARD 8092439e4bfSJean-Christophe PLAGNIOL-VILLARD if (dp83902a_init() == false) 8102439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 811*e710185aSgoda.yusuke 8122439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_start(dev_addr); 8132439e4bfSJean-Christophe PLAGNIOL-VILLARD initialized=1; 814*e710185aSgoda.yusuke 8152439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 8162439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8172439e4bfSJean-Christophe PLAGNIOL-VILLARD 8182439e4bfSJean-Christophe PLAGNIOL-VILLARD void eth_halt() { 819*e710185aSgoda.yusuke 8202439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("### eth_halt\n"); 8212439e4bfSJean-Christophe PLAGNIOL-VILLARD if(initialized) 8222439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_stop(); 8232439e4bfSJean-Christophe PLAGNIOL-VILLARD initialized=0; 8242439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8252439e4bfSJean-Christophe PLAGNIOL-VILLARD 8262439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_rx() { 8272439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_poll(); 8282439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1; 8292439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8302439e4bfSJean-Christophe PLAGNIOL-VILLARD 8312439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_send(volatile void *packet, int length) { 8322439e4bfSJean-Christophe PLAGNIOL-VILLARD int tmo; 8332439e4bfSJean-Christophe PLAGNIOL-VILLARD 8342439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("### eth_send\n"); 8352439e4bfSJean-Christophe PLAGNIOL-VILLARD 8362439e4bfSJean-Christophe PLAGNIOL-VILLARD pkey = -1; 8372439e4bfSJean-Christophe PLAGNIOL-VILLARD 838*e710185aSgoda.yusuke dp83902a_send((u8 *) packet, length, 666); 8392439e4bfSJean-Christophe PLAGNIOL-VILLARD tmo = get_timer (0) + TOUT * CFG_HZ; 8402439e4bfSJean-Christophe PLAGNIOL-VILLARD while(1) { 8412439e4bfSJean-Christophe PLAGNIOL-VILLARD dp83902a_poll(); 8422439e4bfSJean-Christophe PLAGNIOL-VILLARD if (pkey != -1) { 8432439e4bfSJean-Christophe PLAGNIOL-VILLARD PRINTK("Packet sucesfully sent\n"); 8442439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 8452439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8462439e4bfSJean-Christophe PLAGNIOL-VILLARD if (get_timer (0) >= tmo) { 8472439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("transmission error (timoeut)\n"); 8482439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 8492439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8502439e4bfSJean-Christophe PLAGNIOL-VILLARD 8512439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8522439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 8532439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8542439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 855