Changeset a2117cd6 in rtems
- Timestamp:
- 09/07/02 23:09:47 (20 years ago)
- Branches:
- 4.10, 4.11, 4.8, 4.9, 5, master
- Children:
- 4e7ba21
- Parents:
- 19ed3cf
- Location:
- c/src/libchip
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/libchip/ChangeLog
r19ed3cf ra2117cd6 1 2002-09-07 Chris Johns <ccj@acm.org> 2 3 * network/Makefile.am, network/README.cs8900, network/cs8900.c, 4 network/cs8900.h: Significant update which corrects the problem 5 where the cs8900.c file was actually the BSP glue. Joel did 6 some hacking so this file will compile. Previously it required 7 providing a target.h file to compile. 8 * network/cs8900.c.bsp: New file. 9 1 10 2002-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de> 2 11 -
c/src/libchip/network/Makefile.am
r19ed3cf ra2117cd6 9 9 LIB = $(ARCH)/$(LIBNAME).a 10 10 11 # add cs8900.c to work with it and make it compile 12 C_FILES = dec21140.c i82586.c sonic.c if_fxp.c 11 C_FILES = cs8900.c dec21140.c i82586.c sonic.c if_fxp.c 13 12 C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.$(OBJEXT)) 14 13 … … 53 52 54 53 EXTRA_DIST = README README.cs8900 README.dec21140 README.i82586 README.sonic \ 55 cs8900.c dec21140.c i82586.c if_fxp.c sonic.c54 cs8900.c cs8900.c.bsp dec21140.c i82586.c if_fxp.c sonic.c 56 55 57 56 include $(top_srcdir)/../../../automake/local.am -
c/src/libchip/network/README.cs8900
r19ed3cf ra2117cd6 2 2 # $Id$ 3 3 # 4 5 Target Support 6 ============== 7 8 The target is required to provide the low level support routines as 9 listed in the Configuration section of this file. 10 11 The file cs8900.c.bsp is an example BSP file for a Coldfire processor. 4 12 5 13 Conditionals -
c/src/libchip/network/cs8900.c
r19ed3cf ra2117cd6 11 11 COPYRIGHT (c) 1989-1998. 12 12 On-Line Applications Research Corporation (OAR). 13 Copyright assigned to U.S. Government, 1994. 13 14 14 15 The license and distribution terms for this file may be 15 16 found in the file LICENSE in this distribution or at 16 17 http://www.OARcorp.com/rtems/license.html. 17 18 18 19 ------------------------------------------------------------------------ 19 20 20 21 CS8900 net boot driver. 21 22 23 */ 24 25 #include <sys/errno.h> 26 #include <string.h> 27 #include <stdio.h> 28 29 /* #include <target.h> 30 chris explain what this is to contain and provide a default one */ 31 #include "cs8900.h" 32 33 /*********************************************************** 34 *********************************************************** 35 BEGIN SECTION OF DEFAULT DEFINES 36 *********************************************************** 37 ***********************************************************/ 38 39 /* 40 * Number of devices supported by this driver 22 41 */ 23 24 #include <rtems/bspIo.h> 25 #include <rtems.h> 26 27 #include <libchip/cs8900.h> 42 #ifndef CS8900_DEVICES 43 #define CS8900_DEVICES 1 44 #endif 45 46 /* 47 * This variable really should come from a per device configuration 48 * table so the base can vary by adapter. 49 */ 50 51 #ifndef CS8900_IO_BASE 52 extern unsigned int bsp_cs8900_io_base; 53 #define CS8900_IO_BASE bsp_cs8900_io_base 54 #endif 55 56 /* 57 * This variable really should come from a per device configuration 58 * table so the base can vary by adapter. 59 */ 60 61 #ifndef CS8900_MEMORY_BASE 62 extern unsigned int bsp_cs8900_memory_base; 63 #define CS8900_MEMORY_BASE bsp_cs8900_memory_base 64 #endif 65 66 /* 67 * This could go to a BSP provided callout. 68 */ 69 #ifndef WATCHDOG_TOGGLE 70 #define WATCHDOG_TOGGLE() 71 #endif 72 73 /* 74 * This variable really should come from a per device configuration 75 * table so the base can vary by adapter. 76 * 77 * chris this is probably not a good default --joel 78 */ 79 80 #ifndef CS8900_RX_QUEUE_SIZE 81 #define CS8900_RX_QUEUE_SIZE 1 82 #endif 83 84 /*********************************************************** 85 *********************************************************** 86 END SECTION OF DEFAULT DEFINES 87 *********************************************************** 88 ***********************************************************/ 89 90 /* 91 * We expect to be able to read a complete packet into an mbuf. 92 */ 93 94 #if (MCLBYTES < 1520) 95 #error "CS8900 Driver must have MCLBYTES >= 1520" 96 #endif 97 98 /* 99 * Task event usage. 100 */ 101 102 #define CS8900_RX_OK_EVENT RTEMS_EVENT_1 103 #define CS8900_TX_START_EVENT RTEMS_EVENT_1 104 #define CS8900_TX_OK_EVENT RTEMS_EVENT_2 105 #define CS8900_TX_WAIT_EVENT RTEMS_EVENT_3 28 106 29 107 /* … … 31 109 */ 32 110 33 #ifdef CS8900_VERBOSE 34 static BOOLEAN cs8900_io_verbose; 111 static cs8900_device cs8900[CS8900_DEVICES]; 112 113 /* 114 * IO Packet Page inteface. 115 */ 116 117 static inline unsigned short 118 io_pp_get_reg_16 (int dev, unsigned short reg) 119 { 120 cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR, 121 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); 122 return cs8900_io_get_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0); 123 } 124 125 static inline unsigned long 126 io_pp_get_reg_32 (int dev, unsigned short reg) 127 { 128 cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR, 129 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); 130 return ((cs8900_io_get_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0) << 16) | 131 cs8900_io_get_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT1)); 132 } 133 134 static inline void 135 io_pp_set_reg_16 (int dev, unsigned short reg, unsigned short data) 136 { 137 cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR, 138 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); 139 cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0, data); 140 } 141 142 static inline void 143 io_pp_set_reg_32 (int dev, unsigned short reg, unsigned long data) 144 { 145 cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PACKET_PAGE_PTR, 146 0x3000 | CS8900_PPP_AUTO_INCREMENT | reg); 147 cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT0, data >> 16); 148 cs8900_io_set_reg (dev, CS8900_IO_BASE + CS8900_IO_PP_DATA_PORT1, data); 149 } 150 151 static inline void 152 io_pp_bit_set_reg_16 (int dev, unsigned short reg, unsigned short mask) 153 { 154 io_pp_set_reg_16 (dev, reg, io_pp_get_reg_16 (dev, reg) | mask); 155 } 156 157 static inline void 158 io_pp_bit_clear_reg_16 (int dev, unsigned short reg, unsigned short mask) 159 { 160 io_pp_set_reg_16 (dev, reg, io_pp_get_reg_16 (dev, reg) & ~mask); 161 } 162 163 /* 164 * Memory Mapped Packet Page interface. 165 */ 166 167 static inline unsigned short 168 mem_pp_get_reg (int dev, unsigned short reg) 169 { 170 return cs8900_mem_get_reg (dev, CS8900_MEMORY_BASE + reg); 171 } 172 173 static inline void 174 mem_pp_set_reg (int dev, unsigned short reg, unsigned short data) 175 { 176 cs8900_mem_set_reg (dev, CS8900_MEMORY_BASE + reg, data); 177 } 178 179 static inline void 180 mem_pp_bit_set_reg (int dev, unsigned short reg, unsigned short mask) 181 { 182 mem_pp_set_reg (dev, reg, mem_pp_get_reg (dev, reg) | mask); 183 } 184 185 static inline void 186 mem_pp_bit_clear_reg (int dev, unsigned short reg, unsigned short mask) 187 { 188 mem_pp_set_reg (dev, reg, mem_pp_get_reg (dev, reg) & ~mask); 189 } 190 191 /* 192 * Trace defines and control structures. 193 */ 194 195 #define CS8900_T_INT (0) 196 #define CS8900_T_RX_OK (1) 197 #define CS8900_T_RX_DROPPED (2) 198 #define CS8900_T_NO_MBUF (3) 199 #define CS8900_T_NO_CLUSTERS (4) 200 #define CS8900_T_RX_BEGIN (5) 201 #define CS8900_T_RX_END (6) 202 203 #if CS8900_TRACE 204 205 static const char *cs8900_trace_labels[] = 206 { 207 "int", 208 "rx ok", 209 "rx dropped", 210 "no mbuf", 211 "no clusters", 212 "rx begin", 213 "rx end" 214 }; 215 216 /* 217 * Assumes a micro-second timer such as the Coldfire. 218 */ 219 220 rtems_unsigned32 rtems_read_timer (); 221 222 static inline void 223 cs8900_trace (cs8900_device *cs, unsigned short key, unsigned long var) 224 { 225 rtems_interrupt_level level; 226 227 rtems_interrupt_disable (level); 228 229 if (cs->trace_in < CS8900_TRACE_SIZE) 230 { 231 cs->trace_key[cs->trace_in] = key; 232 cs->trace_var[cs->trace_in] = var; 233 cs->trace_time[cs->trace_in] = rtems_read_timer (); 234 cs->trace_in++; 235 } 236 237 rtems_interrupt_enable (level); 238 } 239 #else 240 #define cs8900_trace(c, k, v) 35 241 #endif 36 242 37 static rtems_isr_void_entry old_handler[CS8900_DEVICES]; 38 static void *old_parameter[CS8900_DEVICES]; 39 40 /* 41 * Tables of IO addresses and interrupt levels for each device attached. 243 /* 244 * Bring the chip online. 42 245 */ 43 246 44 static const unsigned long ethernet_io_base[CS8900_DEVICES] = 45 { 46 ETHERNET_BASE 247 static void 248 cs8900_hardware_init (cs8900_device *cs) 249 { 250 unsigned long prod_id; 251 unsigned short status; 252 int dev = cs->dev; 253 254 /* 255 * Do nothing while the device is calibrating and checking the EEPROM. 256 * We must wait 20msecs. 257 */ 258 259 io_pp_bit_set_reg_16 (dev, CS8900_PP_SelfCTL, CS8900_SELF_CTRL_RESET); 260 261 rtems_task_wake_after (TOD_MILLISECONDS_TO_TICKS (20)); 262 263 status = io_pp_get_reg_16 (dev, CS8900_PP_SelfST); 264 265 if (((status & CS8900_SELF_STATUS_INITD) == 0) || 266 ((status & CS8900_SELF_STATUS_INITD) && 267 (status & CS8900_SELF_STATUS_EEPROM_PRESENT) && 268 (status & CS8900_SELF_STATUS_SIBUST))) 269 { 270 printf ("CS8900: %s. Initialisation aborted.\n", 271 (status & CS8900_SELF_STATUS_INITD) ? 272 "EEPROM read/write failed to complete" : 273 "Failed to complete to reset"); 274 return; 275 } 276 277 /* Probe the device for its ID */ 278 279 prod_id = io_pp_get_reg_32 (dev, CS8900_PP_PROD_ID); 280 281 if ((prod_id >> 16) != CS8900_ESIA_ID) 282 { 283 printf ("CS9800: Invalid EISA ID, read product code 0x%08lx\n", prod_id); 284 return; 285 } 286 287 if ((prod_id & 0x000000ff) != 0) 288 { 289 printf ("CS9800: Unsupported product id, read product code 0x%08lx\n", 290 prod_id); 291 return; 292 } 293 294 printf ("CS8900 Rev %ld, %s, %s.\n", 295 (prod_id >> 8) & 0x1f, 296 status & CS8900_SELF_STATUS_3_3_V ? "3.3V" : "5.0V", 297 status & CS8900_SELF_STATUS_EEPROM_PRESENT ? 298 "EEPROM present" : "no EEPROM"); 299 300 /* 301 * Switch to memory base accesses as they are faster. No indirect access. 302 */ 303 304 io_pp_set_reg_16 (dev, CS8900_PP_MEM_BASE, CS8900_MEMORY_BASE); 305 io_pp_set_reg_16 (dev, CS8900_PP_MEM_BASE + 2, (CS8900_MEMORY_BASE >> 16) & 0xf); 306 307 io_pp_set_reg_16 (dev, 308 CS8900_PP_BusCTL, 309 CS8900_BUS_CTRL_RESET_RX_DMA | 310 CS8900_BUS_CTRL_USE_SA | 311 CS8900_BUS_CTRL_MEMORY_ENABLE); 312 io_pp_set_reg_16 (dev, 313 CS8900_PP_BusCTL, 314 CS8900_BUS_CTRL_USE_SA | 315 CS8900_BUS_CTRL_MEMORY_ENABLE); 316 317 /* 318 * We are now in memory mapped mode. 319 */ 320 321 /* 322 * Program the Line Control register with the mode we want. 323 * 324 * No auto detect support at the moment. Only 10BaseT. 325 */ 326 327 mem_pp_set_reg (dev, CS8900_PP_LineCFG, CS8900_LINE_CTRL_10BASET); 328 329 /* 330 * Ask the user for the MAC address, the program into the device. 331 */ 332 333 #define MACO(o) cs->arpcom.ac_enaddr[o] 334 335 mem_pp_set_reg (dev, CS8900_PP_IA, 336 (((unsigned int) MACO (1)) << 8) | 337 ((unsigned int) MACO (0))); 338 mem_pp_set_reg (dev, CS8900_PP_IA + 2, 339 (((unsigned int) MACO (3)) << 8) | 340 ((unsigned int) MACO (2))); 341 mem_pp_set_reg (dev, CS8900_PP_IA + 4, 342 (((unsigned int) MACO (5)) << 8) | 343 ((unsigned int) MACO (4))); 344 345 /* 346 * Set the Buffer configuration. 347 */ 348 349 mem_pp_set_reg (dev, CS8900_PP_BufCFG, 350 CS8900_BUFFER_CONFIG_RDY_FOR_TX | 351 CS8900_BUFFER_CONFIG_TX_UNDERRUN | 352 CS8900_BUFFER_CONFIG_TX_COL_OVF | 353 CS8900_BUFFER_CONFIG_RX_MISSED_OVF); 354 355 /* 356 * Set the Receiver configuration. 357 */ 358 359 mem_pp_set_reg (dev, CS8900_PP_RxCFG, 360 CS8900_RX_CONFIG_RX_OK | 361 CS8900_RX_CONFIG_CRC_ERROR | 362 CS8900_RX_CONFIG_RUNT| 363 CS8900_RX_CONFIG_EXTRA_DATA); 364 365 /* 366 * Set the Receiver control. 367 */ 368 369 mem_pp_set_reg (dev, CS8900_PP_RxCTL, 370 CS8900_RX_CTRL_RX_OK | 371 CS8900_RX_CTRL_MULTICAST | 372 CS8900_RX_CTRL_INDIVIDUAL | 373 CS8900_RX_CTRL_BROADCAST); 374 375 /* 376 * Set the Transmitter configuration. 377 */ 378 379 mem_pp_set_reg (dev, CS8900_PP_TxCFG, 380 CS8900_TX_CONFIG_TX_OK | 381 CS8900_TX_CONFIG_OUT_OF_WINDOW | 382 CS8900_TX_CONFIG_JABBER | 383 CS8900_TX_CONFIG_16_COLLISION); 384 385 /* 386 * Attach the interrupt handler. 387 */ 388 389 cs8900_attach_interrupt (dev, cs); 390 391 /* 392 * Program the interrupt level we require then enable interrupts. 393 */ 394 395 mem_pp_set_reg (dev, CS8900_PP_INT, 0); 396 397 mem_pp_bit_set_reg (dev, CS8900_PP_BusCTL, 398 CS8900_BUS_CTRL_ENABLE_INT); 399 } 400 401 rtems_isr 402 cs8900_interrupt (rtems_vector_number v, void *csp) 403 { 404 cs8900_device *cs = csp; 405 int dev = cs->dev; 406 unsigned short isq = 0; 407 struct mbuf *m; 408 unsigned char *p; 409 410 ++cs->eth_stats.interrupts; 411 412 while (1) 413 { 414 isq = mem_pp_get_reg (dev, CS8900_PP_ISQ); 415 416 cs8900_trace (cs, CS8900_T_INT, isq); 417 418 WATCHDOG_TOGGLE (); 419 420 /* 421 * No more interrupts to service. 422 */ 423 424 if (isq == 0) 425 return; 426 427 switch (isq & 0x1f) 428 { 429 case 0x04: 430 431 /* 432 * RxEvent. 433 */ 434 435 ++cs->eth_stats.rx_interrupts; 436 437 if (isq & CS8900_RX_EVENT_RX_OK) 438 { 439 m = cs->rx_ready_head; 440 if (m) 441 { 442 cs->rx_ready_head = m->m_nextpkt; 443 if (cs->rx_ready_head == 0) 444 cs->rx_ready_tail = 0; 445 m->m_nextpkt = 0; 446 cs->rx_ready_len--; 447 448 p = mtod (m, unsigned char *); 449 450 m->m_pkthdr.len = cs8900_get_data_block (dev, p); 451 452 if (cs->rx_loaded_tail == 0) 453 cs->rx_loaded_head = m; 454 else 455 cs->rx_loaded_tail->m_nextpkt = m; 456 cs->rx_loaded_tail = m; 457 cs->rx_loaded_len++; 458 459 if (cs->rx_loaded_len == 1) 460 { 461 cs8900_trace (cs, CS8900_T_RX_OK, cs->rx_loaded_len); 462 rtems_event_send (cs->rx_task, CS8900_RX_OK_EVENT); 463 } 464 } 465 else 466 { 467 ++cs->eth_stats.rx_dropped; 468 469 cs8900_trace (cs, CS8900_T_RX_DROPPED, cs->rx_loaded_len); 470 471 if (cs->rx_loaded_len == 0) 472 rtems_event_send (cs->rx_task, CS8900_RX_OK_EVENT); 473 } 474 } 475 else 476 { 477 if (isq & CS8900_RX_EVENT_CRC_ERROR) 478 ++cs->eth_stats.rx_crc_errors; 479 480 if (isq & CS8900_RX_EVENT_RUNT) 481 ++cs->eth_stats.rx_runt_errors; 482 483 if (isq & CS8900_RX_EVENT_EXTRA_DATA) 484 ++cs->eth_stats.rx_oversize_errors; 485 } 486 break; 487 488 case 0x08: 489 490 /* 491 * TxEvent. 492 */ 493 494 ++cs->eth_stats.tx_interrupts; 495 496 if (cs->tx_active) 497 { 498 if (isq & CS8900_TX_EVENT_TX_OK) 499 ++cs->eth_stats.tx_ok; 500 501 cs->tx_active = 0; 502 503 rtems_event_send (cs->tx_task, CS8900_TX_OK_EVENT); 504 } 505 break; 506 507 case 0x0c: 508 509 /* 510 * BufEvent. 511 */ 512 513 if (isq & CS8900_BUFFER_EVENT_RDY_FOR_TX) 514 { 515 if (cs->tx_active) 516 { 517 ++cs->eth_stats.tx_rdy4tx; 518 rtems_event_send (cs->tx_task, CS8900_TX_WAIT_EVENT); 519 } 520 } 521 else if (isq & CS8900_BUFFER_EVENT_TX_UNDERRUN) 522 { 523 ++cs->eth_stats.tx_underrun_errors; 524 if (cs->tx_active) 525 rtems_event_send (cs->tx_task, CS8900_TX_OK_EVENT); 526 } 527 else if (isq & CS8900_BUFFER_EVENT_SW_INT) 528 { 529 ++cs->eth_stats.int_swint_res; 530 } 531 break; 532 533 case 0x10: 534 535 /* 536 * RxMiss. 537 */ 538 539 cs->eth_stats.rx_missed_errors += 540 mem_pp_get_reg (dev, CS8900_PP_RxMISS) >> 6; 541 break; 542 543 case 0x12: 544 545 /* 546 * TxCol. 547 */ 548 549 cs->eth_stats.tx_collisions += 550 mem_pp_get_reg (dev, CS8900_PP_TxCol) >> 6; 551 break; 552 553 default: 554 break; 555 } 556 } 557 558 } 559 560 int 561 cs8900_link_active (int dev) 562 { 563 return ((mem_pp_get_reg (dev, CS8900_PP_LineST) & CS8900_LINE_STATUS_LINK_OK) ? 564 1 : 0); 565 } 566 567 static inline void 568 cs8900_rx_refill_queue (cs8900_device *cs) 569 { 570 struct ifnet *ifp = &cs->arpcom.ac_if; 571 struct mbuf *m; 572 rtems_interrupt_level level; 573 574 /* 575 * Hold a single queue of mbuf's at the interface. This 576 * will lower the latency of the driver. 577 */ 578 579 while (cs->rx_ready_len < CS8900_RX_QUEUE_SIZE) 580 { 581 MGETHDR (m, M_DONTWAIT, MT_DATA); 582 583 if (!m) 584 { 585 ++cs->eth_stats.rx_no_mbufs; 586 cs8900_trace (cs, CS8900_T_NO_MBUF, cs->eth_stats.rx_no_mbufs); 587 return; 588 } 589 590 MCLGET (m, M_DONTWAIT); 591 592 if (!m->m_ext.ext_buf) 593 { 594 ++cs->eth_stats.rx_no_clusters; 595 cs8900_trace (cs, CS8900_T_NO_CLUSTERS, cs->eth_stats.rx_no_clusters); 596 m_free (m); 597 return; 598 } 599 m->m_pkthdr.rcvif = ifp; 600 m->m_nextpkt = 0; 601 602 rtems_interrupt_disable (level); 603 604 if (cs->rx_ready_tail == 0) 605 cs->rx_ready_head = m; 606 else 607 cs->rx_ready_tail->m_nextpkt = m; 608 cs->rx_ready_tail = m; 609 cs->rx_ready_len++; 610 611 rtems_interrupt_enable (level); 612 } 613 } 614 615 static void 616 cs8900_rx_task (void *arg) 617 { 618 cs8900_device *cs = arg; 619 int dev = cs->dev; 620 struct ifnet *ifp = &cs->arpcom.ac_if; 621 rtems_event_set events; 622 struct mbuf *m; 623 struct ether_header *eh; 624 rtems_status_code sc; 625 rtems_interrupt_level level; 626 627 /* 628 * Turn the receiver and transmitter on. 629 */ 630 631 mem_pp_bit_set_reg (dev, CS8900_PP_LineCFG, 632 CS8900_LINE_CTRL_RX_ON | 633 CS8900_LINE_CTRL_TX_ON); 634 635 /* 636 * Start the software interrupt watchdog. 637 */ 638 639 rtems_interrupt_disable (level); 640 mem_pp_bit_set_reg (dev, CS8900_PP_BufCFG, 641 CS8900_BUFFER_CONFIG_SW_INT); 642 ++cs->eth_stats.int_swint_req; 643 rtems_interrupt_enable (level); 644 645 /* 646 * Loop reading packets. 647 */ 648 649 while (1) 650 { 651 cs8900_rx_refill_queue (cs); 652 653 sc = rtems_bsdnet_event_receive (CS8900_RX_OK_EVENT, 654 RTEMS_WAIT | RTEMS_EVENT_ANY, 655 TOD_MILLISECONDS_TO_TICKS (250), 656 &events); 657 658 cs8900_rx_refill_queue (cs); 659 660 if (sc == RTEMS_TIMEOUT) 661 { 662 /* 663 * We need to check the interrupt hardware in the cs8900a 664 * has not locked up. It seems this occurs if the ISQ 665 * queue fills up. 666 * To test we generate a software interrupt and watch 667 * a counter go up. If the counter does not go for 2 668 * software interrupts requests we flush the ISQ queue. 669 */ 670 671 if ((cs->eth_stats.int_swint_req - cs->eth_stats.int_swint_res) > 1) 672 { 673 printf ("cs8900: int lockup, isq flush\n"); 674 675 mem_pp_bit_clear_reg (dev, CS8900_PP_BusCTL, 676 CS8900_BUS_CTRL_ENABLE_INT); 677 678 while (mem_pp_get_reg (dev, CS8900_PP_ISQ) != 0); 679 680 cs->eth_stats.int_swint_req = cs->eth_stats.int_swint_res = 0; 681 ++cs->eth_stats.int_lockup; 682 683 mem_pp_bit_set_reg (dev, CS8900_PP_BusCTL, 684 CS8900_BUS_CTRL_ENABLE_INT); 685 } 686 687 rtems_interrupt_disable (level); 688 mem_pp_bit_set_reg (dev, CS8900_PP_BufCFG, 689 CS8900_BUFFER_CONFIG_SW_INT); 690 ++cs->eth_stats.int_swint_req; 691 rtems_interrupt_enable (level); 692 } 693 694 cs8900_trace (cs, CS8900_T_RX_BEGIN, cs->rx_loaded_len); 695 696 while (cs->rx_loaded_len) 697 { 698 rtems_interrupt_disable (level); 699 700 m = cs->rx_loaded_head; 701 if (m) 702 { 703 cs->rx_loaded_head = m->m_nextpkt; 704 if (cs->rx_loaded_head == 0) 705 cs->rx_loaded_tail = 0; 706 m->m_nextpkt = 0; 707 cs->rx_loaded_len--; 708 709 rtems_interrupt_enable (level); 710 711 m->m_pkthdr.rcvif = ifp; 712 713 cs->eth_stats.rx_bytes += m->m_pkthdr.len; 714 715 m->m_len = m->m_pkthdr.len = m->m_pkthdr.len - sizeof (struct ether_header); 716 717 eh = mtod (m, struct ether_header *); 718 m->m_data += sizeof (struct ether_header); 719 720 ++cs->eth_stats.rx_packets; 721 722 ether_input (ifp, eh, m); 723 } 724 else 725 { 726 rtems_interrupt_enable (level); 727 } 728 } 729 cs8900_trace (cs, CS8900_T_RX_END, cs->rx_loaded_len); 730 } 731 } 732 733 static void 734 cs8900_tx_task (void *arg) 735 { 736 cs8900_device *cs = arg; 737 int dev = cs->dev; 738 struct ifnet *ifp = &cs->arpcom.ac_if; 739 rtems_event_set events; 740 struct mbuf *m; 741 rtems_status_code sc; 742 743 /* 744 * Wait for the link to come up. 745 */ 746 747 rtems_task_wake_after (TOD_MILLISECONDS_TO_TICKS (750)); 748 749 /* 750 * Loop processing the tx queue. 751 */ 752 753 while (1) 754 { 755 /* 756 * Fetch the mbuf list from the interface's queue. 757 */ 758 759 IF_DEQUEUE (&ifp->if_snd, m); 760 761 /* 762 * If something actually is present send it. 763 */ 764 765 if (!m) 766 { 767 ifp->if_flags &= ~IFF_OACTIVE; 768 769 rtems_bsdnet_event_receive (CS8900_TX_START_EVENT, 770 RTEMS_WAIT | RTEMS_EVENT_ANY, 771 RTEMS_NO_TIMEOUT, 772 &events); 773 } 774 else 775 { 776 if (cs8900_link_active (dev)) 777 { 778 int resending; 779 780 do 781 { 782 unsigned short buf_status; 783 784 resending = 0; 785 786 cs->tx_active = 1; 787 788 mem_pp_set_reg (dev, CS8900_PP_TxCMD, 789 CS8900_TX_CMD_STATUS_TX_START_ENTIRE | 790 CS8900_TX_CMD_STATUS_FORCE); 791 mem_pp_set_reg (dev, CS8900_PP_TxLength, m->m_pkthdr.len); 792 793 buf_status = mem_pp_get_reg (dev, CS8900_PP_BusST); 794 795 /* 796 * If the bid for memory in the device fails trash the 797 * transmit and try again next time. 798 */ 799 800 if (buf_status & CS8900_BUS_STATUS_TX_BID_ERROR) 801 ++cs->eth_stats.tx_bid_errors; 802 else 803 { 804 /* 805 * If the buffer is not read enable the interrupt and then wait. 806 */ 807 808 if ((buf_status & CS8900_BUS_STATUS_RDY_FOR_TX_NOW) == 0) 809 { 810 cs->eth_stats.tx_wait_for_rdy4tx++; 811 sc = rtems_bsdnet_event_receive (CS8900_TX_WAIT_EVENT, 812 RTEMS_WAIT | RTEMS_EVENT_ANY, 813 TOD_MILLISECONDS_TO_TICKS (750), 814 &events); 815 if (sc == RTEMS_TIMEOUT) 816 { 817 /* 818 * For some reason the wait request has been dropped, 819 * so lets resend from the start. 820 */ 821 822 printf ("tx resend\n"); 823 ++cs->eth_stats.tx_resends; 824 resending = 1; 825 } 826 } 827 828 if (!resending) 829 { 830 cs8900_tx_load (dev, m); 831 cs->eth_stats.tx_packets++; 832 cs->eth_stats.tx_bytes += m->m_pkthdr.len; 833 } 834 } 835 } 836 while (resending); 837 838 m_freem (m); 839 840 do 841 { 842 rtems_bsdnet_event_receive (CS8900_TX_OK_EVENT, 843 RTEMS_WAIT | RTEMS_EVENT_ANY, 844 RTEMS_NO_TIMEOUT, 845 &events); 846 } 847 while (cs->tx_active); 848 } 849 else 850 { 851 ++cs->eth_stats.tx_dropped; 852 m_freem (m); 853 } 854 } 855 } 856 } 857 858 static void 859 cs8900_start (struct ifnet *ifp) 860 { 861 cs8900_device *cs = ifp->if_softc; 862 863 /* 864 * Tell the transmit daemon to wake up and send a packet. 865 */ 866 867 ifp->if_flags |= IFF_OACTIVE; 868 869 rtems_event_send (cs->tx_task, CS8900_TX_START_EVENT); 870 } 871 872 static void 873 cs8900_stop (cs8900_device *cs) 874 { 875 int dev = cs->dev; 876 877 mem_pp_bit_clear_reg (dev, CS8900_PP_LineCFG, 878 CS8900_LINE_CTRL_RX_ON | 879 CS8900_LINE_CTRL_TX_ON); 880 881 mem_pp_bit_clear_reg (dev, CS8900_PP_BusCTL, 882 CS8900_BUS_CTRL_ENABLE_INT); 883 } 884 885 static const char *eth_statistics_labels[] = 886 { 887 "rx packets", 888 "tx packets", 889 "rx bytes", 890 "tx bytes", 891 "rx interrupts", 892 "tx interrupts", 893 "rx dropped", 894 "rx no mbuf", 895 "rx no custers", 896 "rx oversize errors", 897 "rx crc errors", 898 "rx runt errors", 899 "rx missed errors", 900 "tx ok", 901 "tx collisions", 902 "tx bid errors", 903 "tx wait for rdy4tx", 904 "tx rdy4tx", 905 "tx underrun errors", 906 "tx dropped", 907 "tx resends", 908 "int swint req", 909 "int swint res", 910 "int lockup", 911 "interrupts" 47 912 }; 48 913 49 static const unsigned long ethernet_mem_base[CS8900_DEVICES] = 50 { 51 ETHERNET_BASE + CS8900_MEMORY_BASE 52 }; 53 54 static const unsigned int ethernet_irq_level[CS8900_DEVICES] = 55 { 56 ETHERNET_IRQ_LEVEL 57 }; 58 59 static const unsigned int ethernet_irq_priority[CS8900_DEVICES] = 60 { 61 ETHERNET_IRQ_PRIORITY 62 }; 63 64 static const unsigned int ethernet_irq_vector[CS8900_DEVICES] = 65 { 66 ETHERNET_IRQ_VECTOR, 67 }; 68 69 void cs8900_io_set_reg (int dev, unsigned short reg, unsigned short data) 70 { 71 #ifdef CS8900_DATA_BUS_SWAPPED 72 data = (data >> 8) | (data << 8); 914 static void 915 cs8900_stats (cs8900_device *cs) 916 { 917 int dev = cs->dev; 918 int i; 919 int max_label = 0; 920 int len; 921 unsigned long *value = (unsigned long*) &cs->eth_stats.rx_packets; 922 923 cs->eth_stats.rx_missed_errors += 924 mem_pp_get_reg (dev, CS8900_PP_RxMISS) >> 6; 925 926 cs->eth_stats.tx_collisions += 927 mem_pp_get_reg (dev, CS8900_PP_TxCol) >> 6; 928 929 printf ("Network Driver Stats for CS8900 :\n"); 930 931 for (i = 0; i < (sizeof (eth_statistics_labels) / sizeof (const char *)); i++) 932 { 933 len = strlen (eth_statistics_labels[i]); 934 if (len > max_label) 935 max_label = len; 936 } 937 938 max_label += 2; 939 940 printf ("%*s - %10u %*s - %10u\n", 941 max_label, "rx ready len", cs->rx_ready_len, 942 max_label, "rx loaded len", cs->rx_loaded_len); 943 944 for (i = 0; 945 i < (sizeof (eth_statistics_labels) / sizeof (const char *)); 946 i++) 947 { 948 printf ("%*s - %10lu", 949 max_label, eth_statistics_labels[i], value[i]); 950 951 i++; 952 953 if (i < (sizeof (eth_statistics_labels) / sizeof (const char *))) 954 printf (" %*s - %10lu", 955 max_label, eth_statistics_labels[i], value[i]); 956 printf ("\n"); 957 } 958 959 #if CS8900_TRACE 960 961 for (i = 0; i < cs->trace_in; i++) 962 { 963 printf ("%8ld.%03ld ", cs->trace_time[i] / 1000, cs->trace_time[i] % 1000); 964 965 if (cs->trace_key[i] < sizeof (cs8900_trace_labels) / sizeof (char*)) 966 printf ("%s : ", cs8900_trace_labels[cs->trace_key[i]]); 967 else 968 printf ("unknown trace key, %d : ", cs->trace_key[i]); 969 970 if (cs->trace_key[i] == CS8900_T_INT) 971 { 972 printf ("0x%04lx ", cs->trace_var[i]); 973 if (cs->trace_var[i] == 0) 974 printf ("end"); 975 else 976 { 977 switch (cs->trace_var[i] & 0x1f) 978 { 979 case 0x04: 980 printf ("rx event"); 981 break; 982 983 case 0x08: 984 printf ("tx event"); 985 break; 986 987 case 0x0c: 988 printf ("buffer event"); 989 break; 990 991 case 0x10: 992 printf ("rx missed"); 993 break; 994 995 case 0x12: 996 printf ("tx collisions"); 997 break; 998 999 case 0x1f: 1000 printf ("tx request"); 1001 break; 1002 1003 case 0x1e: 1004 printf ("tx wait 4 tx"); 1005 break; 1006 1007 case 0x1d: 1008 printf ("tx already active"); 1009 break; 1010 1011 default: 1012 printf ("unknown event"); 1013 break; 1014 } 1015 } 1016 } 1017 else 1018 printf ("0x%08lx", cs->trace_var[i]); 1019 1020 printf ("\n"); 1021 } 1022 1023 cs->trace_in = 0; 1024 73 1025 #endif 74 75 #ifdef CS8900_VERBOSE 76 if (cs8900_io_verbose) 77 printf ("CS8900: io set reg=0x%04x, data=0x%04x\n", reg, data); 1026 } 1027 1028 static void 1029 cs8900_init (void *arg) 1030 { 1031 cs8900_device *cs = arg; 1032 int dev = cs->dev; 1033 struct ifnet *ifp = &cs->arpcom.ac_if; 1034 1035 if (cs->rx_task == 0) 1036 { 1037 1038 /* 1039 * Set up the hardware. 1040 */ 1041 1042 cs8900_hardware_init (cs); 1043 1044 /* 1045 * Start driver task. We have only one task. 1046 */ 1047 1048 cs->rx_task = rtems_bsdnet_newproc ("CSr0", 4096, cs8900_rx_task, cs); 1049 cs->tx_task = rtems_bsdnet_newproc ("CSt0", 4096, cs8900_tx_task, cs); 1050 } 1051 1052 #ifdef todo 1053 /* 1054 * Set flags appropriately 1055 */ 1056 if (ifp->if_flags & IFF_PROMISC) 1057 else 78 1058 #endif 79 80 WRITE_REGISTER_16 (ethernet_io_base[dev] + reg, data); 81 } 82 83 unsigned short cs8900_io_get_reg (int dev, unsigned short reg) 84 { 85 unsigned long data; 86 87 READ_REGISTER_16 (ethernet_io_base[dev] + reg, data); 88 89 #ifdef CS8900_DATA_BUS_SWAPPED 90 data = (data >> 8) | (data << 8); 91 #endif 92 93 #ifdef CS8900_VERBOSE 94 if (cs8900_io_verbose) 95 printk ("CS8900: io get reg=0x%04x, data=0x%04x\n", reg, data); 96 #endif 97 98 return data; 99 } 100 101 void cs8900_mem_set_reg (int dev, unsigned long reg, unsigned short data) 102 { 103 #ifdef CS8900_DATA_BUS_SWAPPED 104 data = (data >> 8) | (data << 8); 105 #endif 106 107 #ifdef CS8900_VERBOSE 108 if (cs8900_io_verbose) 109 printk ("CS8900: mem set reg=0x%04x, data=0x%04x\n", reg, data); 110 #endif 111 112 WRITE_REGISTER_16 (ethernet_io_base[dev] + reg, data); 113 } 114 115 unsigned short cs8900_mem_get_reg (int dev, unsigned long reg) 116 { 117 unsigned short data; 118 READ_REGISTER_16 (ethernet_io_base[dev] + reg, data); 119 120 #ifdef CS8900_DATA_BUS_SWAPPED 121 data = (data >> 8) | (data << 8); 122 #endif 123 124 #ifdef CS8900_VERBOSE 125 if (cs8900_io_verbose) 126 printk ("CS8900: mem get reg=0x%04x, data=0x%04x\n", reg, data); 127 #endif 128 129 return data; 130 } 131 132 void cs8900_put_data_block (int dev, int len, unsigned char *data) 133 { 134 #ifndef CS8900_DATA_BUS_SWAPPED 135 unsigned short swap_word; 136 #endif 137 unsigned short *src = (unsigned short *) ((unsigned long) data); 138 unsigned short *dst = (unsigned short *) (ethernet_mem_base[dev] + CS8900_PP_TxFrameLoc); 139 140 while (len > 1) 141 { 142 #ifndef CS8900_DATA_BUS_SWAPPED 143 swap_word = *src++; 144 *dst++ = (swap_word >> 8) | (swap_word << 8); 145 #else 146 *dst++ = *src++; 147 #endif 148 len -= 2; 149 } 150 151 if (len) 152 { 153 #ifndef CS8900_DATA_BUS_SWAPPED 154 swap_word = *src++; 155 *dst++ = (swap_word >> 8) | (swap_word << 8); 156 #else 157 *dst++ = *src++; 158 #endif 159 } 160 } 161 162 unsigned short cs8900_get_data_block (int dev, unsigned char *data) 163 { 164 unsigned short swap_word; 165 volatile unsigned short *src = (unsigned short *) (ethernet_mem_base[dev] + CS8900_PP_RxLength); 166 unsigned short *dst; 167 unsigned short len; 168 unsigned short rx_len; 169 unsigned short len_odd; 170 171 #ifdef CS8900_DATA_BUS_SWAPPED 172 swap_word = *src++; 173 len = (swap_word >> 8) | (swap_word << 8); 174 #else 175 len = *src++; 176 #endif 177 178 dst = (unsigned short *) ((unsigned long) data); 179 180 len_odd = len & 1; 181 rx_len = len & ~1; 182 183 for (; rx_len; rx_len -= 2) 184 { 185 #ifndef CS8900_DATA_BUS_SWAPPED 186 swap_word = *src++; 187 *dst++ = (swap_word >> 8) | (swap_word << 8); 188 #else 189 *dst++ = *src++; 190 #endif 191 } 192 193 if (len_odd) 194 { 195 #ifndef CS8900_DATA_BUS_SWAPPED 196 swap_word = *src++; 197 *dst++ = (swap_word >> 8) | (swap_word << 8); 198 #else 199 *dst++ = *src++; 200 #endif 201 } 202 203 return len; 204 } 205 206 void 207 cs8900_tx_load (int dev, struct mbuf *m) 208 { 209 volatile unsigned short *dst = (unsigned short *) (ethernet_mem_base[dev] + CS8900_PP_TxFrameLoc); 210 unsigned int len; 211 unsigned char *src; 212 int remainder = 0; 213 unsigned char remainder_data = '\0'; 214 215 while (m) 216 { 1059 1060 /* 1061 * Tell the world that we're running. 1062 */ 1063 1064 ifp->if_flags |= IFF_RUNNING; 1065 1066 /* 1067 * Set the Line Control to bring the receive and transmitter online. 1068 */ 1069 1070 mem_pp_bit_set_reg (dev, CS8900_PP_LineCFG, 1071 CS8900_LINE_CTRL_RX_ON | 1072 CS8900_LINE_CTRL_TX_ON); 1073 1074 mem_pp_bit_set_reg (dev, CS8900_PP_BusCTL, 1075 CS8900_BUS_CTRL_ENABLE_INT); 1076 } 1077 1078 static int 1079 cs8900_ioctl (struct ifnet *ifp, int cmd, caddr_t data) 1080 { 1081 cs8900_device *cs = ifp->if_softc; 1082 int error = 0; 1083 1084 switch (cmd) 1085 { 1086 case SIOCGIFADDR: 1087 case SIOCSIFADDR: 1088 1089 error = ether_ioctl (ifp, cmd, data); 1090 break; 1091 1092 case SIOCSIFFLAGS: 1093 1094 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) 1095 { 1096 case IFF_RUNNING: 1097 1098 cs8900_stop (cs); 1099 break; 1100 1101 case IFF_UP: 1102 1103 cs8900_init (cs); 1104 break; 1105 1106 case IFF_UP | IFF_RUNNING: 1107 1108 cs8900_stop (cs); 1109 cs8900_init (cs); 1110 break; 1111 1112 default: 1113 break; 1114 } 1115 break; 1116 1117 case SIO_RTEMS_SHOW_STATS: 1118 1119 cs8900_stats (cs); 1120 break; 1121 1122 /* FIXME: Multicast commands must be added here. */ 1123 1124 default: 1125 error = EINVAL; 1126 break; 1127 } 1128 1129 return error; 1130 } 1131 1132 int 1133 cs8900_driver_attach (struct rtems_bsdnet_ifconfig *config, int attaching) 1134 { 1135 cs8900_device *cs; 1136 struct ifnet *ifp; 1137 int mtu; 1138 int unit; 1139 char *name; 1140 1141 /* 1142 * Parse driver name 1143 */ 1144 1145 if ((unit = rtems_bsdnet_parse_driver_name (config, &name)) < 0) 1146 return 0; 1147 1148 /* 1149 * Is driver free? 1150 */ 1151 1152 if (unit >= CS8900_DEVICES) 1153 { 1154 printf ("Bad CS8900 unit number for device `%s'.\n", config->name); 1155 return 0; 1156 } 1157 1158 cs = &cs8900[unit]; 1159 cs->dev = unit; 1160 ifp = &cs->arpcom.ac_if; 1161 1162 if (attaching) 1163 { 1164 if (ifp->if_softc) 1165 { 1166 printf ("Driver `%s' already in use.\n", config->name); 1167 return 0; 1168 } 1169 217 1170 /* 218 * We can get empty mbufs from the stack.1171 * Process options 219 1172 */ 220 221 len = m->m_len; 222 src = mtod (m, unsigned char*); 223 224 if (len) 1173 1174 if (config->hardware_address) 1175 memcpy (cs->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); 1176 else 1177 cs8900_get_mac_addr (unit, cs->arpcom.ac_enaddr); 1178 1179 if (config->mtu) 1180 mtu = config->mtu; 1181 else 1182 mtu = ETHERMTU; 1183 1184 cs->accept_bcast = !config->ignore_broadcast; 1185 1186 /* 1187 * Set up network interface values. 1188 */ 1189 1190 ifp->if_softc = cs; 1191 ifp->if_unit = unit; 1192 ifp->if_name = name; 1193 ifp->if_mtu = mtu; 1194 ifp->if_init = cs8900_init; 1195 ifp->if_ioctl = cs8900_ioctl; 1196 ifp->if_start = cs8900_start; 1197 ifp->if_output = ether_output; 1198 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; 1199 1200 if (ifp->if_snd.ifq_maxlen == 0) 1201 ifp->if_snd.ifq_maxlen = ifqmaxlen; 1202 1203 /* 1204 * Attach the interface to the stack. 1205 */ 1206 1207 if_attach (ifp); 1208 ether_ifattach (ifp); 1209 } 1210 else 1211 { 1212 if (!ifp->if_softc) 225 1213 { 226 if (remainder) 227 { 228 #ifndef CS8900_DATA_BUS_SWAPPED 229 *dst++ = remainder_data | (*src++ << 8); 230 #else 231 *dst++ = *src++ | (remainder_data << 8); 232 #endif 233 len--; 234 remainder = 0; 235 } 236 237 if (len & 1) 238 { 239 remainder = 1; 240 len--; 241 } 242 243 for (; len; len -= 2) 244 #ifndef CS8900_DATA_BUS_SWAPPED 245 *dst++ = (*src++) | (*(++src) << 8); 246 #else 247 *dst++ = (*src++ << 8) | *(++src); 248 #endif 249 250 if (remainder) 251 remainder_data = *src++; 1214 printf ("Driver `%s' not found.\n", config->name); 1215 return 0; 252 1216 } 253 254 m = m->m_next; 255 } 256 257 if (remainder) 258 { 259 #ifndef CS8900_DATA_BUS_SWAPPED 260 *dst = (unsigned short) remainder_data; 261 #else 262 *dst = (unsigned short) (remainder_data << 8); 263 #endif 264 } 265 } 266 267 void cs8900_attach_interrupt (int dev, cs8900_device *cs) 268 { 269 rtems_interrupt_catch_with_void (cs8900_interrupt, 270 ethernet_irq_vector[dev], 271 &old_handler[dev], 272 cs, 273 &old_parameter[dev]); 274 275 CF_SIM_WRITE_ICR (CF_BASE, 276 ethernet_irq_level[dev], 277 CF_SIM_ICR_AVEC_AUTO, 278 ethernet_irq_level[dev], 279 ethernet_irq_priority[dev]); 280 CF_SIM_IMR_ENABLE (CF_BASE, 1 << ethernet_irq_level[dev]); 281 } 282 283 void cs8900_detach_interrupt (int dev) 284 { 285 CF_SIM_IMR_DISABLE (CF_BASE, 1 << ethernet_irq_level[dev]); 286 287 rtems_interrupt_catch_with_void (old_handler, 288 ethernet_irq_vector[dev], 289 NULL, 290 old_parameter[dev], 291 NULL); 292 } 293 294 void cs8900_get_mac_addr (int dev, unsigned char *mac_address) 295 { 296 memcpy (mac_address, rct_get_mac_address (dev), 6); 297 } 1217 1218 cs8900_stop (cs); 1219 cs8900_detach_interrupt (unit); 1220 } 1221 1222 return 1; 1223 1224 } -
c/src/libchip/network/cs8900.h
r19ed3cf ra2117cd6 3 3 $Id$ 4 4 ------------------------------------------------------------------------ 5 5 6 6 My Right Boot, a boot ROM for embedded hardware. 7 7 … … 38 38 #include <netinet/in.h> 39 39 #include <netinet/if_ether.h> 40 41 /* #include <target.h> what does this provide? joel to chris */ 40 42 41 43 #define ET_MINLEN 60 … … 383 385 */ 384 386 385 struct arpcom arpcom;387 struct arpcom arpcom; 386 388 387 389 /* … … 418 420 419 421 eth_statistics eth_stats; 420 422 421 423 } cs8900_device; 422 424
Note: See TracChangeset
for help on using the changeset viewer.