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