]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/net/dm9000x.c
rename CFG_ macros to CONFIG_SYS
[people/ms/u-boot.git] / drivers / net / dm9000x.c
CommitLineData
281e00a3
WD
1/*
2 dm9000.c: Version 1.2 12/15/2003
3
4 A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.
5 Copyright (C) 1997 Sten Wang
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
18
19V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match
53677ef1
WD
20 06/22/2001 Support DM9801 progrmming
21 E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
22 E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
23 R17 = (R17 & 0xfff0) | NF + 3
24 E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
25 R17 = (R17 & 0xfff0) | NF
26
27v1.00 modify by simon 2001.9.5
281e00a3
WD
28 change for kernel 2.4.x
29
53677ef1 30v1.1 11/09/2001 fix force mode bug
281e00a3
WD
31
32v1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>:
33 Fixed phy reset.
34 Added tx/rx 32 bit mode.
35 Cleaned up for kernel merge.
36
37--------------------------------------
38
a101361b
RB
39 12/15/2003 Initial port to u-boot by
40 Sascha Hauer <saschahauer@web.de>
41
42 06/03/2008 Remy Bohmer <linux@bohmer.net>
850ba755
RB
43 - Fixed the driver to work with DM9000A.
44 (check on ISR receive status bit before reading the
45 FIFO as described in DM9000 programming guide and
46 application notes)
a101361b 47 - Added autodetect of databus width.
134e2662 48 - Made debug code compile again.
acba3184
RB
49 - Adapt eth_send such that it matches the DM9000*
50 application notes. Needed to make it work properly
51 for DM9000A.
fbcb7ece
RB
52 - Adapted reset procedure to match DM9000 application
53 notes (i.e. double reset)
98291e2e 54 - some minor code cleanups
a101361b
RB
55 These changes are tested with DM9000{A,EP,E} together
56 with a 200MHz Atmel AT91SAM92161 core
281e00a3 57
d26b739a 58TODO: external MII is not functional, only internal at the moment.
281e00a3
WD
59*/
60
61#include <common.h>
62#include <command.h>
63#include <net.h>
64#include <asm/io.h>
65
281e00a3
WD
66#include "dm9000x.h"
67
68/* Board/System/Debug information/definition ---------------- */
69
281e00a3
WD
70/* #define CONFIG_DM9000_DEBUG */
71
72#ifdef CONFIG_DM9000_DEBUG
134e2662
RB
73#define DM9000_DBG(fmt,args...) printf(fmt, ##args)
74#define DM9000_DMP_PACKET(func,packet,length) \
75 do { \
76 int i; \
77 printf(func ": length: %d\n", length); \
78 for (i = 0; i < length; i++) { \
79 if (i % 8 == 0) \
80 printf("\n%s: %02x: ", func, i); \
81 printf("%02x ", ((unsigned char *) packet)[i]); \
82 } printf("\n"); \
83 } while(0)
84#else
281e00a3 85#define DM9000_DBG(fmt,args...)
134e2662
RB
86#define DM9000_DMP_PACKET(func,packet,length)
87#endif
88
281e00a3
WD
89/* Structure/enum declaration ------------------------------- */
90typedef struct board_info {
91 u32 runt_length_counter; /* counter: RX length < 64byte */
92 u32 long_length_counter; /* counter: RX length > 1514byte */
93 u32 reset_counter; /* counter: RESET */
94 u32 reset_tx_timeout; /* RESET caused by TX Timeout */
95 u32 reset_rx_status; /* RESET caused by RX Statsus wrong */
96 u16 tx_pkt_cnt;
97 u16 queue_start_addr;
98 u16 dbug_cnt;
99 u8 phy_addr;
100 u8 device_wait_reset; /* device state */
281e00a3 101 unsigned char srom[128];
0e38c938 102 void (*outblk)(volatile void *data_ptr, int count);
a101361b
RB
103 void (*inblk)(void *data_ptr, int count);
104 void (*rx_status)(u16 *RxStatus, u16 *RxLen);
98291e2e 105} board_info_t;
a101361b 106static board_info_t dm9000_info;
281e00a3 107
281e00a3
WD
108/* function declaration ------------------------------------- */
109int eth_init(bd_t * bd);
110int eth_send(volatile void *, int);
111int eth_rx(void);
112void eth_halt(void);
113static int dm9000_probe(void);
114static u16 phy_read(int);
115static void phy_write(int, u16);
5e5803e1 116u16 read_srom_word(int);
281e00a3
WD
117static u8 DM9000_ior(int);
118static void DM9000_iow(int reg, u8 value);
119
120/* DM9000 network board routine ---------------------------- */
121
122#define DM9000_outb(d,r) ( *(volatile u8 *)r = d )
123#define DM9000_outw(d,r) ( *(volatile u16 *)r = d )
124#define DM9000_outl(d,r) ( *(volatile u32 *)r = d )
125#define DM9000_inb(r) (*(volatile u8 *)r)
126#define DM9000_inw(r) (*(volatile u16 *)r)
127#define DM9000_inl(r) (*(volatile u32 *)r)
128
129#ifdef CONFIG_DM9000_DEBUG
130static void
131dump_regs(void)
132{
133 DM9000_DBG("\n");
134 DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0));
135 DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1));
136 DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2));
137 DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3));
138 DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
139 DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5));
140 DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6));
134e2662 141 DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
281e00a3
WD
142 DM9000_DBG("\n");
143}
a101361b
RB
144#endif
145
0e38c938 146static void dm9000_outblk_8bit(volatile void *data_ptr, int count)
a101361b
RB
147{
148 int i;
149 for (i = 0; i < count; i++)
150 DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
151}
152
0e38c938 153static void dm9000_outblk_16bit(volatile void *data_ptr, int count)
a101361b
RB
154{
155 int i;
156 u32 tmplen = (count + 1) / 2;
157
158 for (i = 0; i < tmplen; i++)
159 DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
160}
0e38c938 161static void dm9000_outblk_32bit(volatile void *data_ptr, int count)
a101361b
RB
162{
163 int i;
164 u32 tmplen = (count + 3) / 4;
165
166 for (i = 0; i < tmplen; i++)
167 DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
168}
169
170static void dm9000_inblk_8bit(void *data_ptr, int count)
171{
172 int i;
173 for (i = 0; i < count; i++)
174 ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
175}
176
177static void dm9000_inblk_16bit(void *data_ptr, int count)
178{
179 int i;
180 u32 tmplen = (count + 1) / 2;
181
182 for (i = 0; i < tmplen; i++)
183 ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
184}
185static void dm9000_inblk_32bit(void *data_ptr, int count)
186{
187 int i;
188 u32 tmplen = (count + 3) / 4;
189
190 for (i = 0; i < tmplen; i++)
191 ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
192}
193
194static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
195{
d6ee5fa4 196 u32 tmpdata;
a101361b
RB
197
198 DM9000_outb(DM9000_MRCMD, DM9000_IO);
199
d6ee5fa4 200 tmpdata = DM9000_inl(DM9000_DATA);
943b825b
TL
201 *RxStatus = __le16_to_cpu(tmpdata);
202 *RxLen = __le16_to_cpu(tmpdata >> 16);
a101361b
RB
203}
204
205static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen)
206{
207 DM9000_outb(DM9000_MRCMD, DM9000_IO);
208
943b825b
TL
209 *RxStatus = __le16_to_cpu(DM9000_inw(DM9000_DATA));
210 *RxLen = __le16_to_cpu(DM9000_inw(DM9000_DATA));
a101361b
RB
211}
212
213static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen)
214{
215 DM9000_outb(DM9000_MRCMD, DM9000_IO);
216
943b825b
TL
217 *RxStatus =
218 __le16_to_cpu(DM9000_inb(DM9000_DATA) +
219 (DM9000_inb(DM9000_DATA) << 8));
220 *RxLen =
221 __le16_to_cpu(DM9000_inb(DM9000_DATA) +
222 (DM9000_inb(DM9000_DATA) << 8));
a101361b 223}
281e00a3
WD
224
225/*
226 Search DM9000 board, allocate space and register it
227*/
228int
229dm9000_probe(void)
230{
231 u32 id_val;
232 id_val = DM9000_ior(DM9000_VIDL);
233 id_val |= DM9000_ior(DM9000_VIDH) << 8;
234 id_val |= DM9000_ior(DM9000_PIDL) << 16;
235 id_val |= DM9000_ior(DM9000_PIDH) << 24;
236 if (id_val == DM9000_ID) {
237 printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE,
238 id_val);
239 return 0;
240 } else {
241 printf("dm9000 not found at 0x%08x id: 0x%08x\n",
242 CONFIG_DM9000_BASE, id_val);
243 return -1;
244 }
245}
246
281e00a3
WD
247/* General Purpose dm9000 reset routine */
248static void
249dm9000_reset(void)
250{
fbcb7ece
RB
251 DM9000_DBG("resetting DM9000\n");
252
253 /* Reset DM9000,
254 see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
255
d26b739a
AD
256 /* DEBUG: Make all GPIO0 outputs, all others inputs */
257 DM9000_iow(DM9000_GPCR, GPCR_GPIO0_OUT);
fbcb7ece
RB
258 /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
259 DM9000_iow(DM9000_GPR, 0);
260 /* Step 2: Software reset */
d26b739a 261 DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
fbcb7ece
RB
262
263 do {
264 DM9000_DBG("resetting the DM9000, 1st reset\n");
265 udelay(25); /* Wait at least 20 us */
266 } while (DM9000_ior(DM9000_NCR) & 1);
267
268 DM9000_iow(DM9000_NCR, 0);
d26b739a 269 DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST)); /* Issue a second reset */
fbcb7ece
RB
270
271 do {
272 DM9000_DBG("resetting the DM9000, 2nd reset\n");
273 udelay(25); /* Wait at least 20 us */
274 } while (DM9000_ior(DM9000_NCR) & 1);
275
276 /* Check whether the ethernet controller is present */
277 if ((DM9000_ior(DM9000_PIDL) != 0x0) ||
278 (DM9000_ior(DM9000_PIDH) != 0x90))
279 printf("ERROR: resetting DM9000 -> not responding\n");
281e00a3
WD
280}
281
282/* Initilize dm9000 board
283*/
284int
285eth_init(bd_t * bd)
286{
287 int i, oft, lnk;
a101361b
RB
288 u8 io_mode;
289 struct board_info *db = &dm9000_info;
290
281e00a3
WD
291 DM9000_DBG("eth_init()\n");
292
293 /* RESET device */
294 dm9000_reset();
d26b739a
AD
295
296 if (dm9000_probe() < 0)
297 return -1;
281e00a3 298
a101361b
RB
299 /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
300 io_mode = DM9000_ior(DM9000_ISR) >> 6;
301
302 switch (io_mode) {
303 case 0x0: /* 16-bit mode */
304 printf("DM9000: running in 16 bit mode\n");
305 db->outblk = dm9000_outblk_16bit;
306 db->inblk = dm9000_inblk_16bit;
307 db->rx_status = dm9000_rx_status_16bit;
308 break;
309 case 0x01: /* 32-bit mode */
310 printf("DM9000: running in 32 bit mode\n");
311 db->outblk = dm9000_outblk_32bit;
312 db->inblk = dm9000_inblk_32bit;
313 db->rx_status = dm9000_rx_status_32bit;
314 break;
315 case 0x02: /* 8 bit mode */
316 printf("DM9000: running in 8 bit mode\n");
317 db->outblk = dm9000_outblk_8bit;
318 db->inblk = dm9000_inblk_8bit;
319 db->rx_status = dm9000_rx_status_8bit;
320 break;
321 default:
322 /* Assume 8 bit mode, will probably not work anyway */
323 printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
324 db->outblk = dm9000_outblk_8bit;
325 db->inblk = dm9000_inblk_8bit;
326 db->rx_status = dm9000_rx_status_8bit;
327 break;
328 }
329
d26b739a 330 /* Program operating register, only internal phy supported */
98291e2e
RB
331 DM9000_iow(DM9000_NCR, 0x0);
332 /* TX Polling clear */
333 DM9000_iow(DM9000_TCR, 0);
334 /* Less 3Kb, 200us */
d26b739a 335 DM9000_iow(DM9000_BPTR, BPTR_BPHW(3) | BPTR_JPT_600US);
98291e2e
RB
336 /* Flow Control : High/Low Water */
337 DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
338 /* SH FIXME: This looks strange! Flow Control */
339 DM9000_iow(DM9000_FCR, 0x0);
340 /* Special Mode */
341 DM9000_iow(DM9000_SMCR, 0);
342 /* clear TX status */
343 DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
344 /* Clear interrupt status */
d26b739a 345 DM9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);
281e00a3
WD
346
347 /* Set Node address */
d26b739a 348#if !defined(CONFIG_AT91SAM9261EK)
281e00a3
WD
349 for (i = 0; i < 6; i++)
350 ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
d99a8ff6 351#endif
50cca8b9 352
5f470948
SB
353 if (is_zero_ether_addr(bd->bi_enetaddr) ||
354 is_multicast_ether_addr(bd->bi_enetaddr)) {
50cca8b9
MR
355 /* try reading from environment */
356 u8 i;
357 char *s, *e;
358 s = getenv ("ethaddr");
359 for (i = 0; i < 6; ++i) {
360 bd->bi_enetaddr[i] = s ?
361 simple_strtoul (s, &e, 16) : 0;
362 if (s)
363 s = (*e) ? e + 1 : e;
364 }
365 }
366
281e00a3
WD
367 printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
368 bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
369 bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
d26b739a
AD
370
371 /* fill device MAC address registers */
372 for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
281e00a3
WD
373 DM9000_iow(oft, bd->bi_enetaddr[i]);
374 for (i = 0, oft = 0x16; i < 8; i++, oft++)
375 DM9000_iow(oft, 0xff);
376
377 /* read back mac, just to be sure */
378 for (i = 0, oft = 0x10; i < 6; i++, oft++)
379 DM9000_DBG("%02x:", DM9000_ior(oft));
380 DM9000_DBG("\n");
381
382 /* Activate DM9000 */
98291e2e
RB
383 /* RX enable */
384 DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
385 /* Enable TX/RX interrupt mask */
386 DM9000_iow(DM9000_IMR, IMR_PAR);
387
281e00a3
WD
388 i = 0;
389 while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
390 udelay(1000);
391 i++;
392 if (i == 10000) {
393 printf("could not establish link\n");
394 return 0;
395 }
396 }
397
398 /* see what we've got */
399 lnk = phy_read(17) >> 12;
400 printf("operating at ");
401 switch (lnk) {
402 case 1:
403 printf("10M half duplex ");
404 break;
405 case 2:
406 printf("10M full duplex ");
407 break;
408 case 4:
409 printf("100M half duplex ");
410 break;
411 case 8:
412 printf("100M full duplex ");
413 break;
414 default:
415 printf("unknown: %d ", lnk);
416 break;
417 }
418 printf("mode\n");
419 return 0;
420}
421
422/*
423 Hardware start transmission.
424 Send a packet to media from the upper layer.
425*/
426int
427eth_send(volatile void *packet, int length)
428{
281e00a3 429 int tmo;
a101361b
RB
430 struct board_info *db = &dm9000_info;
431
134e2662 432 DM9000_DMP_PACKET("eth_send", packet, length);
281e00a3 433
acba3184
RB
434 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
435
281e00a3 436 /* Move data to DM9000 TX RAM */
acba3184 437 DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
281e00a3 438
a101361b 439 /* push the data to the TX-fifo */
0e38c938 440 (db->outblk)(packet, length);
281e00a3
WD
441
442 /* Set TX length to DM9000 */
443 DM9000_iow(DM9000_TXPLL, length & 0xff);
444 DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
445
446 /* Issue TX polling command */
acba3184 447 DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
281e00a3
WD
448
449 /* wait for end of transmission */
6d0f6bcf 450 tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
acba3184
RB
451 while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
452 !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
281e00a3
WD
453 if (get_timer(0) >= tmo) {
454 printf("transmission timeout\n");
455 break;
456 }
457 }
acba3184
RB
458 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
459
281e00a3
WD
460 DM9000_DBG("transmit done\n\n");
461 return 0;
462}
463
464/*
465 Stop the interface.
466 The interface is stopped when it is brought.
467*/
468void
469eth_halt(void)
470{
471 DM9000_DBG("eth_halt\n");
472
473 /* RESET devie */
474 phy_write(0, 0x8000); /* PHY RESET */
475 DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
476 DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
477 DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
478}
479
480/*
481 Received a packet and pass to upper layer
482*/
483int
484eth_rx(void)
485{
486 u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
487 u16 RxStatus, RxLen = 0;
a101361b 488 struct board_info *db = &dm9000_info;
281e00a3 489
850ba755
RB
490 /* Check packet ready or not, we must check
491 the ISR status first for DM9000A */
492 if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
281e00a3
WD
493 return 0;
494
850ba755 495 DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
281e00a3 496
850ba755
RB
497 /* There is _at least_ 1 package in the fifo, read them all */
498 for (;;) {
499 DM9000_ior(DM9000_MRCMDX); /* Dummy read */
281e00a3 500
0e38c938
RB
501 /* Get most updated data,
502 only look at bits 0:1, See application notes DM9000 */
503 rxbyte = DM9000_inb(DM9000_DATA) & 0x03;
281e00a3 504
850ba755
RB
505 /* Status check: this byte must be 0 or 1 */
506 if (rxbyte > DM9000_PKT_RDY) {
507 DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
508 DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
509 printf("DM9000 error: status check fail: 0x%x\n",
510 rxbyte);
511 return 0;
512 }
281e00a3 513
850ba755
RB
514 if (rxbyte != DM9000_PKT_RDY)
515 return 0; /* No packet received, ignore */
516
517 DM9000_DBG("receiving packet\n");
518
519 /* A packet ready now & Get status/length */
520 (db->rx_status)(&RxStatus, &RxLen);
521
522 DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
523
524 /* Move data from DM9000 */
525 /* Read received packet from RX SRAM */
526 (db->inblk)(rdptr, RxLen);
527
528 if ((RxStatus & 0xbf00) || (RxLen < 0x40)
529 || (RxLen > DM9000_PKT_MAX)) {
530 if (RxStatus & 0x100) {
531 printf("rx fifo error\n");
532 }
533 if (RxStatus & 0x200) {
534 printf("rx crc error\n");
535 }
536 if (RxStatus & 0x8000) {
537 printf("rx length error\n");
538 }
539 if (RxLen > DM9000_PKT_MAX) {
540 printf("rx length too big\n");
541 dm9000_reset();
542 }
543 } else {
544 DM9000_DMP_PACKET("eth_rx", rdptr, RxLen);
281e00a3 545
850ba755
RB
546 DM9000_DBG("passing packet to upper layer\n");
547 NetReceive(NetRxPackets[0], RxLen);
281e00a3 548 }
281e00a3
WD
549 }
550 return 0;
551}
552
553/*
554 Read a word data from SROM
555*/
5e5803e1 556u16
281e00a3
WD
557read_srom_word(int offset)
558{
559 DM9000_iow(DM9000_EPAR, offset);
560 DM9000_iow(DM9000_EPCR, 0x4);
5f470948 561 udelay(8000);
281e00a3
WD
562 DM9000_iow(DM9000_EPCR, 0x0);
563 return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8));
564}
565
5e5803e1
SB
566void
567write_srom_word(int offset, u16 val)
568{
569 DM9000_iow(DM9000_EPAR, offset);
570 DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
571 DM9000_iow(DM9000_EPDRL, (val & 0xff));
572 DM9000_iow(DM9000_EPCR, 0x12);
573 udelay(8000);
574 DM9000_iow(DM9000_EPCR, 0);
575}
576
577
281e00a3
WD
578/*
579 Read a byte from I/O port
580*/
581static u8
582DM9000_ior(int reg)
583{
584 DM9000_outb(reg, DM9000_IO);
585 return DM9000_inb(DM9000_DATA);
586}
587
588/*
589 Write a byte to I/O port
590*/
591static void
592DM9000_iow(int reg, u8 value)
593{
594 DM9000_outb(reg, DM9000_IO);
595 DM9000_outb(value, DM9000_DATA);
596}
597
598/*
599 Read a word from phyxcer
600*/
601static u16
602phy_read(int reg)
603{
604 u16 val;
605
606 /* Fill the phyxcer register into REG_0C */
607 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
608 DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
98291e2e 609 udelay(100); /* Wait read complete */
281e00a3
WD
610 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
611 val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
612
613 /* The read data keeps on REG_0D & REG_0E */
134e2662 614 DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
281e00a3
WD
615 return val;
616}
617
618/*
619 Write a word to phyxcer
620*/
621static void
622phy_write(int reg, u16 value)
623{
624
625 /* Fill the phyxcer register into REG_0C */
626 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
627
628 /* Fill the written data into REG_0D & REG_0E */
629 DM9000_iow(DM9000_EPDRL, (value & 0xff));
630 DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
631 DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
98291e2e 632 udelay(500); /* Wait write complete */
281e00a3 633 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
134e2662 634 DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
281e00a3 635}