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