]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/net/dm9000x.c
DM9000 fix status check fail 0x6d error for trizeps board
[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
WD
57
58TODO: Homerun NIC and longrun NIC are not functional, only internal at the
59 moment.
60*/
61
62#include <common.h>
63#include <command.h>
64#include <net.h>
65#include <asm/io.h>
66
67#ifdef CONFIG_DRIVER_DM9000
68
69#include "dm9000x.h"
70
71/* Board/System/Debug information/definition ---------------- */
72
73#define DM9801_NOISE_FLOOR 0x08
74#define DM9802_NOISE_FLOOR 0x05
75
76/* #define CONFIG_DM9000_DEBUG */
77
78#ifdef CONFIG_DM9000_DEBUG
134e2662
RB
79#define DM9000_DBG(fmt,args...) printf(fmt, ##args)
80#define DM9000_DMP_PACKET(func,packet,length) \
81 do { \
82 int i; \
83 printf(func ": length: %d\n", length); \
84 for (i = 0; i < length; i++) { \
85 if (i % 8 == 0) \
86 printf("\n%s: %02x: ", func, i); \
87 printf("%02x ", ((unsigned char *) packet)[i]); \
88 } printf("\n"); \
89 } while(0)
90#else
281e00a3 91#define DM9000_DBG(fmt,args...)
134e2662
RB
92#define DM9000_DMP_PACKET(func,packet,length)
93#endif
94
281e00a3
WD
95enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD =
96 1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO =
97 8, DM9000_1M_HPNA = 0x10
98};
99enum DM9000_NIC_TYPE { FASTETHER_NIC = 0, HOMERUN_NIC = 1, LONGRUN_NIC = 2
100};
101
102/* Structure/enum declaration ------------------------------- */
103typedef struct board_info {
104 u32 runt_length_counter; /* counter: RX length < 64byte */
105 u32 long_length_counter; /* counter: RX length > 1514byte */
106 u32 reset_counter; /* counter: RESET */
107 u32 reset_tx_timeout; /* RESET caused by TX Timeout */
108 u32 reset_rx_status; /* RESET caused by RX Statsus wrong */
109 u16 tx_pkt_cnt;
110 u16 queue_start_addr;
111 u16 dbug_cnt;
112 u8 phy_addr;
113 u8 device_wait_reset; /* device state */
114 u8 nic_type; /* NIC type */
115 unsigned char srom[128];
0e38c938 116 void (*outblk)(volatile void *data_ptr, int count);
a101361b
RB
117 void (*inblk)(void *data_ptr, int count);
118 void (*rx_status)(u16 *RxStatus, u16 *RxLen);
98291e2e 119} board_info_t;
a101361b 120static board_info_t dm9000_info;
281e00a3
WD
121
122/* For module input parameter */
123static int media_mode = DM9000_AUTO;
124static u8 nfloor = 0;
125
126/* function declaration ------------------------------------- */
127int eth_init(bd_t * bd);
128int eth_send(volatile void *, int);
129int eth_rx(void);
130void eth_halt(void);
131static int dm9000_probe(void);
132static u16 phy_read(int);
133static void phy_write(int, u16);
5e5803e1 134u16 read_srom_word(int);
281e00a3
WD
135static u8 DM9000_ior(int);
136static void DM9000_iow(int reg, u8 value);
137
138/* DM9000 network board routine ---------------------------- */
139
140#define DM9000_outb(d,r) ( *(volatile u8 *)r = d )
141#define DM9000_outw(d,r) ( *(volatile u16 *)r = d )
142#define DM9000_outl(d,r) ( *(volatile u32 *)r = d )
143#define DM9000_inb(r) (*(volatile u8 *)r)
144#define DM9000_inw(r) (*(volatile u16 *)r)
145#define DM9000_inl(r) (*(volatile u32 *)r)
146
147#ifdef CONFIG_DM9000_DEBUG
148static void
149dump_regs(void)
150{
151 DM9000_DBG("\n");
152 DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0));
153 DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1));
154 DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2));
155 DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3));
156 DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
157 DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5));
158 DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6));
134e2662 159 DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
281e00a3
WD
160 DM9000_DBG("\n");
161}
a101361b
RB
162#endif
163
0e38c938 164static void dm9000_outblk_8bit(volatile void *data_ptr, int count)
a101361b
RB
165{
166 int i;
167 for (i = 0; i < count; i++)
168 DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
169}
170
0e38c938 171static void dm9000_outblk_16bit(volatile void *data_ptr, int count)
a101361b
RB
172{
173 int i;
174 u32 tmplen = (count + 1) / 2;
175
176 for (i = 0; i < tmplen; i++)
177 DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
178}
0e38c938 179static void dm9000_outblk_32bit(volatile void *data_ptr, int count)
a101361b
RB
180{
181 int i;
182 u32 tmplen = (count + 3) / 4;
183
184 for (i = 0; i < tmplen; i++)
185 DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
186}
187
188static void dm9000_inblk_8bit(void *data_ptr, int count)
189{
190 int i;
191 for (i = 0; i < count; i++)
192 ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
193}
194
195static void dm9000_inblk_16bit(void *data_ptr, int count)
196{
197 int i;
198 u32 tmplen = (count + 1) / 2;
199
200 for (i = 0; i < tmplen; i++)
201 ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
202}
203static void dm9000_inblk_32bit(void *data_ptr, int count)
204{
205 int i;
206 u32 tmplen = (count + 3) / 4;
207
208 for (i = 0; i < tmplen; i++)
209 ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
210}
211
212static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
213{
d6ee5fa4 214 u32 tmpdata;
a101361b
RB
215
216 DM9000_outb(DM9000_MRCMD, DM9000_IO);
217
d6ee5fa4 218 tmpdata = DM9000_inl(DM9000_DATA);
a101361b
RB
219 *RxStatus = tmpdata;
220 *RxLen = tmpdata >> 16;
221}
222
223static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen)
224{
225 DM9000_outb(DM9000_MRCMD, DM9000_IO);
226
227 *RxStatus = DM9000_inw(DM9000_DATA);
228 *RxLen = DM9000_inw(DM9000_DATA);
229}
230
231static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen)
232{
233 DM9000_outb(DM9000_MRCMD, DM9000_IO);
234
235 *RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
236 *RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
237}
281e00a3
WD
238
239/*
240 Search DM9000 board, allocate space and register it
241*/
242int
243dm9000_probe(void)
244{
245 u32 id_val;
246 id_val = DM9000_ior(DM9000_VIDL);
247 id_val |= DM9000_ior(DM9000_VIDH) << 8;
248 id_val |= DM9000_ior(DM9000_PIDL) << 16;
249 id_val |= DM9000_ior(DM9000_PIDH) << 24;
250 if (id_val == DM9000_ID) {
251 printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE,
252 id_val);
253 return 0;
254 } else {
255 printf("dm9000 not found at 0x%08x id: 0x%08x\n",
256 CONFIG_DM9000_BASE, id_val);
257 return -1;
258 }
259}
260
261/* Set PHY operationg mode
262*/
263static void
264set_PHY_mode(void)
265{
266 u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000;
267 if (!(media_mode & DM9000_AUTO)) {
268 switch (media_mode) {
269 case DM9000_10MHD:
270 phy_reg4 = 0x21;
271 phy_reg0 = 0x0000;
272 break;
273 case DM9000_10MFD:
274 phy_reg4 = 0x41;
275 phy_reg0 = 0x1100;
276 break;
277 case DM9000_100MHD:
278 phy_reg4 = 0x81;
279 phy_reg0 = 0x2000;
280 break;
281 case DM9000_100MFD:
282 phy_reg4 = 0x101;
283 phy_reg0 = 0x3100;
284 break;
285 }
286 phy_write(4, phy_reg4); /* Set PHY media mode */
287 phy_write(0, phy_reg0); /* Tmp */
288 }
289 DM9000_iow(DM9000_GPCR, 0x01); /* Let GPIO0 output */
290 DM9000_iow(DM9000_GPR, 0x00); /* Enable PHY */
291}
292
293/*
294 Init HomeRun DM9801
295*/
296static void
297program_dm9801(u16 HPNA_rev)
298{
299 __u16 reg16, reg17, reg24, reg25;
300 if (!nfloor)
301 nfloor = DM9801_NOISE_FLOOR;
302 reg16 = phy_read(16);
303 reg17 = phy_read(17);
304 reg24 = phy_read(24);
305 reg25 = phy_read(25);
306 switch (HPNA_rev) {
307 case 0xb900: /* DM9801 E3 */
308 reg16 |= 0x1000;
309 reg25 = ((reg24 + nfloor) & 0x00ff) | 0xf000;
310 break;
311 case 0xb901: /* DM9801 E4 */
312 reg25 = ((reg24 + nfloor) & 0x00ff) | 0xc200;
313 reg17 = (reg17 & 0xfff0) + nfloor + 3;
314 break;
315 case 0xb902: /* DM9801 E5 */
316 case 0xb903: /* DM9801 E6 */
317 default:
318 reg16 |= 0x1000;
319 reg25 = ((reg24 + nfloor - 3) & 0x00ff) | 0xc200;
320 reg17 = (reg17 & 0xfff0) + nfloor;
321 }
322 phy_write(16, reg16);
323 phy_write(17, reg17);
324 phy_write(25, reg25);
325}
326
327/*
328 Init LongRun DM9802
329*/
330static void
331program_dm9802(void)
332{
333 __u16 reg25;
334 if (!nfloor)
335 nfloor = DM9802_NOISE_FLOOR;
336 reg25 = phy_read(25);
337 reg25 = (reg25 & 0xff00) + nfloor;
338 phy_write(25, reg25);
339}
340
341/* Identify NIC type
342*/
343static void
344identify_nic(void)
345{
a101361b 346 struct board_info *db = &dm9000_info;
281e00a3
WD
347 u16 phy_reg3;
348 DM9000_iow(DM9000_NCR, NCR_EXT_PHY);
349 phy_reg3 = phy_read(3);
350 switch (phy_reg3 & 0xfff0) {
351 case 0xb900:
352 if (phy_read(31) == 0x4404) {
353 db->nic_type = HOMERUN_NIC;
354 program_dm9801(phy_reg3);
355 DM9000_DBG("found homerun NIC\n");
356 } else {
357 db->nic_type = LONGRUN_NIC;
358 DM9000_DBG("found longrun NIC\n");
359 program_dm9802();
360 }
361 break;
362 default:
363 db->nic_type = FASTETHER_NIC;
364 break;
365 }
366 DM9000_iow(DM9000_NCR, 0);
367}
368
369/* General Purpose dm9000 reset routine */
370static void
371dm9000_reset(void)
372{
fbcb7ece
RB
373 DM9000_DBG("resetting DM9000\n");
374
375 /* Reset DM9000,
376 see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
377
378 /* DEBUG: Make all GPIO pins outputs */
379 DM9000_iow(DM9000_GPCR, 0x0F);
380 /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
381 DM9000_iow(DM9000_GPR, 0);
382 /* Step 2: Software reset */
383 DM9000_iow(DM9000_NCR, 3);
384
385 do {
386 DM9000_DBG("resetting the DM9000, 1st reset\n");
387 udelay(25); /* Wait at least 20 us */
388 } while (DM9000_ior(DM9000_NCR) & 1);
389
390 DM9000_iow(DM9000_NCR, 0);
391 DM9000_iow(DM9000_NCR, 3); /* Issue a second reset */
392
393 do {
394 DM9000_DBG("resetting the DM9000, 2nd reset\n");
395 udelay(25); /* Wait at least 20 us */
396 } while (DM9000_ior(DM9000_NCR) & 1);
397
398 /* Check whether the ethernet controller is present */
399 if ((DM9000_ior(DM9000_PIDL) != 0x0) ||
400 (DM9000_ior(DM9000_PIDH) != 0x90))
401 printf("ERROR: resetting DM9000 -> not responding\n");
281e00a3
WD
402}
403
404/* Initilize dm9000 board
405*/
406int
407eth_init(bd_t * bd)
408{
409 int i, oft, lnk;
a101361b
RB
410 u8 io_mode;
411 struct board_info *db = &dm9000_info;
412
281e00a3
WD
413 DM9000_DBG("eth_init()\n");
414
415 /* RESET device */
416 dm9000_reset();
417 dm9000_probe();
418
a101361b
RB
419 /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
420 io_mode = DM9000_ior(DM9000_ISR) >> 6;
421
422 switch (io_mode) {
423 case 0x0: /* 16-bit mode */
424 printf("DM9000: running in 16 bit mode\n");
425 db->outblk = dm9000_outblk_16bit;
426 db->inblk = dm9000_inblk_16bit;
427 db->rx_status = dm9000_rx_status_16bit;
428 break;
429 case 0x01: /* 32-bit mode */
430 printf("DM9000: running in 32 bit mode\n");
431 db->outblk = dm9000_outblk_32bit;
432 db->inblk = dm9000_inblk_32bit;
433 db->rx_status = dm9000_rx_status_32bit;
434 break;
435 case 0x02: /* 8 bit mode */
436 printf("DM9000: running in 8 bit mode\n");
437 db->outblk = dm9000_outblk_8bit;
438 db->inblk = dm9000_inblk_8bit;
439 db->rx_status = dm9000_rx_status_8bit;
440 break;
441 default:
442 /* Assume 8 bit mode, will probably not work anyway */
443 printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
444 db->outblk = dm9000_outblk_8bit;
445 db->inblk = dm9000_inblk_8bit;
446 db->rx_status = dm9000_rx_status_8bit;
447 break;
448 }
449
281e00a3
WD
450 /* NIC Type: FASTETHER, HOMERUN, LONGRUN */
451 identify_nic();
452
453 /* GPIO0 on pre-activate PHY */
454 DM9000_iow(DM9000_GPR, 0x00); /*REG_1F bit0 activate phyxcer */
455
456 /* Set PHY */
457 set_PHY_mode();
458
98291e2e
RB
459 /* Program operating register, only intern phy supported by now */
460 DM9000_iow(DM9000_NCR, 0x0);
461 /* TX Polling clear */
462 DM9000_iow(DM9000_TCR, 0);
463 /* Less 3Kb, 200us */
464 DM9000_iow(DM9000_BPTR, 0x3f);
465 /* Flow Control : High/Low Water */
466 DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
467 /* SH FIXME: This looks strange! Flow Control */
468 DM9000_iow(DM9000_FCR, 0x0);
469 /* Special Mode */
470 DM9000_iow(DM9000_SMCR, 0);
471 /* clear TX status */
472 DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
473 /* Clear interrupt status */
474 DM9000_iow(DM9000_ISR, 0x0f);
281e00a3
WD
475
476 /* Set Node address */
477 for (i = 0; i < 6; i++)
478 ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
50cca8b9 479
5f470948
SB
480 if (is_zero_ether_addr(bd->bi_enetaddr) ||
481 is_multicast_ether_addr(bd->bi_enetaddr)) {
50cca8b9
MR
482 /* try reading from environment */
483 u8 i;
484 char *s, *e;
485 s = getenv ("ethaddr");
486 for (i = 0; i < 6; ++i) {
487 bd->bi_enetaddr[i] = s ?
488 simple_strtoul (s, &e, 16) : 0;
489 if (s)
490 s = (*e) ? e + 1 : e;
491 }
492 }
493
281e00a3
WD
494 printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
495 bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
496 bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
497 for (i = 0, oft = 0x10; i < 6; i++, oft++)
498 DM9000_iow(oft, bd->bi_enetaddr[i]);
499 for (i = 0, oft = 0x16; i < 8; i++, oft++)
500 DM9000_iow(oft, 0xff);
501
502 /* read back mac, just to be sure */
503 for (i = 0, oft = 0x10; i < 6; i++, oft++)
504 DM9000_DBG("%02x:", DM9000_ior(oft));
505 DM9000_DBG("\n");
506
507 /* Activate DM9000 */
98291e2e
RB
508 /* RX enable */
509 DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
510 /* Enable TX/RX interrupt mask */
511 DM9000_iow(DM9000_IMR, IMR_PAR);
512
281e00a3
WD
513 i = 0;
514 while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
515 udelay(1000);
516 i++;
517 if (i == 10000) {
518 printf("could not establish link\n");
519 return 0;
520 }
521 }
522
523 /* see what we've got */
524 lnk = phy_read(17) >> 12;
525 printf("operating at ");
526 switch (lnk) {
527 case 1:
528 printf("10M half duplex ");
529 break;
530 case 2:
531 printf("10M full duplex ");
532 break;
533 case 4:
534 printf("100M half duplex ");
535 break;
536 case 8:
537 printf("100M full duplex ");
538 break;
539 default:
540 printf("unknown: %d ", lnk);
541 break;
542 }
543 printf("mode\n");
544 return 0;
545}
546
547/*
548 Hardware start transmission.
549 Send a packet to media from the upper layer.
550*/
551int
552eth_send(volatile void *packet, int length)
553{
281e00a3 554 int tmo;
a101361b
RB
555 struct board_info *db = &dm9000_info;
556
134e2662 557 DM9000_DMP_PACKET("eth_send", packet, length);
281e00a3 558
acba3184
RB
559 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
560
281e00a3 561 /* Move data to DM9000 TX RAM */
acba3184 562 DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
281e00a3 563
a101361b 564 /* push the data to the TX-fifo */
0e38c938 565 (db->outblk)(packet, length);
281e00a3
WD
566
567 /* Set TX length to DM9000 */
568 DM9000_iow(DM9000_TXPLL, length & 0xff);
569 DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
570
571 /* Issue TX polling command */
acba3184 572 DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
281e00a3
WD
573
574 /* wait for end of transmission */
575 tmo = get_timer(0) + 5 * CFG_HZ;
acba3184
RB
576 while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
577 !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
281e00a3
WD
578 if (get_timer(0) >= tmo) {
579 printf("transmission timeout\n");
580 break;
581 }
582 }
acba3184
RB
583 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
584
281e00a3
WD
585 DM9000_DBG("transmit done\n\n");
586 return 0;
587}
588
589/*
590 Stop the interface.
591 The interface is stopped when it is brought.
592*/
593void
594eth_halt(void)
595{
596 DM9000_DBG("eth_halt\n");
597
598 /* RESET devie */
599 phy_write(0, 0x8000); /* PHY RESET */
600 DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
601 DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
602 DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
603}
604
605/*
606 Received a packet and pass to upper layer
607*/
608int
609eth_rx(void)
610{
611 u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
612 u16 RxStatus, RxLen = 0;
a101361b 613 struct board_info *db = &dm9000_info;
281e00a3 614
850ba755
RB
615 /* Check packet ready or not, we must check
616 the ISR status first for DM9000A */
617 if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
281e00a3
WD
618 return 0;
619
850ba755 620 DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
281e00a3 621
850ba755
RB
622 /* There is _at least_ 1 package in the fifo, read them all */
623 for (;;) {
624 DM9000_ior(DM9000_MRCMDX); /* Dummy read */
281e00a3 625
0e38c938
RB
626 /* Get most updated data,
627 only look at bits 0:1, See application notes DM9000 */
628 rxbyte = DM9000_inb(DM9000_DATA) & 0x03;
281e00a3 629
850ba755
RB
630 /* Status check: this byte must be 0 or 1 */
631 if (rxbyte > DM9000_PKT_RDY) {
632 DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
633 DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
634 printf("DM9000 error: status check fail: 0x%x\n",
635 rxbyte);
636 return 0;
637 }
281e00a3 638
850ba755
RB
639 if (rxbyte != DM9000_PKT_RDY)
640 return 0; /* No packet received, ignore */
641
642 DM9000_DBG("receiving packet\n");
643
644 /* A packet ready now & Get status/length */
645 (db->rx_status)(&RxStatus, &RxLen);
646
647 DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
648
649 /* Move data from DM9000 */
650 /* Read received packet from RX SRAM */
651 (db->inblk)(rdptr, RxLen);
652
653 if ((RxStatus & 0xbf00) || (RxLen < 0x40)
654 || (RxLen > DM9000_PKT_MAX)) {
655 if (RxStatus & 0x100) {
656 printf("rx fifo error\n");
657 }
658 if (RxStatus & 0x200) {
659 printf("rx crc error\n");
660 }
661 if (RxStatus & 0x8000) {
662 printf("rx length error\n");
663 }
664 if (RxLen > DM9000_PKT_MAX) {
665 printf("rx length too big\n");
666 dm9000_reset();
667 }
668 } else {
669 DM9000_DMP_PACKET("eth_rx", rdptr, RxLen);
281e00a3 670
850ba755
RB
671 DM9000_DBG("passing packet to upper layer\n");
672 NetReceive(NetRxPackets[0], RxLen);
281e00a3 673 }
281e00a3
WD
674 }
675 return 0;
676}
677
678/*
679 Read a word data from SROM
680*/
5e5803e1 681u16
281e00a3
WD
682read_srom_word(int offset)
683{
684 DM9000_iow(DM9000_EPAR, offset);
685 DM9000_iow(DM9000_EPCR, 0x4);
5f470948 686 udelay(8000);
281e00a3
WD
687 DM9000_iow(DM9000_EPCR, 0x0);
688 return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8));
689}
690
5e5803e1
SB
691void
692write_srom_word(int offset, u16 val)
693{
694 DM9000_iow(DM9000_EPAR, offset);
695 DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
696 DM9000_iow(DM9000_EPDRL, (val & 0xff));
697 DM9000_iow(DM9000_EPCR, 0x12);
698 udelay(8000);
699 DM9000_iow(DM9000_EPCR, 0);
700}
701
702
281e00a3
WD
703/*
704 Read a byte from I/O port
705*/
706static u8
707DM9000_ior(int reg)
708{
709 DM9000_outb(reg, DM9000_IO);
710 return DM9000_inb(DM9000_DATA);
711}
712
713/*
714 Write a byte to I/O port
715*/
716static void
717DM9000_iow(int reg, u8 value)
718{
719 DM9000_outb(reg, DM9000_IO);
720 DM9000_outb(value, DM9000_DATA);
721}
722
723/*
724 Read a word from phyxcer
725*/
726static u16
727phy_read(int reg)
728{
729 u16 val;
730
731 /* Fill the phyxcer register into REG_0C */
732 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
733 DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
98291e2e 734 udelay(100); /* Wait read complete */
281e00a3
WD
735 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
736 val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
737
738 /* The read data keeps on REG_0D & REG_0E */
134e2662 739 DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
281e00a3
WD
740 return val;
741}
742
743/*
744 Write a word to phyxcer
745*/
746static void
747phy_write(int reg, u16 value)
748{
749
750 /* Fill the phyxcer register into REG_0C */
751 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
752
753 /* Fill the written data into REG_0D & REG_0E */
754 DM9000_iow(DM9000_EPDRL, (value & 0xff));
755 DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
756 DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
98291e2e 757 udelay(500); /* Wait write complete */
281e00a3 758 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
134e2662 759 DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
281e00a3 760}
98291e2e 761#endif /* CONFIG_DRIVER_DM9000 */