xref: /rk3399_rockchip-uboot/drivers/net/dc2114x.c (revision 2439e4bfa111babf4bc07ba20efbf3e36036813e)
1*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
2*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * See file CREDITS for list of people who contributed to this
3*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * project.
4*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
5*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * This program is free software; you can redistribute it and/or
6*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * modify it under the terms of the GNU General Public License as
7*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * published by the Free Software Foundation; either version 2 of
8*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * the License, or (at your option) any later version.
9*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
10*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * This program is distributed in the hope that it will be useful,
11*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
13*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * GNU General Public License for more details.
14*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
15*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * You should have received a copy of the GNU General Public License
16*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * along with this program; if not, write to the Free Software
17*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * MA 02111-1307 USA
19*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
20*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
21*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
22*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
23*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_CMD_NET) \
24*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	&& defined(CONFIG_NET_MULTI) && defined(CONFIG_TULIP)
25*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
26*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <malloc.h>
27*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h>
28*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <pci.h>
29*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
30*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #undef DEBUG_SROM
31*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #undef DEBUG_SROM2
32*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
33*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #undef UPDATE_SROM
34*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
35*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* PCI Registers.
36*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
37*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PCI_CFDA_PSM		0x43
38*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
39*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CFRV_RN		0x000000f0	/* Revision Number */
40*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
41*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define WAKEUP		0x00		/* Power Saving Wakeup */
42*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SLEEP		0x80		/* Power Saving Sleep Mode */
43*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
44*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DC2114x_BRK	0x0020		/* CFRV break between DC21142 & DC21143 */
45*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
46*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Ethernet chip registers.
47*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
48*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DE4X5_BMR	0x000		/* Bus Mode Register */
49*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DE4X5_TPD	0x008		/* Transmit Poll Demand Reg */
50*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DE4X5_RRBA	0x018		/* RX Ring Base Address Reg */
51*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DE4X5_TRBA	0x020		/* TX Ring Base Address Reg */
52*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DE4X5_STS	0x028		/* Status Register */
53*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DE4X5_OMR	0x030		/* Operation Mode Register */
54*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DE4X5_SICR	0x068		/* SIA Connectivity Register */
55*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DE4X5_APROM	0x048		/* Ethernet Address PROM */
56*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
57*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Register bits.
58*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
59*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define BMR_SWR		0x00000001	/* Software Reset */
60*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define STS_TS		0x00700000	/* Transmit Process State */
61*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define STS_RS		0x000e0000	/* Receive Process State */
62*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OMR_ST		0x00002000	/* Start/Stop Transmission Command */
63*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OMR_SR		0x00000002	/* Start/Stop Receive */
64*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OMR_PS		0x00040000	/* Port Select */
65*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OMR_SDP		0x02000000	/* SD Polarity - MUST BE ASSERTED */
66*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OMR_PM		0x00000080	/* Pass All Multicast */
67*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
68*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Descriptor bits.
69*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
70*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define R_OWN		0x80000000	/* Own Bit */
71*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RD_RER		0x02000000	/* Receive End Of Ring */
72*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RD_LS		0x00000100	/* Last Descriptor */
73*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RD_ES		0x00008000	/* Error Summary */
74*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TD_TER		0x02000000	/* Transmit End Of Ring */
75*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define T_OWN		0x80000000	/* Own Bit */
76*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TD_LS		0x40000000	/* Last Segment */
77*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TD_FS		0x20000000	/* First Segment */
78*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TD_ES		0x00008000	/* Error Summary */
79*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TD_SET		0x08000000	/* Setup Packet */
80*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
81*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The EEPROM commands include the alway-set leading bit. */
82*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SROM_WRITE_CMD	5
83*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SROM_READ_CMD	6
84*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SROM_ERASE_CMD	7
85*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
86*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SROM_HWADD	    0x0014	/* Hardware Address offset in SROM */
87*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SROM_RD		0x00004000	/* Read from Boot ROM */
88*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_DATA_WRITE	      0x04	/* EEPROM chip data in. */
89*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_WRITE_0	    0x4801
90*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_WRITE_1	    0x4805
91*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define EE_DATA_READ	      0x08	/* EEPROM chip data out. */
92*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SROM_SR		0x00000800	/* Select Serial ROM when set */
93*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
94*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DT_IN		0x00000004	/* Serial Data In */
95*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DT_CLK		0x00000002	/* Serial ROM Clock */
96*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DT_CS		0x00000001	/* Serial ROM Chip Select */
97*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
98*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define POLL_DEMAND	1
99*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
100*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_FIX_DAVICOM
101*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RESET_DM9102(dev) {\
102*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     unsigned long i;\
103*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     i=INL(dev, 0x0);\
104*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     udelay(1000);\
105*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     OUTL(dev, i | BMR_SWR, DE4X5_BMR);\
106*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     udelay(1000);\
107*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
108*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
109*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RESET_DE4X5(dev) {\
110*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     int i;\
111*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     i=INL(dev, DE4X5_BMR);\
112*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     udelay(1000);\
113*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     OUTL(dev, i | BMR_SWR, DE4X5_BMR);\
114*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     udelay(1000);\
115*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     OUTL(dev, i, DE4X5_BMR);\
116*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     udelay(1000);\
117*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     for (i=0;i<5;i++) {INL(dev, DE4X5_BMR); udelay(10000);}\
118*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     udelay(1000);\
119*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
120*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
121*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
122*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define START_DE4X5(dev) {\
123*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     s32 omr; \
124*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     omr = INL(dev, DE4X5_OMR);\
125*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     omr |= OMR_ST | OMR_SR;\
126*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     OUTL(dev, omr, DE4X5_OMR);		/* Enable the TX and/or RX */\
127*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
128*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
129*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define STOP_DE4X5(dev) {\
130*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     s32 omr; \
131*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     omr = INL(dev, DE4X5_OMR);\
132*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     omr &= ~(OMR_ST|OMR_SR);\
133*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     OUTL(dev, omr, DE4X5_OMR);		/* Disable the TX and/or RX */ \
134*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
135*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
136*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define NUM_RX_DESC PKTBUFSRX
137*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_TULIP_FIX_DAVICOM
138*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	#define NUM_TX_DESC 1			/* Number of TX descriptors   */
139*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
140*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	#define NUM_TX_DESC 4
141*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
142*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_BUFF_SZ  PKTSIZE_ALIGN
143*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
144*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TOUT_LOOP   1000000
145*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
146*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SETUP_FRAME_LEN 192
147*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define ETH_ALEN	6
148*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
149*2439e4bfSJean-Christophe PLAGNIOL-VILLARD struct de4x5_desc {
150*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	volatile s32 status;
151*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u32 des1;
152*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u32 buf;
153*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u32 next;
154*2439e4bfSJean-Christophe PLAGNIOL-VILLARD };
155*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
156*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct de4x5_desc rx_ring[NUM_RX_DESC] __attribute__ ((aligned(32))); /* RX descriptor ring         */
157*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct de4x5_desc tx_ring[NUM_TX_DESC] __attribute__ ((aligned(32))); /* TX descriptor ring         */
158*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int rx_new;                             /* RX descriptor ring pointer */
159*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int tx_new;                             /* TX descriptor ring pointer */
160*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
161*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static char rxRingSize;
162*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static char txRingSize;
163*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
164*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM)
165*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void  sendto_srom(struct eth_device* dev, u_int command, u_long addr);
166*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int   getfrom_srom(struct eth_device* dev, u_long addr);
167*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int   do_eeprom_cmd(struct eth_device *dev, u_long ioaddr,int cmd,int cmd_len);
168*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int   do_read_eeprom(struct eth_device *dev,u_long ioaddr,int location,int addr_len);
169*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif	/* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */
170*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef UPDATE_SROM
171*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int   write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value);
172*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void  update_srom(struct eth_device *dev, bd_t *bis);
173*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
174*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_TULIP_FIX_DAVICOM
175*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int   read_srom(struct eth_device *dev, u_long ioaddr, int index);
176*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void  read_hw_addr(struct eth_device* dev, bd_t * bis);
177*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif	/* CONFIG_TULIP_FIX_DAVICOM */
178*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void  send_setup_frame(struct eth_device* dev, bd_t * bis);
179*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
180*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int   dc21x4x_init(struct eth_device* dev, bd_t* bis);
181*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int   dc21x4x_send(struct eth_device* dev, volatile void *packet, int length);
182*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int   dc21x4x_recv(struct eth_device* dev);
183*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void  dc21x4x_halt(struct eth_device* dev);
184*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_SELECT_MEDIA
185*2439e4bfSJean-Christophe PLAGNIOL-VILLARD extern void  dc21x4x_select_media(struct eth_device* dev);
186*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
187*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
188*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_E500)
189*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define phys_to_bus(a) (a)
190*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
191*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define phys_to_bus(a)	pci_phys_to_mem((pci_dev_t)dev->priv, a)
192*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
193*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
194*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int INL(struct eth_device* dev, u_long addr)
195*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
196*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase));
197*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
198*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
199*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void OUTL(struct eth_device* dev, int command, u_long addr)
200*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
201*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	*(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command);
202*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
203*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
204*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct pci_device_id supported[] = {
205*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST },
206*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 },
207*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_FIX_DAVICOM
208*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	{ PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DAVICOM_DM9102A },
209*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
210*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	{ }
211*2439e4bfSJean-Christophe PLAGNIOL-VILLARD };
212*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
213*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int dc21x4x_initialize(bd_t *bis)
214*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
215*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int             	idx=0;
216*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int             	card_number = 0;
217*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned int           	cfrv;
218*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned char   	timer;
219*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	pci_dev_t		devbusfn;
220*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned int		iobase;
221*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned short		status;
222*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	struct eth_device* 	dev;
223*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
224*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while(1) {
225*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		devbusfn =  pci_find_devices(supported, idx++);
226*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (devbusfn == -1) {
227*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			break;
228*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
229*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
230*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Get the chip configuration revision register. */
231*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv);
232*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
233*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_TULIP_FIX_DAVICOM
234*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if ((cfrv & CFRV_RN) < DC2114x_BRK ) {
235*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf("Error: The chip is not DC21143.\n");
236*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			continue;
237*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
238*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
239*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
240*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		pci_read_config_word(devbusfn, PCI_COMMAND, &status);
241*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		status |=
242*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_USE_IO
243*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		  PCI_COMMAND_IO |
244*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
245*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		  PCI_COMMAND_MEMORY |
246*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
247*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		  PCI_COMMAND_MASTER;
248*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		pci_write_config_word(devbusfn, PCI_COMMAND, status);
249*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
250*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		pci_read_config_word(devbusfn, PCI_COMMAND, &status);
251*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (!(status & PCI_COMMAND_IO)) {
252*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf("Error: Can not enable I/O access.\n");
253*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			continue;
254*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
255*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
256*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (!(status & PCI_COMMAND_IO)) {
257*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf("Error: Can not enable I/O access.\n");
258*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			continue;
259*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
260*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
261*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (!(status & PCI_COMMAND_MASTER)) {
262*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf("Error: Can not enable Bus Mastering.\n");
263*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			continue;
264*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
265*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
266*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Check the latency timer for values >= 0x60. */
267*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer);
268*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
269*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (timer < 0x60) {
270*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x60);
271*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
272*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
273*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_USE_IO
274*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* read BAR for memory space access */
275*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase);
276*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		iobase &= PCI_BASE_ADDRESS_IO_MASK;
277*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
278*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* read BAR for memory space access */
279*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase);
280*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		iobase &= PCI_BASE_ADDRESS_MEM_MASK;
281*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
282*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		debug ("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase);
283*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
284*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		dev = (struct eth_device*) malloc(sizeof *dev);
285*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
286*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_FIX_DAVICOM
287*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		sprintf(dev->name, "Davicom#%d", card_number);
288*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
289*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		sprintf(dev->name, "dc21x4x#%d", card_number);
290*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
291*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
292*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_USE_IO
293*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		dev->iobase = pci_io_to_phys(devbusfn, iobase);
294*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
295*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		dev->iobase = pci_mem_to_phys(devbusfn, iobase);
296*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
297*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		dev->priv   = (void*) devbusfn;
298*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		dev->init   = dc21x4x_init;
299*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		dev->halt   = dc21x4x_halt;
300*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		dev->send   = dc21x4x_send;
301*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		dev->recv   = dc21x4x_recv;
302*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
303*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Ensure we're not sleeping. */
304*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
305*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
306*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay(10 * 1000);
307*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
308*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_TULIP_FIX_DAVICOM
309*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		read_hw_addr(dev, bis);
310*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
311*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		eth_register(dev);
312*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
313*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		card_number++;
314*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
315*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
316*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return card_number;
317*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
318*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
319*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int dc21x4x_init(struct eth_device* dev, bd_t* bis)
320*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
321*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int		i;
322*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int		devbusfn = (int) dev->priv;
323*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
324*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Ensure we're not sleeping. */
325*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
326*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
327*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_FIX_DAVICOM
328*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	RESET_DM9102(dev);
329*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
330*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	RESET_DE4X5(dev);
331*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
332*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
333*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ((INL(dev, DE4X5_STS) & (STS_TS | STS_RS)) != 0) {
334*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("Error: Cannot reset ethernet controller.\n");
335*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
336*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
337*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
338*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_SELECT_MEDIA
339*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	dc21x4x_select_media(dev);
340*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
341*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);
342*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
343*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
344*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < NUM_RX_DESC; i++) {
345*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		rx_ring[i].status = cpu_to_le32(R_OWN);
346*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
347*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		rx_ring[i].buf = cpu_to_le32(phys_to_bus((u32) NetRxPackets[i]));
348*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_FIX_DAVICOM
349*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		rx_ring[i].next = cpu_to_le32(phys_to_bus((u32) &rx_ring[(i+1) % NUM_RX_DESC]));
350*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
351*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		rx_ring[i].next = 0;
352*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
353*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
354*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
355*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i=0; i < NUM_TX_DESC; i++) {
356*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		tx_ring[i].status = 0;
357*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		tx_ring[i].des1 = 0;
358*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		tx_ring[i].buf = 0;
359*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
360*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_TULIP_FIX_DAVICOM
361*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tx_ring[i].next = cpu_to_le32(phys_to_bus((u32) &tx_ring[(i+1) % NUM_TX_DESC]));
362*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
363*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		tx_ring[i].next = 0;
364*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
365*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
366*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
367*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	rxRingSize = NUM_RX_DESC;
368*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	txRingSize = NUM_TX_DESC;
369*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
370*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Write the end of list marker to the descriptor lists. */
371*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	rx_ring[rxRingSize - 1].des1 |= cpu_to_le32(RD_RER);
372*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER);
373*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
374*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Tell the adapter where the TX/RX rings are located. */
375*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	OUTL(dev, phys_to_bus((u32) &rx_ring), DE4X5_RRBA);
376*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	OUTL(dev, phys_to_bus((u32) &tx_ring), DE4X5_TRBA);
377*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
378*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	START_DE4X5(dev);
379*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
380*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tx_new = 0;
381*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	rx_new = 0;
382*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
383*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	send_setup_frame(dev, bis);
384*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
385*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 1;
386*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
387*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
388*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length)
389*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
390*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int		status = -1;
391*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int		i;
392*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
393*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (length <= 0) {
394*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("%s: bad packet size: %d\n", dev->name, length);
395*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		goto Done;
396*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
397*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
398*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
399*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (i >= TOUT_LOOP) {
400*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf("%s: tx error buffer not ready\n", dev->name);
401*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			goto Done;
402*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
403*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
404*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
405*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tx_ring[tx_new].buf    = cpu_to_le32(phys_to_bus((u32) packet));
406*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tx_ring[tx_new].des1   = cpu_to_le32(TD_TER | TD_LS | TD_FS | length);
407*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tx_ring[tx_new].status = cpu_to_le32(T_OWN);
408*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
409*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	OUTL(dev, POLL_DEMAND, DE4X5_TPD);
410*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
411*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
412*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (i >= TOUT_LOOP) {
413*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf(".%s: tx buffer not ready\n", dev->name);
414*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			goto Done;
415*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
416*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
417*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
418*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES) {
419*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 /* test-only */
420*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("TX error status = 0x%08X\n",
421*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			le32_to_cpu(tx_ring[tx_new].status));
422*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
423*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		tx_ring[tx_new].status = 0x0;
424*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		goto Done;
425*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
426*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
427*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	status = length;
428*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
429*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  Done:
430*2439e4bfSJean-Christophe PLAGNIOL-VILLARD     tx_new = (tx_new+1) % NUM_TX_DESC;
431*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return status;
432*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
433*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
434*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int dc21x4x_recv(struct eth_device* dev)
435*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
436*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	s32		status;
437*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int		length    = 0;
438*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
439*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for ( ; ; ) {
440*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		status = (s32)le32_to_cpu(rx_ring[rx_new].status);
441*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
442*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (status & R_OWN) {
443*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			break;
444*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
445*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
446*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (status & RD_LS) {
447*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			/* Valid frame status.
448*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			 */
449*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			if (status & RD_ES) {
450*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
451*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				/* There was an error.
452*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				 */
453*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				printf("RX error status = 0x%08X\n", status);
454*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			} else {
455*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				/* A valid frame received.
456*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				 */
457*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				length = (le32_to_cpu(rx_ring[rx_new].status) >> 16);
458*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
459*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				/* Pass the packet up to the protocol
460*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				 * layers.
461*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				 */
462*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				NetReceive(NetRxPackets[rx_new], length - 4);
463*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			}
464*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
465*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			/* Change buffer ownership for this frame, back
466*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			 * to the adapter.
467*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			 */
468*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			rx_ring[rx_new].status = cpu_to_le32(R_OWN);
469*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
470*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
471*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Update entry information.
472*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		 */
473*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		rx_new = (rx_new + 1) % rxRingSize;
474*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
475*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
476*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return length;
477*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
478*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
479*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void dc21x4x_halt(struct eth_device* dev)
480*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
481*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int		devbusfn = (int) dev->priv;
482*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
483*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	STOP_DE4X5(dev);
484*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	OUTL(dev, 0, DE4X5_SICR);
485*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
486*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP);
487*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
488*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
489*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void send_setup_frame(struct eth_device* dev, bd_t *bis)
490*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
491*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int		i;
492*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	char	setup_frame[SETUP_FRAME_LEN];
493*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	char 	*pa = &setup_frame[0];
494*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
495*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	memset(pa, 0xff, SETUP_FRAME_LEN);
496*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
497*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < ETH_ALEN; i++) {
498*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		*(pa + (i & 1)) = dev->enetaddr[i];
499*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (i & 0x01) {
500*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			pa += 4;
501*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
502*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
503*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
504*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
505*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (i >= TOUT_LOOP) {
506*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf("%s: tx error buffer not ready\n", dev->name);
507*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			goto Done;
508*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
509*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
510*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
511*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) &setup_frame[0]));
512*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN);
513*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tx_ring[tx_new].status = cpu_to_le32(T_OWN);
514*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
515*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	OUTL(dev, POLL_DEMAND, DE4X5_TPD);
516*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
517*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
518*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (i >= TOUT_LOOP) {
519*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf("%s: tx buffer not ready\n", dev->name);
520*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			goto Done;
521*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
522*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
523*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
524*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) {
525*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status));
526*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
527*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tx_new = (tx_new+1) % NUM_TX_DESC;
528*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
529*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Done:
530*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return;
531*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
532*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
533*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM)
534*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* SROM Read and write routines.
535*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
536*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void
537*2439e4bfSJean-Christophe PLAGNIOL-VILLARD sendto_srom(struct eth_device* dev, u_int command, u_long addr)
538*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
539*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	OUTL(dev, command, addr);
540*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay(1);
541*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
542*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
543*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int
544*2439e4bfSJean-Christophe PLAGNIOL-VILLARD getfrom_srom(struct eth_device* dev, u_long addr)
545*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
546*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	s32 tmp;
547*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
548*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	tmp = INL(dev, addr);
549*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay(1);
550*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
551*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return tmp;
552*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
553*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
554*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Note: this routine returns extra data bits for size detection. */
555*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len)
556*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
557*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
558*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned retval = 0;
559*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int read_cmd = location | (SROM_READ_CMD << addr_len);
560*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
561*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
562*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
563*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
564*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM
565*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf(" EEPROM read at %d ", location);
566*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
567*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
568*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Shift the read command bits out. */
569*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 4 + addr_len; i >= 0; i--) {
570*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
571*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, ioaddr);
572*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay(10);
573*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, ioaddr);
574*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay(10);
575*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM2
576*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("%X", getfrom_srom(dev, ioaddr) & 15);
577*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
578*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0);
579*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
580*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
581*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
582*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
583*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM2
584*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf(" :%X:", getfrom_srom(dev, ioaddr) & 15);
585*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
586*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
587*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 16; i > 0; i--) {
588*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
589*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay(10);
590*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM2
591*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("%X", getfrom_srom(dev, ioaddr) & 15);
592*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
593*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0);
594*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
595*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay(10);
596*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
597*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
598*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Terminate the EEPROM access. */
599*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);
600*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
601*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM2
602*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf(" EEPROM value at %d is %5.5x.\n", location, retval);
603*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
604*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
605*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return retval;
606*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
607*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif	/* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */
608*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
609*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* This executes a generic EEPROM command, typically a write or write
610*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * enable. It returns the data output from the EEPROM, and thus may
611*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * also be used for reads.
612*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
613*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM)
614*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len)
615*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
616*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned retval = 0;
617*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
618*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM
619*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf(" EEPROM op 0x%x: ", cmd);
620*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
621*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
622*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	sendto_srom(dev,SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr);
623*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
624*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Shift the command bits out. */
625*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	do {
626*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
627*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		sendto_srom(dev,dataval, ioaddr);
628*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay(10);
629*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
630*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM2
631*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("%X", getfrom_srom(dev,ioaddr) & 15);
632*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
633*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
634*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		sendto_srom(dev,dataval | DT_CLK, ioaddr);
635*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay(10);
636*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		retval = (retval << 1) | ((getfrom_srom(dev,ioaddr) & EE_DATA_READ) ? 1 : 0);
637*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} while (--cmd_len >= 0);
638*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	sendto_srom(dev,SROM_RD | SROM_SR | DT_CS, ioaddr);
639*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
640*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Terminate the EEPROM access. */
641*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	sendto_srom(dev,SROM_RD | SROM_SR, ioaddr);
642*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
643*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM
644*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf(" EEPROM result is 0x%5.5x.\n", retval);
645*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
646*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
647*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return retval;
648*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
649*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif	/* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */
650*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
651*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_TULIP_FIX_DAVICOM
652*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int read_srom(struct eth_device *dev, u_long ioaddr, int index)
653*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
654*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
655*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
656*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return do_eeprom_cmd(dev, ioaddr,
657*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			     (((SROM_READ_CMD << ee_addr_size) | index) << 16)
658*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			     | 0xffff, 3 + ee_addr_size + 16);
659*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
660*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif	/* CONFIG_TULIP_FIX_DAVICOM */
661*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
662*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef UPDATE_SROM
663*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value)
664*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
665*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
666*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
667*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned short newval;
668*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
669*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay(10*1000); /* test-only */
670*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
671*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM
672*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf("ee_addr_size=%d.\n", ee_addr_size);
673*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index);
674*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
675*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
676*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Enable programming modes. */
677*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	do_eeprom_cmd(dev, ioaddr, (0x4f << (ee_addr_size-4)), 3+ee_addr_size);
678*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
679*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Do the actual write. */
680*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	do_eeprom_cmd(dev, ioaddr,
681*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		      (((SROM_WRITE_CMD<<ee_addr_size)|index) << 16) | new_value,
682*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		      3 + ee_addr_size + 16);
683*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
684*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Poll for write finished. */
685*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);
686*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 10000; i++)			/* Typical 2000 ticks */
687*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (getfrom_srom(dev, ioaddr) & EE_DATA_READ)
688*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			break;
689*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
690*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM
691*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf(" Write finished after %d ticks.\n", i);
692*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
693*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
694*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Disable programming. */
695*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size-4)), 3 + ee_addr_size);
696*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
697*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* And read the result. */
698*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	newval = do_eeprom_cmd(dev, ioaddr,
699*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			       (((SROM_READ_CMD<<ee_addr_size)|index) << 16)
700*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			       | 0xffff, 3 + ee_addr_size + 16);
701*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_SROM
702*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf("  New value at offset %d is %4.4x.\n", index, newval);
703*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
704*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 1;
705*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
706*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
707*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
708*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_TULIP_FIX_DAVICOM
709*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void read_hw_addr(struct eth_device *dev, bd_t *bis)
710*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
711*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u_short tmp, *p = (u_short *)(&dev->enetaddr[0]);
712*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i, j = 0;
713*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
714*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < (ETH_ALEN >> 1); i++) {
715*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		tmp = read_srom(dev, DE4X5_APROM, ((SROM_HWADD >> 1) + i));
716*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		*p = le16_to_cpu(tmp);
717*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		j += *p++;
718*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
719*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
720*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ((j == 0) || (j == 0x2fffd)) {
721*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		memset (dev->enetaddr, 0, ETH_ALEN);
722*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		debug ("Warning: can't read HW address from SROM.\n");
723*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		goto Done;
724*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
725*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
726*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return;
727*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
728*2439e4bfSJean-Christophe PLAGNIOL-VILLARD Done:
729*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef UPDATE_SROM
730*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	update_srom(dev, bis);
731*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
732*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return;
733*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
734*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif	/* CONFIG_TULIP_FIX_DAVICOM */
735*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
736*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef UPDATE_SROM
737*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void update_srom(struct eth_device *dev, bd_t *bis)
738*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
739*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
740*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	static unsigned short eeprom[0x40] = {
741*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x140b, 0x6610, 0x0000, 0x0000, 	/* 00 */
742*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x0000, 	/* 04 */
743*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x00a3, 0x0103, 0x0000, 0x0000,  	/* 08 */
744*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x1f00, 0x0000, 0x0000, 	/* 0c */
745*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0108, 0x038d, 0x0000, 0x0000,  	/* 10 */
746*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0xe078, 0x0001, 0x0040, 0x0018, 	/* 14 */
747*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x0000,  	/* 18 */
748*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x0000, 	/* 1c */
749*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x0000,  	/* 20 */
750*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x0000, 	/* 24 */
751*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x0000,  	/* 28 */
752*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x0000, 	/* 2c */
753*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x0000,  	/* 30 */
754*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x0000, 	/* 34 */
755*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x0000,  	/* 38 */
756*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		0x0000, 0x0000, 0x0000, 0x4e07,		/* 3c */
757*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	};
758*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
759*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Ethernet Addr... */
760*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	eeprom[0x0a] = ((bis->bi_enetaddr[1] & 0xff) << 8) | (bis->bi_enetaddr[0] & 0xff);
761*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	eeprom[0x0b] = ((bis->bi_enetaddr[3] & 0xff) << 8) | (bis->bi_enetaddr[2] & 0xff);
762*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	eeprom[0x0c] = ((bis->bi_enetaddr[5] & 0xff) << 8) | (bis->bi_enetaddr[4] & 0xff);
763*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
764*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i=0; i<0x40; i++)
765*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	{
766*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		write_srom(dev, DE4X5_APROM, i, eeprom[i]);
767*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
768*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
769*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif	/* UPDATE_SROM */
770*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
771*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
772