- Timestamp:
- 06/17/11 11:58:41 (13 years ago)
- Branches:
- 4.11, 5, master
- Children:
- 18124551
- Parents:
- 1dd95cc
- Location:
- c/src/lib/libbsp/powerpc/gen5200
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/lib/libbsp/powerpc/gen5200/ChangeLog
r1dd95cc r25ed11d0 1 2011-06-17 Sebastian Huber <sebastian.huber@embedded-brains.de> 2 3 * Makefile.am: Added custom memcpy(). Update for network sources. 4 * configure.ac: Enable interrupt driven Termios for all BSPs. 5 * ide/pcmcia_ide.c: Disable broken DMA support. 6 * include/bsp.h: Fixed NEED_LOW_LEVEL_INIT define. Set default 7 console baud to 115200. 8 * include/irq.h, irq/irq.c: Fixed interrupt handling to avoid the 9 following problems: 1. multiple invokation of peripheral interrupt 10 handlers, 2. missing synchronization after mask write and enabling of 11 external exceptions, and 3. logic overhead. 12 * network_5200/network.c: Added MII interface. Fixed controller 13 restart after FIFO errors. Performance improvements. 14 * start/start.S: Fixed ROM startup. Initialize XLB arbiter for all 15 BSPs. 16 * startup/bspstart.c: Special intialization for MPC5200B (B variant). 17 Install standard alignment handler. 18 * startup/cpuinit.c, startup/linkcmds.brs5l, startup/linkcmds.dp2, 19 startup/linkcmds.icecube, startup/linkcmds.pm520_cr825, 20 startup/linkcmds.pm520_ze30: Avoid accesses outside the RAM area. 21 1 22 2011-06-07 Sebastian Huber <sebastian.huber@embedded-brains.de> 2 23 -
c/src/lib/libbsp/powerpc/gen5200/Makefile.am
r1dd95cc r25ed11d0 143 143 ../../shared/bspgetworkarea.c \ 144 144 ../shared/startup/bspidle.c \ 145 ../shared/src/memcpy.c \ 145 146 startup/bspstart.c \ 146 147 startup/cpuinit.c \ … … 148 149 149 150 if HAS_NETWORKING 150 network_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ 151 network_CPPFLAGS += -D__BSD_VISIBLE 152 noinst_PROGRAMS += network.rel 153 network_rel_SOURCES = network_5200/network.c 154 network_rel_CPPFLAGS = $(AM_CPPFLAGS) $(network_CPPFLAGS) 155 network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) 151 libbsp_a_SOURCES += network_5200/network.c 156 152 endif 157 153 … … 164 160 ../../../libcpu/@RTEMS_CPU@/mpc6xx/timer.rel 165 161 166 if HAS_NETWORKING167 libbsp_a_LIBADD += network.rel168 endif169 170 162 include $(srcdir)/preinstall.am 171 163 include $(top_srcdir)/../../../../automake/local.am -
c/src/lib/libbsp/powerpc/gen5200/configure.ac
r1dd95cc r25ed11d0 83 83 RTEMS_BSPOPTS_HELP([MPC5200_PSC_INDEX_FOR_GPS_MODULE],[PSC index for GPS module, if defined results in '/dev/gps']) 84 84 85 RTEMS_BSPOPTS_SET([SINGLE_CHAR_MODE],[dp2],[]) 86 RTEMS_BSPOPTS_SET([SINGLE_CHAR_MODE],[*],[1]) 85 RTEMS_BSPOPTS_SET([SINGLE_CHAR_MODE],[*],[]) 87 86 RTEMS_BSPOPTS_HELP([SINGLE_CHAR_MODE],[enable single character mode for the PSC console driver]) 88 87 89 RTEMS_BSPOPTS_SET([UARTS_USE_TERMIOS_INT],[ dp2],[1])88 RTEMS_BSPOPTS_SET([UARTS_USE_TERMIOS_INT],[*],[1]) 90 89 RTEMS_BSPOPTS_HELP([UARTS_USE_TERMIOS_INT],[enable interrupt support for the PSC console driver]) 91 90 -
c/src/lib/libbsp/powerpc/gen5200/ide/pcmcia_ide.c
r1dd95cc r25ed11d0 93 93 #define IDE_DMA_TEST FALSE 94 94 95 #ifdef BRS5L 96 #define IDE_USE_INT TRUE 97 #define IDE_READ_USE_DMA TRUE 98 #define IDE_USE_READ_PIO_OPT FALSE 99 #define IDE_WRITE_USE_DMA TRUE 100 #define IDE_USE_WRITE_PIO_OPT TRUE 101 /* #define IDE_USE_DMA (IDE_READ_USE_DMA||IDE_WRITE_USE_DMA) */ 102 #define IDE_USE_DMA TRUE 103 #else 95 /* DMA supported PIO mode is broken */ 104 96 #define IDE_USE_INT TRUE 105 97 #define IDE_READ_USE_DMA FALSE … … 107 99 #define IDE_WRITE_USE_DMA FALSE 108 100 #define IDE_USE_WRITE_PIO_OPT FALSE 109 /* #define IDE_USE_DMA (IDE_READ_USE_DMA||IDE_WRITE_USE_DMA) */ 110 #define IDE_USE_DMA FALSE 111 #endif 101 #define IDE_USE_DMA (IDE_READ_USE_DMA || IDE_WRITE_USE_DMA) 112 102 113 103 #define IDE_USE_STATISTICS TRUE … … 465 455 (*pos) += bufs[bufs_from_dma].length; 466 456 bufs_from_dma++; 457 bds_free++; 467 458 } 468 459 } while ((nxt_bd_idx != TASK_ERR_BD_RING_EMPTY) && -
c/src/lib/libbsp/powerpc/gen5200/include/bsp.h
r1dd95cc r25ed11d0 80 80 #endif 81 81 82 #if !defined(HAS_UBOOT) 83 /* we need the low level initialization in start.S*/ 84 #define NEED_LOW_LEVEL_INIT 85 #endif 86 82 87 #if defined(BRS5L) 83 88 /* … … 118 123 #include <bsp/vectors.h> 119 124 #include <bsp/u-boot.h> 120 121 #if !defined(HAS_UBOOT)122 /* we need the low level initialization in start.S*/123 #define NEED_LOW_LEVEL_INIT124 #endif125 125 126 126 /* … … 180 180 #define GEN5200_CONSOLE_BAUD (bsp_uboot_board_info.bi_baudrate) 181 181 #else 182 #define GEN5200_CONSOLE_BAUD 9600182 #define GEN5200_CONSOLE_BAUD 115200 183 183 #endif 184 184 -
c/src/lib/libbsp/powerpc/gen5200/include/irq.h
r1dd95cc r25ed11d0 88 88 #define LIBBSP_POWERPC_GEN5200_IRQ_H 89 89 90 #define CHK_CE_SHADOW(_pmce) ((_pmce) & 0x00000001) 91 #define CHK_CSE_STICKY(_pmce) (((_pmce) >> 10) & 0x00000001) 92 #define CHK_MSE_STICKY(_pmce) (((_pmce) >> 21) & 0x00000001) 93 #define CHK_PSE_STICKY(_pmce) (((_pmce) >> 29) & 0x00000001) 94 #define CLR_CSE_STICKY(_pmce) ((_pmce) |= (1 << 29 )) 95 #define CLR_MSE_STICKY(_pmce) ((_pmce) |= (1 << 21 )) 96 #define CLR_PSE_STICKY(_pmce) ((_pmce) |= (1 << 10 )) 97 #define CSE_SOURCE(_source) (((_source) >> 8) & 0x00000003) 98 #define MSE_SOURCE(_source) (((_source) >> 16) & 0x0000001F) 99 #define PSE_SOURCE(_source) (((_source) >> 24) & 0x0000001F) 90 #define PMCE_CE_SHADOW (1U << (31 - 31)) 91 #define PMCE_CSE_STICKY (1U << (31 - 21)) 92 #define PMCE_MSE_STICKY (1U << (31 - 10)) 93 #define PMCE_PSE_STICKY (1U << (31 - 2)) 94 #define PMCE_CSE_SOURCE(_pmce) (((_pmce) >> 8) & 0x3U) 95 #define PMCE_MSE_SOURCE(_pmce) (((_pmce) >> 16) & 0x1fU) 96 #define PMCE_PSE_SOURCE(_pmce) (((_pmce) >> 24) & 0x1fU) 100 97 101 98 /* -
c/src/lib/libbsp/powerpc/gen5200/irq/irq.c
r1dd95cc r25ed11d0 172 172 prio_index_offset; 173 173 uint32_t *reg; 174 volatile uint32_t per_pri_1,175 main_pri_1,176 crit_pri_main_mask,177 per_mask;178 174 179 175 /* calculate the index offset of priority value bit field */ … … 224 220 mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]); 225 221 226 main_pri_1 = mpc5200.main_pri_1;227 crit_pri_main_mask = mpc5200.crit_pri_main_mask;228 per_pri_1 = mpc5200.per_pri_1;229 per_mask = mpc5200.per_mask;230 222 /* FIXME: Why? */ 223 mpc5200.main_pri_1; 224 mpc5200.crit_pri_main_mask; 225 mpc5200.per_pri_1; 226 mpc5200.per_mask; 231 227 } 232 228 … … 485 481 #if (ALLOW_IRQ_NESTING == 1) 486 482 uint32_t msr; 483 uint32_t mask = *maskreg; 487 484 #endif 488 485 489 uint32_t mask = *maskreg;490 491 486 irq += offset; 492 487 493 *maskreg = mask | irqMaskTable [irq];494 495 488 #if (ALLOW_IRQ_NESTING == 1) 489 *maskreg = mask | irqMaskTable [irq]; 490 /* Make sure that the write operation completed (cache inhibited area) */ 491 *maskreg; 496 492 msr = ppc_external_exceptions_enable(); 497 493 #endif … … 501 497 #if (ALLOW_IRQ_NESTING == 1) 502 498 ppc_external_exceptions_disable(msr); 499 *maskreg = mask; 503 500 #endif 504 505 *maskreg = mask;506 501 } 507 502 … … 527 522 #endif 528 523 529 switch (excNum) { 530 /* 531 * Handle decrementer interrupt 532 */ 533 case ASM_DEC_VECTOR: 534 535 /* Dispatch interrupt handlers */ 536 bsp_interrupt_handler_dispatch( BSP_DECREMENTER); 537 538 break; 539 540 case ASM_EXT_VECTOR: 541 case ASM_60X_SYSMGMT_VECTOR: 542 /* get the content of main interrupt status register */ 543 pmce = mpc5200.pmce; 544 545 /* critical interrupts may be routed to the core_int 546 * dependent on premature initialization, see bit 31 (CEbsH) 547 */ 548 while ((CHK_CE_SHADOW( pmce) && CHK_CSE_STICKY( pmce)) 549 || CHK_MSE_STICKY( pmce) || CHK_PSE_STICKY( pmce)) { 550 551 /* first: check for critical interrupt sources (hierarchical order) 552 * -> HI_int indicates peripheral sources 553 */ 554 if (CHK_CE_SHADOW( pmce) && CHK_CSE_STICKY( pmce)) { 555 /* get source of critical interrupt */ 556 irq = CSE_SOURCE( pmce); 557 switch (irq) { 558 /* irq0, slice timer 1 or ccs wakeup detected */ 559 case 0: 560 case 1: 561 case 3: 562 563 /* add proper offset for critical interrupts in the siu 564 * handler array */ 565 irq += BSP_CRIT_IRQ_LOWEST_OFFSET; 566 567 /* Dispatch interrupt handlers */ 568 bsp_interrupt_handler_dispatch( irq); 569 570 break; 571 572 /* peripheral HI_int interrupt source detected */ 573 case 2: 574 /* check for valid peripheral interrupt source */ 575 if (CHK_PSE_STICKY( pmce)) { 576 /* get source of peripheral interrupt */ 577 irq = PSE_SOURCE( pmce); 578 579 dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); 580 581 /* force re-evaluation of peripheral interrupts */ 582 CLR_PSE_STICKY( mpc5200.pmce); 583 } else { 584 /* this case may not occur: no valid peripheral 585 * interrupt source */ 586 printk( "No valid peripheral HI_int interrupt source\n"); 587 } 588 break; 589 default: 590 /* error: unknown interrupt source */ 591 printk( "Unknown HI_int interrupt source\n"); 592 break; 524 /* get the content of main interrupt status register */ 525 pmce = mpc5200.pmce; 526 527 /* critical interrupts are routed to the core_int, see premature 528 * initialization 529 */ 530 while ((pmce & (PMCE_CSE_STICKY | PMCE_MSE_STICKY)) != 0) { 531 /* first: check for critical interrupt sources (hierarchical order) 532 * -> HI_int indicates peripheral sources 533 */ 534 if ((pmce & PMCE_CSE_STICKY) != 0) { 535 /* get source of critical interrupt */ 536 irq = PMCE_CSE_SOURCE(pmce); 537 538 switch (irq) { 539 /* peripheral HI_int interrupt source detected */ 540 case 2: 541 /* check for valid peripheral interrupt source */ 542 if ((pmce & PMCE_PSE_STICKY) != 0) { 543 /* get source of peripheral interrupt */ 544 irq = PMCE_PSE_SOURCE(pmce); 545 546 dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); 547 } else { 548 /* this case may not occur: no valid peripheral 549 * interrupt source */ 550 printk( "No valid peripheral HI_int interrupt source\n"); 593 551 } 594 /* force re-evaluation of critical interrupts */ 595 CLR_CSE_STICKY( mpc5200.pmce); 596 } 597 598 /* second: check for main interrupt sources (hierarchical order) 599 * -> LO_int indicates peripheral sources */ 600 if (CHK_MSE_STICKY( pmce)) { 601 /* get source of main interrupt */ 602 irq = MSE_SOURCE( pmce); 603 604 switch (irq) { 605 606 /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer 607 * 2 is always routed to SMI) */ 608 case 0: 609 case 1: 610 case 2: 611 case 3: 612 case 5: 613 case 6: 614 case 7: 615 case 8: 616 case 9: 617 case 10: 618 case 11: 619 case 12: 620 case 13: 621 case 14: 622 case 15: 623 case 16: 624 dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask); 625 break; 626 627 /* peripheral LO_int interrupt source detected */ 628 case 4: 629 /* check for valid peripheral interrupt source */ 630 if (CHK_PSE_STICKY( pmce)) { 631 /* get source of peripheral interrupt */ 632 irq = PSE_SOURCE( pmce); 633 634 dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); 635 636 /* force re-evaluation of peripheral interrupts */ 637 CLR_PSE_STICKY( mpc5200.pmce); 638 } else { 639 /* this case may not occur: no valid peripheral 640 * interrupt source */ 641 printk( "No valid peripheral LO_int interrupt source\n"); 642 } 643 break; 644 645 /* error: unknown interrupt source */ 646 default: 647 printk( "Unknown peripheral LO_int interrupt source\n"); 648 break; 552 break; 553 554 /* irq0, slice timer 1 or ccs wakeup detected */ 555 case 0: 556 case 1: 557 case 3: 558 559 /* add proper offset for critical interrupts in the siu 560 * handler array */ 561 irq += BSP_CRIT_IRQ_LOWEST_OFFSET; 562 563 /* Dispatch interrupt handlers */ 564 bsp_interrupt_handler_dispatch( irq); 565 566 break; 567 568 default: 569 /* error: unknown interrupt source */ 570 printk( "Unknown HI_int interrupt source\n"); 571 break; 572 } 573 } 574 575 /* second: check for main interrupt sources (hierarchical order) 576 * -> LO_int indicates peripheral sources */ 577 if ((pmce & PMCE_MSE_STICKY) != 0) { 578 /* get source of main interrupt */ 579 irq = PMCE_MSE_SOURCE(pmce); 580 581 if (irq == 4) { 582 /* peripheral LO_int interrupt source detected */ 583 /* check for valid peripheral interrupt source */ 584 if ((pmce & PMCE_PSE_STICKY) != 0) { 585 /* get source of peripheral interrupt */ 586 irq = PMCE_PSE_SOURCE(pmce); 587 588 dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); 589 } else { 590 /* this case may not occur: no valid peripheral 591 * interrupt source */ 592 printk( "No valid peripheral LO_int interrupt source\n"); 649 593 } 650 /* force re-evaluation of main interrupts */ 651 CLR_MSE_STICKY( mpc5200.pmce); 652 } 653 654 if (CHK_PSE_STICKY( pmce)) { 655 /* get source of peripheral interrupt */ 656 irq = PSE_SOURCE( pmce); 657 658 dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); 659 660 /* force re-evaluation of peripheral interrupts */ 661 CLR_PSE_STICKY( mpc5200.pmce); 662 } 663 664 /* get the content of main interrupt status register */ 665 pmce = mpc5200.pmce; 594 } else if (irq <= 16) { 595 /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer 596 * 2 is always routed to SMI) */ 597 dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask); 598 } else { 599 /* error: unknown interrupt source */ 600 printk( "Unknown peripheral LO_int interrupt source\n"); 666 601 } 667 break; 668 669 default: 670 printk( "Unknown processor exception\n"); 671 break; 672 673 } /* end of switch( excNum) */ 602 } 603 604 /* force re-evaluation of interrupts */ 605 mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY; 606 607 /* get the content of main interrupt status register */ 608 pmce = mpc5200.pmce; 609 } 674 610 675 611 #if (BENCHMARK_IRQ_PROCESSING == 1) … … 772 708 return RTEMS_IO_ERROR; 773 709 } 774 if (ppc_exc_set_handler( ASM_DEC_VECTOR, C_dispatch_irq_handler)) {775 return RTEMS_IO_ERROR;776 }777 710 if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler)) { 778 711 return RTEMS_IO_ERROR; -
c/src/lib/libbsp/powerpc/gen5200/network_5200/network.c
r1dd95cc r25ed11d0 54 54 * 55 55 */ 56 57 #define __INSIDE_RTEMS_BSD_TCPIP_STACK__ 1 58 #define __BSD_VISIBLE 1 59 56 60 #include <rtems.h> 57 61 #include <rtems/error.h> 58 62 #include <rtems/rtems_bsdnet.h> 63 #include <rtems/rtems_mii_ioctl.h> 59 64 #include <stdio.h> 65 #include <inttypes.h> 60 66 #include <sys/param.h> 61 67 #include <sys/mbuf.h> … … 67 73 #include <bsp.h> 68 74 #include <bsp/irq.h> 69 #include "../include/mpc5200.h"75 #include <bsp/mpc5200.h> 70 76 #include <net/if_var.h> 71 77 #include <errno.h> 72 78 73 /* motorola-capi-specifics... */ 74 #include "../bestcomm/include/ppctypes.h" /* uint32, et. al. */ 75 #include "../bestcomm/dma_image.h" 76 #include "../bestcomm/bestcomm_glue.h" 77 78 79 #define SDMA_BD_TFD 0x08000000 /*< Transmit Frame Done */ 80 #define SDMA_BD_INT 0x04000000 /*< Interrupt on frame done */ 81 #define SDMA_BD_RX_NUM 64 /* Number of receive buffer descriptors */ 82 #define SDMA_BD_TX_NUM 64 /* Number of transmit buffer descriptors */ 83 84 #define SET_BD_STATUS(bd, stat) { \ 85 (bd)->Status &= 0x0000ffff; \ 86 (bd)->Status |= 0xffff0000 & stat; \ 87 } 88 #define SET_BD_LENGTH(bd, len) { \ 89 (bd)->Status &= 0xffff0000; \ 90 (bd)->Status |= 0x0000ffff & len; \ 91 } 92 #define GET_BD_STATUS(bd) ((bd)->Status & 0xffff0000) 93 #define GET_BD_LENGTH(bd) ((bd)->Status & 0x0000ffff) 94 #define GET_SDMA_PENDINGBIT(Bit) \ 95 (mpc5200.sdma.IntPend & (uint32)(1<<Bit)) 96 97 #include "../bestcomm/bestcomm_api.h" 98 #include "../bestcomm/task_api/bestcomm_cntrl.h" 99 #include "../bestcomm/task_api/tasksetup_bdtable.h" 100 101 static TaskId rxTaskId; /* SDMA RX task ID */ 102 static TaskId txTaskId; /* SDMA TX task ID */ 79 #include <bsp/bestcomm/include/ppctypes.h> 80 #include <bsp/bestcomm/dma_image.h> 81 #include <bsp/bestcomm/bestcomm_glue.h> 82 #include <bsp/bestcomm/bestcomm_api.h> 83 #include <bsp/bestcomm/task_api/bestcomm_cntrl.h> 84 #include <bsp/bestcomm/task_api/tasksetup_bdtable.h> 103 85 104 86 /* #define ETH_DEBUG */ 87 88 #define FEC_BD_LAST TASK_BD_TFD 89 #define FEC_BD_INT TASK_BD_INT 90 #define FEC_BD_READY SDMA_BD_MASK_READY 105 91 106 92 /* … … 114 100 * since a single frame often uses four or more buffer descriptors. 115 101 */ 116 #define RX_BUF_COUNT SDMA_BD_RX_NUM 117 #define TX_BUF_COUNT SDMA_BD_TX_NUM 118 #define TX_BD_PER_BUF 1 102 #define RX_BUF_COUNT 64 103 #define TX_BUF_COUNT 64 119 104 120 105 #define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") 121 106 122 123 /* 124 * RTEMS event used by interrupt handler to signal daemons. 125 * This must *not* be the same event used by the TCP/IP task synchronization. 126 */ 127 #define INTERRUPT_EVENT RTEMS_EVENT_1 128 #define FATAL_INT_EVENT RTEMS_EVENT_3 129 130 /* 131 * RTEMS event used to start transmit daemon. 132 * This must not be the same as INTERRUPT_EVENT. 133 */ 134 #define START_TRANSMIT_EVENT RTEMS_EVENT_2 107 #define FEC_EVENT RTEMS_EVENT_0 135 108 136 109 /* Task number assignment */ … … 187 160 #define MPC5200_FEC_MII_DATA_PA_SHIFT 0x17 /* MII PHY address bits */ 188 161 189 190 /* Receive & Transmit Buffer Descriptor definitions */191 typedef struct mpc5200_buffer_desc_192 {193 volatile uint16_t status;194 volatile uint16_t length;195 volatile void *buffer;196 } mpc5200_buffer_desc_t;197 198 199 162 #define FEC_INTR_MASK_USED \ 200 163 (FEC_INTR_LCEN |FEC_INTR_CRLEN |\ 201 164 FEC_INTR_XFUNEN|FEC_INTR_XFERREN|FEC_INTR_RFERREN) 202 165 166 typedef enum { 167 FEC_STATE_RESTART_0, 168 FEC_STATE_RESTART_1, 169 FEC_STATE_NORMAL, 170 } mpc5200_fec_state; 171 203 172 /* 204 173 * Device data 205 174 */ 206 struct mpc5200_enet_struct { 207 #if 0 208 struct ifnet ac_if; 209 #else 175 typedef struct { 210 176 struct arpcom arpcom; 211 #endif212 177 struct mbuf **rxMbuf; 213 178 struct mbuf **txMbuf; 179 mpc5200_fec_state state; 214 180 int acceptBroadcast; 215 181 int rxBdCount; … … 227 193 unsigned long rxNonOctet; 228 194 unsigned long rxBadCRC; 229 unsigned long rx Overrun;195 unsigned long rxFIFOError; 230 196 unsigned long rxCollision; 231 197 … … 234 200 unsigned long txLateCollision; 235 201 unsigned long txUnderrun; 202 unsigned long txFIFOError; 236 203 unsigned long txMisaligned; 237 204 unsigned long rxNotFirst; 238 205 unsigned long txRetryLimit; 239 }; 240 241 static struct mpc5200_enet_struct enet_driver[NIFACES]; 242 243 extern int taskTable; 244 static void mpc5200_fec_restart(struct mpc5200_enet_struct *sc); 245 246 247 248 /* 249 * Function: mpc5200_fec_rx_bd_init 250 * 251 * Description: Initialize the receive buffer descriptor ring. 252 * 253 * Returns: void 254 * 255 * Notes: Space for the buffers of rx BDs is allocated by the rx deamon 256 * 257 */ 258 static void mpc5200_fec_rx_bd_init(struct mpc5200_enet_struct *sc) { 259 int rxBdIndex; 260 struct mbuf *m; 261 struct ifnet *ifp = &sc->arpcom.ac_if; 262 BDIdx bdi; 263 264 /* 265 * Fill RX buffer descriptor ring. 266 */ 267 for( rxBdIndex = 0; rxBdIndex < sc->rxBdCount; rxBdIndex++ ) { 268 MGETHDR (m, M_WAIT, MT_DATA); 269 MCLGET (m, M_WAIT); 270 271 m->m_pkthdr.rcvif = ifp; 272 sc->rxMbuf[rxBdIndex] = m; 273 bdi = TaskBDAssign( rxTaskId, 274 mtod(m, void *), 275 NULL, 276 ETHER_MAX_LEN, 277 0 ); 278 if (bdi != rxBdIndex) { 279 rtems_panic("network rx buffer indices out of sync"); 280 } 281 } 282 } 283 284 /* 285 * Function: mpc5200_fec_rx_bd_cleanup 286 * 287 * Description: put all mbufs pending in rx BDs back to buffer pool 288 * 289 * Returns: void 290 * 291 */ 292 static void mpc5200_fec_rx_bd_cleanup(struct mpc5200_enet_struct *sc) { 293 int rxBdIndex; 294 struct mbuf *m,*n; 295 296 /* 297 * Drain RX buffer descriptor ring. 298 */ 299 for( rxBdIndex = 0; rxBdIndex < sc->rxBdCount; rxBdIndex++ ) { 300 n = sc->rxMbuf[rxBdIndex]; 301 while (n != NULL) { 302 m = n; 303 MFREE(m,n); 304 } 305 } 206 207 struct rtems_mdio_info mdio; 208 int phyAddr; 209 bool phyInitialized; 210 } mpc5200_fec_context; 211 212 static mpc5200_fec_context enet_driver[NIFACES]; 213 214 static void mpc5200_fec_send_event(rtems_id task) 215 { 216 rtems_event_send(task, FEC_EVENT); 217 } 218 219 static void mpc5200_fec_wait_for_event(void) 220 { 221 rtems_event_set out; 222 rtems_bsdnet_event_receive( 223 FEC_EVENT, 224 RTEMS_EVENT_ANY | RTEMS_WAIT, 225 RTEMS_NO_TIMEOUT, 226 &out 227 ); 228 } 229 230 static void mpc5200_fec_stop_dma(void) 231 { 232 TaskStop(FEC_RECV_TASK_NO); 233 TaskStop(FEC_XMIT_TASK_NO); 234 } 235 236 static void mpc5200_fec_request_restart(mpc5200_fec_context *self) 237 { 238 self->state = FEC_STATE_RESTART_0; 239 mpc5200_fec_send_event(self->txDaemonTid); 240 mpc5200_fec_send_event(self->rxDaemonTid); 241 } 242 243 static void mpc5200_fec_start_dma_and_controller(void) 244 { 245 TaskStart(FEC_RECV_TASK_NO, 1, FEC_RECV_TASK_NO, 1); 246 TaskStart(FEC_XMIT_TASK_NO, 1, FEC_XMIT_TASK_NO, 1); 247 248 mpc5200.ecntrl |= FEC_ECNTRL_OE | FEC_ECNTRL_EN; 306 249 } 307 250 … … 317 260 * 318 261 */ 319 static void mpc5200_eth_addr_filter_set( struct mpc5200_enet_struct *sc) {262 static void mpc5200_eth_addr_filter_set(mpc5200_fec_context *self) { 320 263 unsigned char *mac; 321 264 unsigned char currByte; /* byte for which to compute the CRC */ … … 327 270 * Get the mac address of ethernet controller 328 271 */ 329 mac = (unsigned char *)(&s c->arpcom.ac_enaddr);272 mac = (unsigned char *)(&self->arpcom.ac_enaddr); 330 273 331 274 /* … … 400 343 } 401 344 345 static int mpc5200_eth_mii_transfer( 346 int phyAddr, 347 unsigned regAddr, 348 uint32_t data 349 ) 350 { 351 int timeout = 0xffff; 352 353 mpc5200.ievent = FEC_INTR_MII; 354 355 mpc5200.mii_data = MPC5200_FEC_MII_DATA_ST 356 | MPC5200_FEC_MII_DATA_TA 357 | (phyAddr << MPC5200_FEC_MII_DATA_PA_SHIFT) 358 | (regAddr << MPC5200_FEC_MII_DATA_RA_SHIFT) 359 | data; 360 361 while (timeout > 0 && (mpc5200.ievent & FEC_INTR_MII) == 0) { 362 --timeout; 363 } 364 365 return timeout > 0 ? 0 : -1; 366 } 367 368 /* FIXME: Make this static, this needs a fix in an application */ 369 int mpc5200_eth_mii_read( 370 int phyAddr, 371 void *arg, 372 unsigned regAddr, 373 uint32_t *retVal 374 ) 375 { 376 int rv = mpc5200_eth_mii_transfer( 377 phyAddr, 378 regAddr, 379 MPC5200_FEC_MII_DATA_OP_RD 380 ); 381 382 *retVal = mpc5200.mii_data & 0xffff; 383 384 return rv; 385 } 386 387 static int mpc5200_eth_mii_write( 388 int phyAddr, 389 void *arg, 390 unsigned regAddr, 391 uint32_t data 392 ) 393 { 394 return mpc5200_eth_mii_transfer( 395 phyAddr, 396 regAddr, 397 MPC5200_FEC_MII_DATA_OP_WR | data 398 ); 399 } 400 402 401 403 402 /* 404 * Function: mpc5200_eth_mii_read 405 * 406 * Description: Read a media independent interface (MII) register on an 407 * 18-wire ethernet tranceiver (PHY). Please see your PHY 408 * documentation for the register map. 409 * 410 * Returns: 32-bit register value 411 * 412 * Notes: 413 * 403 * Reset a running ethernet driver including the hardware FIFOs and the FEC. 414 404 */ 415 int mpc5200_eth_mii_read(struct mpc5200_enet_struct *sc, unsigned char phyAddr, unsigned char regAddr, unsigned short * retVal) 416 { 417 unsigned long reg; /* convenient holder for the PHY register */ 418 unsigned long phy; /* convenient holder for the PHY */ 419 int timeout = 0xffff; 420 421 /* 422 * reading from any PHY's register is done by properly 423 * programming the FEC's MII data register. 424 */ 425 reg = regAddr << MPC5200_FEC_MII_DATA_RA_SHIFT; 426 phy = phyAddr << MPC5200_FEC_MII_DATA_PA_SHIFT; 427 428 mpc5200.mii_data = (MPC5200_FEC_MII_DATA_ST | MPC5200_FEC_MII_DATA_OP_RD | MPC5200_FEC_MII_DATA_TA | phy | reg); 429 430 /* 431 * wait for the related interrupt 432 */ 433 while ((timeout--) && (!(mpc5200.ievent & 0x00800000))); 434 435 if(timeout == 0) 436 { 437 438 #ifdef ETH_DEBUG 439 printf ("Read MDIO failed..." "\r\n"); 440 #endif 441 442 return false; 443 444 } 445 446 /* 447 * clear mii interrupt bit 448 */ 449 mpc5200.ievent = 0x00800000; 450 451 /* 452 * it's now safe to read the PHY's register 453 */ 454 *retVal = (unsigned short)mpc5200.mii_data; 455 456 return true; 457 458 } 459 460 /* 461 * Function: mpc5200_eth_mii_write 462 * 463 * Description: Write a media independent interface (MII) register on an 464 * 18-wire ethernet tranceiver (PHY). Please see your PHY 465 * documentation for the register map. 466 * 467 * Returns: Success (boolean) 468 * 469 * Notes: 470 * 471 */ 472 static int mpc5200_eth_mii_write(struct mpc5200_enet_struct *sc, unsigned char phyAddr, unsigned char regAddr, unsigned short data) 473 { 474 unsigned long reg; /* convenient holder for the PHY register */ 475 unsigned long phy; /* convenient holder for the PHY */ 476 int timeout = 0xffff; 477 478 reg = regAddr << MPC5200_FEC_MII_DATA_RA_SHIFT; 479 phy = phyAddr << MPC5200_FEC_MII_DATA_PA_SHIFT; 480 481 mpc5200.mii_data = (MPC5200_FEC_MII_DATA_ST | MPC5200_FEC_MII_DATA_OP_WR | MPC5200_FEC_MII_DATA_TA | phy | reg | data); 482 483 /* 484 * wait for the MII interrupt 485 */ 486 while ((timeout--) && (!(mpc5200.ievent & 0x00800000))); 487 488 if(timeout == 0) 489 { 490 491 #ifdef ETH_DEBUG 492 printf ("Write MDIO failed..." "\r\n"); 493 #endif 494 495 return false; 496 497 } 498 499 /* 500 * clear MII interrupt bit 501 */ 502 mpc5200.ievent = 0x00800000; 503 504 return true; 505 506 } 507 508 509 /* 510 * Function: mpc5200_fec_reset 511 * 512 * Description: Reset a running ethernet driver including the hardware 513 * FIFOs and the FEC. 514 * 515 * Returns: Success (boolean) 516 * 517 * Notes: 518 * 519 */ 520 static int mpc5200_fec_reset(struct mpc5200_enet_struct *sc) { 405 static void mpc5200_fec_reset(mpc5200_fec_context *self) 406 { 521 407 volatile int delay; 522 408 /* … … 544 430 */ 545 431 for (delay = 0;delay < 16*4;delay++) {}; 546 547 return true;548 432 } 549 433 … … 560 444 * 561 445 */ 562 void mpc5200_fec_off( struct mpc5200_enet_struct *sc)446 void mpc5200_fec_off(mpc5200_fec_context *self) 563 447 { 564 448 int counter = 0xffff; … … 566 450 567 451 #if defined(ETH_DEBUG) 568 u nsigned short phyStatus, i;569 unsigned char phyAddr = 0;452 uint32_t phyStatus; 453 int i; 570 454 571 455 for(i = 0; i < 9; i++) 572 456 { 573 457 574 mpc5200_eth_mii_read(s c, phyAddr, i, &phyStatus);575 printf ("Mii reg %d: 0x%04 x""\r\n", i, phyStatus);458 mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus); 459 printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus); 576 460 577 461 } … … 580 464 { 581 465 582 mpc5200_eth_mii_read(s c, phyAddr, i, &phyStatus);583 printf ("Mii reg %d: 0x%04 x""\r\n", i, phyStatus);466 mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus); 467 printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus); 584 468 585 469 } … … 602 486 while((counter--) && (!(mpc5200.ievent & FEC_INTR_GRA))); 603 487 604 /* 605 * Disable the SmartDMA transmit and receive tasks. 606 */ 607 TaskStop( rxTaskId ); 608 TaskStop( txTaskId ); 488 mpc5200_fec_stop_dma(); 489 609 490 /* 610 491 * Disable transmit / receive interrupts … … 617 498 */ 618 499 mpc5200.ecntrl &= ~(FEC_ECNTRL_OE | FEC_ECNTRL_EN); 619 620 /* 621 * cleanup all buffers 622 */ 623 mpc5200_fec_rx_bd_cleanup(sc); 624 625 } 500 } 626 501 627 502 /* … … 630 505 void mpc5200_fec_irq_handler(rtems_irq_hdl_param handle) 631 506 { 632 struct mpc5200_enet_struct *sc = (struct mpc5200_enet_struct *) handle;507 mpc5200_fec_context *self = (mpc5200_fec_context *) handle; 633 508 volatile uint32_t ievent; 634 509 … … 640 515 */ 641 516 if (ievent & FEC_INTR_LATE_COL) { 642 s c->txLateCollision++;517 self->txLateCollision++; 643 518 } 644 519 if (ievent & FEC_INTR_COL_RETRY) { 645 s c->txRetryLimit++;520 self->txRetryLimit++; 646 521 } 647 522 if (ievent & FEC_INTR_XFIFO_UN) { 648 s c->txUnderrun++;523 self->txUnderrun++; 649 524 } 650 525 if (ievent & FEC_INTR_XFIFO_ERR) { 651 s c->txUnderrun++;526 self->txFIFOError++; 652 527 } 653 528 if (ievent & FEC_INTR_RFIFO_ERR) { 654 s c->rxOverrun++;529 self->rxFIFOError++; 655 530 } 656 531 /* … … 659 534 if (ievent & (FEC_INTR_XFIFO_ERR | FEC_INTR_RFIFO_ERR)) { 660 535 mpc5200.imask &= ~(FEC_INTR_XFERREN | FEC_INTR_RFERREN); 661 rtems_event_send(enet_driver[0].rxDaemonTid, FATAL_INT_EVENT); 662 } 663 } 664 665 /* 666 * MPC5200 SmartComm ethernet interrupt handler 667 */ 668 void mpc5200_smartcomm_rx_irq_handler(rtems_irq_hdl_param unused) 669 { 670 /* Frame received? */ 671 if(GET_SDMA_PENDINGBIT(FEC_RECV_TASK_NO)) 672 { 673 674 SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,FEC_RECV_TASK_NO); 675 676 bestcomm_glue_irq_disable(FEC_RECV_TASK_NO);/*Disable receive ints*/ 677 678 enet_driver[0].rxInterrupts++; /* Rx int has occurred */ 679 680 rtems_event_send(enet_driver[0].rxDaemonTid, INTERRUPT_EVENT); 681 682 } 683 } 684 685 /* 686 * MPC5200 SmartComm ethernet interrupt handler 687 */ 688 void mpc5200_smartcomm_tx_irq_handler(rtems_irq_hdl_param unused) 689 { 690 /* Buffer transmitted or transmitter error? */ 691 if(GET_SDMA_PENDINGBIT(FEC_XMIT_TASK_NO)) 692 { 693 694 SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,FEC_XMIT_TASK_NO); 695 696 bestcomm_glue_irq_disable(FEC_XMIT_TASK_NO);/*Disable tx ints*/ 697 698 enet_driver[0].txInterrupts++; /* Tx int has occurred */ 699 700 rtems_event_send(enet_driver[0].txDaemonTid, INTERRUPT_EVENT); 701 702 } 703 704 } 705 706 707 708 709 710 /* 711 * Function: mpc5200_fec_retire_tbd 712 * 713 * Description: Soak up buffer descriptors that have been sent. 714 * 715 * Returns: void 716 * 717 * Notes: 718 * 719 */ 720 static void mpc5200_fec_retire_tbd(struct mpc5200_enet_struct *sc, 721 bool force) 722 { 723 struct mbuf *n; 724 TaskBD1_t *bdRing = (TaskBD1_t *)TaskGetBDRing( txTaskId );; 725 /* 726 * Clear already transmitted BDs first. Will not work calling same 727 * from fecExceptionHandler(TFINT). 728 */ 729 730 while ((sc->txBdActiveCount > 0) && 731 (force || (bdRing[sc->txBdTail].Status == 0x0))) { 732 if (sc->txMbuf[sc->txBdTail] != NULL) { 733 /* 734 * NOTE: txMbuf can be NULL, if mbuf has been split into different BDs 735 */ 736 MFREE (sc->txMbuf[sc->txBdTail],n); 737 sc->txMbuf[sc->txBdTail] = NULL; 738 } 739 sc->txBdActiveCount--; 740 if(++sc->txBdTail >= sc->txBdCount) { 741 sc->txBdTail = 0; 742 } 743 } 744 } 745 746 #if 0 747 /* 748 * Function: mpc5200_fec_tx_bd_requeue 749 * 750 * Description: put buffers back to interface output queue 751 * 752 * Returns: void 753 * 754 * Notes: 755 * 756 */ 757 static void mpc5200_fec_tx_bd_requeue(struct mpc5200_enet_struct *sc) 758 { 759 /* 760 * Clear already transmitted BDs first. Will not work calling same 761 * from fecExceptionHandler(TFINT). 762 */ 763 764 while (sc->txBdActiveCount > 0) { 765 if (sc->txMbuf[sc->txBdHead] != NULL) { 766 /* 767 * NOTE: txMbuf can be NULL, if mbuf has been split into different BDs 768 */ 769 IF_PREPEND(&(sc->arpcom.ac_if.if_snd),sc->txMbuf[sc->txBdHead]); 770 sc->txMbuf[sc->txBdHead] = NULL; 771 } 772 sc->txBdActiveCount--; 773 if(--sc->txBdHead < 0) { 774 sc->txBdHead = sc->txBdCount-1; 775 } 776 } 777 } 778 #endif 779 780 static void mpc5200_fec_sendpacket(struct ifnet *ifp,struct mbuf *m) { 781 struct mpc5200_enet_struct *sc = ifp->if_softc; 782 struct mbuf *l = NULL; 783 int nAdded; 784 uint32_t status; 785 rtems_event_set events; 786 TaskBD1_t *bdRing = (TaskBD1_t *)TaskGetBDRing( txTaskId ); 787 TaskBD1_t *thisBd; 788 TaskBD1_t *firstBd = NULL; 789 void *data_ptr; 790 size_t data_len; 791 792 /* 793 * Free up buffer descriptors 794 */ 795 mpc5200_fec_retire_tbd(sc,false); 796 797 /* 798 * Set up the transmit buffer descriptors. 799 * No need to pad out short packets since the 800 * hardware takes care of that automatically. 801 * No need to copy the packet to a contiguous buffer 802 * since the hardware is capable of scatter/gather DMA. 803 */ 804 nAdded = 0; 805 806 for(;;) { 807 808 /* 809 * Wait for buffer descriptor to become available. 810 */ 811 if((sc->txBdActiveCount + nAdded) == sc->txBdCount) { 812 813 /* 814 * Clear old events 815 */ 816 SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,FEC_XMIT_TASK_NO); 817 818 /* 819 * Wait for buffer descriptor to become available. 820 * Note that the buffer descriptors are checked 821 * *before* * entering the wait loop -- this catches 822 * the possibility that a buffer descriptor became 823 * available between the `if' above, and the clearing 824 * of the event register. 825 * This is to catch the case where the transmitter 826 * stops in the middle of a frame -- and only the 827 * last buffer descriptor in a frame can generate 828 * an interrupt. 829 */ 830 mpc5200_fec_retire_tbd(sc,false); 831 832 while((sc->txBdActiveCount + nAdded) == sc->txBdCount) { 833 bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO); 834 rtems_bsdnet_event_receive(INTERRUPT_EVENT, 835 RTEMS_WAIT | RTEMS_EVENT_ANY, 836 RTEMS_NO_TIMEOUT, &events); 837 mpc5200_fec_retire_tbd(sc,false); 838 } 839 } 840 841 if(m->m_len == 0) { 842 /* 843 * Just toss empty mbufs 844 */ 845 struct mbuf *n; 846 MFREE(m, n); 847 m = n; 848 if(l != NULL) { 849 l->m_next = m; 850 } 851 } 852 else { 853 /* 854 * Flush the buffer for this descriptor 855 */ 856 /*rtems_cache_flush_multiple_data_lines((const void *)mtod(m, void *), m->m_len);*/ 857 /* 858 * Fill in the buffer descriptor, 859 * set "end of frame" bit in status, 860 * if last mbuf in chain 861 */ 862 thisBd = bdRing + sc->txBdHead; 863 /* 864 * FIXME: do not send interrupt after every frame 865 * doing this every quarter of BDs is much more efficent 866 */ 867 status = ((m->m_next == NULL) 868 ? TASK_BD_TFD | TASK_BD_INT 869 : 0); 870 /* 871 * Don't set the READY flag till the 872 * whole packet has been readied. 873 */ 874 if (firstBd != NULL) { 875 status |= (uint32)SDMA_BD_MASK_READY; 876 } 877 else { 878 firstBd = thisBd; 879 } 880 881 data_ptr = mtod(m, void *); 882 data_len = (uint32)m->m_len; 883 sc->txMbuf[sc->txBdHead] = m; 884 /* go to next part in chain */ 885 l = m; 886 m = m->m_next; 887 888 thisBd->DataPtr[0] = (uint32)data_ptr; 889 thisBd->Status = (status 890 |((uint32)SDMA_DRD_MASK_LENGTH & data_len)); 891 892 nAdded++; 893 if(++(sc->txBdHead) == sc->txBdCount) { 894 sc->txBdHead = 0; 895 } 896 } 897 /* 898 * Set the transmit buffer status. 899 * Break out of the loop if this mbuf is the last in the frame. 900 */ 901 if(m == NULL) { 902 if(nAdded) { 903 firstBd->Status |= SDMA_BD_MASK_READY; 904 SDMA_TASK_ENABLE(SDMA_TCR, txTaskId); 905 sc->txBdActiveCount += nAdded; 906 } 907 break; 908 } 909 } /* end of for(;;) */ 910 } 911 912 913 /* 914 * Driver transmit daemon 915 */ 916 void mpc5200_fec_txDaemon(void *arg) 917 { 918 struct mpc5200_enet_struct *sc = (struct mpc5200_enet_struct *)arg; 919 struct ifnet *ifp = &sc->arpcom.ac_if; 920 struct mbuf *m; 921 rtems_event_set events; 922 923 for(;;) { 924 /* 925 * Wait for packet 926 */ 927 bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO); 928 rtems_bsdnet_event_receive(START_TRANSMIT_EVENT|INTERRUPT_EVENT, 929 RTEMS_EVENT_ANY | RTEMS_WAIT, 930 RTEMS_NO_TIMEOUT, 931 &events); 932 933 /* 934 * Send packets till queue is empty 935 */ 936 for(;;) 937 { 938 939 /* 940 * Get the next mbuf chain to transmit. 941 */ 942 IF_DEQUEUE(&ifp->if_snd, m); 943 944 if (!m) 945 break; 946 947 mpc5200_fec_sendpacket(ifp, m); 948 949 } 950 951 ifp->if_flags &= ~IFF_OACTIVE; 952 953 } 954 955 } 956 957 958 /* 959 * reader task 960 */ 961 static void mpc5200_fec_rxDaemon(void *arg){ 962 struct mpc5200_enet_struct *sc = (struct mpc5200_enet_struct *)arg; 963 struct ifnet *ifp = &sc->arpcom.ac_if; 964 struct mbuf *m; 965 struct ether_header *eh; 966 int rxBdIndex; 967 uint32_t status; 968 size_t size; 969 rtems_event_set events; 970 uint16 len = 1; 971 TaskBD1_t *bd; 972 void *dptr; 973 TaskBD1_t *bdRing = (TaskBD1_t *)TaskGetBDRing( rxTaskId );; 974 975 /* 976 * Input packet handling loop 977 */ 978 rxBdIndex = 0; 979 980 for (;;) { 981 /* 982 * Clear old events 983 */ 984 SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,FEC_RECV_TASK_NO); 985 /* 986 * Get the first BD pointer and its length. 987 */ 988 bd = bdRing + rxBdIndex; 989 status = bd->Status; 990 len = (uint16)GET_BD_LENGTH( bd ); 991 992 /* 993 * Loop through BDs until we find an empty one. This indicates that 994 * the SmartDMA is still using it. 995 */ 996 while( !(status & SDMA_BD_MASK_READY) ) { 997 998 /* 999 * Remember the data pointer from this transfer. 1000 */ 1001 dptr = (void *)bd->DataPtr[0]; 1002 m = sc->rxMbuf[rxBdIndex]; 1003 m->m_len = m->m_pkthdr.len = (len 1004 - sizeof(uint32_t) 1005 - sizeof(struct ether_header)); 1006 eh = mtod(m, struct ether_header *); 1007 m->m_data += sizeof(struct ether_header); 1008 ether_input(ifp, eh, m); 1009 1010 /* 1011 * Done w/ the BD. Clean it. 1012 */ 1013 sc->rxMbuf[rxBdIndex] = NULL; 1014 1015 /* 1016 * Add a new buffer to the ring. 1017 */ 1018 MGETHDR (m, M_WAIT, MT_DATA); 1019 MCLGET (m, M_WAIT); 1020 m->m_pkthdr.rcvif = ifp; 1021 size = ETHER_MAX_LEN; 1022 1023 sc->rxMbuf[rxBdIndex] = m; 1024 bd->DataPtr[0] = (uint32)mtod(m, void *); 1025 bd->Status = ( ( (uint32)SDMA_DRD_MASK_LENGTH & (uint32)size) 1026 | ((uint32)SDMA_BD_MASK_READY)); 1027 1028 /* 1029 * advance to next BD 1030 */ 1031 if (++rxBdIndex >= sc->rxBdCount) { 1032 rxBdIndex = 0; 1033 } 1034 /* 1035 * Get next BD pointer and its length. 1036 */ 1037 bd = bdRing + rxBdIndex; 1038 status = bd->Status; 1039 len = (uint16)GET_BD_LENGTH( bd ); 1040 } 1041 /* 1042 * Unmask RXF (Full frame received) event 1043 */ 1044 bestcomm_glue_irq_enable(FEC_RECV_TASK_NO); 1045 1046 rtems_bsdnet_event_receive (INTERRUPT_EVENT | FATAL_INT_EVENT, 1047 RTEMS_WAIT | RTEMS_EVENT_ANY, 1048 RTEMS_NO_TIMEOUT, &events); 1049 if (events & FATAL_INT_EVENT) { 1050 /* 1051 * fatal interrupt ocurred, so reinit fec and restart bestcomm tasks 1052 */ 1053 mpc5200_fec_restart(sc); 1054 rxBdIndex = 0; 1055 } 1056 } 1057 } 1058 536 mpc5200_fec_request_restart(self); 537 } 538 } 539 540 void mpc5200_smartcomm_rx_irq_handler(void *arg) 541 { 542 mpc5200_fec_context *self = arg; 543 544 ++self->rxInterrupts; 545 mpc5200_fec_send_event(self->rxDaemonTid); 546 SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, FEC_RECV_TASK_NO); 547 bestcomm_glue_irq_disable(FEC_RECV_TASK_NO); 548 } 549 550 void mpc5200_smartcomm_tx_irq_handler(void *arg) 551 { 552 mpc5200_fec_context *self = arg; 553 554 ++self->txInterrupts; 555 mpc5200_fec_send_event(self->txDaemonTid); 556 SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, FEC_XMIT_TASK_NO); 557 bestcomm_glue_irq_disable(FEC_XMIT_TASK_NO); 558 } 559 560 static void mpc5200_fec_init_mib(mpc5200_fec_context *self) 561 { 562 memset(&mpc5200.RES [0], 0, 0x2e4); 563 mpc5200.mib_control = 0x40000000; 564 } 1059 565 1060 566 /* … … 1069 575 * 1070 576 */ 1071 static void mpc5200_fec_initialize_hardware(struct mpc5200_enet_struct *sc) 1072 { 577 static void mpc5200_fec_initialize_hardware(mpc5200_fec_context *self) 578 { 579 /* We want at most 2.5MHz */ 580 uint32_t div = 2 * 2500000; 581 uint32_t mii_speed = (IPB_CLOCK + div - 1) / div; 1073 582 1074 583 /* 1075 584 * Reset mpc5200 FEC 1076 585 */ 1077 mpc5200_fec_reset(sc); 586 mpc5200_fec_reset(self); 587 mpc5200_fec_init_mib(self); 1078 588 1079 589 /* … … 1103 613 1104 614 /* 1105 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock(33Mhz)615 * Set MII_SPEED = IPB clock / (2 * mii_speed)) 1106 616 * and do not drop the Preamble. 1107 617 */ 1108 mpc5200.mii_speed = (7 << 1); /* ipb_clk = 33 MHz */618 mpc5200.mii_speed = mii_speed << 1; 1109 619 1110 620 /* … … 1136 646 * and set physical address registers. 1137 647 */ 1138 mpc5200_eth_addr_filter_set(s c);648 mpc5200_eth_addr_filter_set(self); 1139 649 1140 650 /* … … 1148 658 */ 1149 659 mpc5200.xmit_fsm = FEC_FSM_CRC | FEC_FSM_ENFSM; 1150 660 } 1151 661 1152 662 /* … … 1175 685 * 1176 686 */ 1177 static void mpc5200_fec_initialize_phy(struct mpc5200_enet_struct *sc) 1178 { 1179 int timeout; 1180 unsigned short phyAddr = 0; 1181 687 static void mpc5200_fec_initialize_phy(mpc5200_fec_context *self) 688 { 689 if (self->phyInitialized) { 690 return; 691 } else { 692 self->phyInitialized = true; 693 } 1182 694 1183 695 /* 1184 696 * Reset PHY, then delay 300ns 1185 697 */ 1186 mpc5200_eth_mii_write(s c, phyAddr, 0x0, 0x8000);698 mpc5200_eth_mii_write(self->phyAddr, self, 0x0, 0x8000); 1187 699 1188 700 rtems_task_wake_after(2); … … 1193 705 * Set the auto-negotiation advertisement register bits 1194 706 */ 1195 mpc5200_eth_mii_write(s c, phyAddr, 0x4, 0x01e1);707 mpc5200_eth_mii_write(self->phyAddr, self, 0x4, 0x01e1); 1196 708 1197 709 /* 1198 710 * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation 1199 711 */ 1200 mpc5200_eth_mii_write(s c, phyAddr, 0x0, 0x1200);712 mpc5200_eth_mii_write(self->phyAddr, self, 0x0, 0x1200); 1201 713 1202 714 /* 1203 715 * Wait for AN completion 1204 716 */ 1205 timeout = 0x100;1206 717 #if 0 718 int timeout = 0x100; 719 uint32_t phyStatus; 1207 720 do 1208 721 { … … 1219 732 } 1220 733 1221 if(mpc5200_eth_mii_read(s c, phyAddr, 0x1, &phyStatus) != true)734 if(mpc5200_eth_mii_read(self->phyAddr, self, 0x1, &phyStatus) != true) 1222 735 { 1223 736 1224 737 #if defined(ETH_DEBUG) 1225 printf ("MPC5200FEC PHY auto neg failed: 0x%04 x." "\r\n", phyStatus);738 printf ("MPC5200FEC PHY auto neg failed: 0x%04" PRIx32 ".\r\n", phyStatus); 1226 739 #endif 1227 740 … … 1243 756 #if defined(ETH_DEBUG) 1244 757 int i; 1245 u nsigned short phyStatus;758 uint32_t phyStatus; 1246 759 /* 1247 760 * Print PHY registers after initialization. … … 1250 763 { 1251 764 1252 mpc5200_eth_mii_read(s c, phyAddr, i, &phyStatus);1253 printf ("Mii reg %d: 0x%04 x""\r\n", i, phyStatus);765 mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus); 766 printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus); 1254 767 1255 768 } … … 1258 771 { 1259 772 1260 mpc5200_eth_mii_read(s c, phyAddr, i, &phyStatus);1261 printf ("Mii reg %d: 0x%04 x""\r\n", i, phyStatus);773 mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus); 774 printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus); 1262 775 1263 776 } … … 1266 779 } 1267 780 781 static void mpc5200_fec_restart(mpc5200_fec_context *self, rtems_id otherDaemon) 782 { 783 if (self->state == FEC_STATE_RESTART_1) { 784 mpc5200_fec_initialize_hardware(self); 785 mpc5200_fec_initialize_phy(self); 786 mpc5200_fec_start_dma_and_controller(); 787 self->state = FEC_STATE_NORMAL; 788 } else { 789 self->state = FEC_STATE_RESTART_1; 790 } 791 792 mpc5200_fec_send_event(otherDaemon); 793 while (self->state != FEC_STATE_NORMAL) { 794 mpc5200_fec_wait_for_event(); 795 } 796 } 1268 797 1269 798 /* … … 1273 802 { 1274 803 1275 struct mpc5200_enet_struct *sc= ifp->if_softc;804 mpc5200_fec_context *self = ifp->if_softc; 1276 805 1277 806 ifp->if_flags |= IFF_OACTIVE; 1278 807 1279 rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); 1280 1281 } 1282 1283 1284 /* 1285 * set up sdma tasks for ethernet 1286 */ 1287 static void mpc5200_sdma_task_setup(struct mpc5200_enet_struct *sc) { 1288 TaskSetupParamSet_t rxParam; /* RX task setup parameters */ 1289 TaskSetupParamSet_t txParam; /* TX task setup parameters */ 1290 1291 /* 1292 * Setup the SDMA RX task. 1293 */ 1294 rxParam.NumBD = sc->rxBdCount; 1295 rxParam.Size.MaxBuf = ETHER_MAX_LEN; 1296 rxParam.Initiator = 0; 1297 rxParam.StartAddrSrc = (uint32)&(mpc5200.rfifo_data); 1298 rxParam.IncrSrc = 0; 1299 rxParam.SzSrc = sizeof(uint32_t); 1300 rxParam.StartAddrDst = (uint32)NULL; 1301 rxParam.IncrDst = sizeof(uint32_t); 1302 rxParam.SzDst = sizeof(uint32_t); 1303 rxTaskId = TaskSetup(TASK_FEC_RX,&rxParam ); 1304 1305 /* 1306 * Setup the TX task. 1307 */ 1308 txParam.NumBD = sc->txBdCount; 1309 txParam.Size.MaxBuf = ETHER_MAX_LEN; 1310 txParam.Initiator = 0; 1311 txParam.StartAddrSrc = (uint32)NULL; 1312 txParam.IncrSrc = sizeof(uint32_t); 1313 txParam.SzSrc = sizeof(uint32_t); 1314 txParam.StartAddrDst = (uint32)&(mpc5200.tfifo_data); 1315 txParam.IncrDst = 0; 1316 txParam.SzDst = sizeof(uint32_t); 1317 1318 txTaskId = TaskSetup( TASK_FEC_TX, &txParam ); 1319 1320 } 1321 1322 void mpc5200_fec_irq_on(const rtems_irq_connect_data* ptr) 1323 { 1324 mpc5200.imask = FEC_INTR_MASK_USED; 1325 } 1326 1327 1328 int mpc5200_fec_irq_isOn(const rtems_irq_connect_data* ptr) 1329 { 1330 return mpc5200.imask != 0; 1331 } 1332 1333 1334 void mpc5200_fec_irq_off(const rtems_irq_connect_data* ptr) 1335 { 1336 mpc5200.imask = 0; 1337 } 1338 808 mpc5200_fec_send_event(self->txDaemonTid); 809 810 } 811 812 static TaskBD1_t *mpc5200_fec_init_tx_dma(int bdCount, struct mbuf **mbufs) 813 { 814 TaskSetupParamSet_t param = { 815 .NumBD = bdCount, 816 .Size = { 817 .MaxBuf = ETHER_MAX_LEN 818 }, 819 .Initiator = 0, 820 .StartAddrSrc = 0, 821 .IncrSrc = sizeof(uint32_t), 822 .SzSrc = sizeof(uint32_t), 823 .StartAddrDst = (uint32) &mpc5200.tfifo_data, 824 .IncrDst = 0, 825 .SzDst = sizeof(uint32_t) 826 }; 827 int bdIndex = 0; 828 829 TaskSetup(FEC_XMIT_TASK_NO, ¶m); 830 831 for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { 832 mbufs [bdIndex] = NULL; 833 } 834 835 return (TaskBD1_t *) TaskGetBDRing(FEC_XMIT_TASK_NO); 836 } 837 838 #if 0 839 static void mpc5200_fec_requeue_and_discard_tx_frames( 840 int bdIndex, 841 int bdCount, 842 TaskBD1_t *bdRing, 843 struct mbuf **mbufs 844 ) 845 { 846 int bdStop = bdIndex; 847 struct mbuf *previous = NULL; 848 849 do { 850 struct mbuf *current = NULL; 851 uint32 status = 0; 852 TaskBD1_t *bd = NULL; 853 854 if (bdIndex > 1) { 855 --bdIndex; 856 } else { 857 bdIndex = bdCount - 1; 858 } 859 860 current = mbufs [bdIndex]; 861 mbufs [bdIndex] = NULL; 862 863 status = bdRing [bdIndex].Status; 864 bdRing [bdIndex].Status = 0; 865 866 if (current != NULL) { 867 if ((status & FEC_BD_LAST) != 0) { 868 if (previous != NULL) { 869 IF_PREPEND(&ifp->if_snd, previous); 870 } 871 } 872 } else { 873 break; 874 } 875 876 previous = current; 877 } while (bdIndex != bdStop); 878 } 879 #endif 880 881 static void mpc5200_fec_discard_tx_frames( 882 int bdCount, 883 struct mbuf **mbufs 884 ) 885 { 886 int bdIndex = 0; 887 888 for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { 889 struct mbuf *m = mbufs [bdIndex]; 890 891 if (m != NULL) { 892 mbufs [bdIndex] = NULL; 893 m_free(m); 894 } 895 } 896 } 897 898 static void mpc5200_fec_reset_tx_dma( 899 int bdCount, 900 TaskBD1_t *bdRing, 901 struct mbuf **mbufs, 902 struct mbuf *m 903 ) 904 { 905 TaskStop(FEC_XMIT_TASK_NO); 906 TaskBDReset(FEC_XMIT_TASK_NO); 907 mpc5200_fec_discard_tx_frames(bdCount, mbufs); 908 while (m != NULL) { 909 m = m_free(m); 910 } 911 } 912 913 static struct mbuf *mpc5200_fec_next_fragment( 914 struct ifnet *ifp, 915 struct mbuf *m, 916 bool *isFirst 917 ) 918 { 919 struct mbuf *n = NULL; 920 921 *isFirst = false; 922 923 while (true) { 924 if (m == NULL) { 925 IF_DEQUEUE(&ifp->if_snd, m); 926 927 if (m != NULL) { 928 *isFirst = true; 929 } else { 930 ifp->if_flags &= ~IFF_OACTIVE; 931 932 return NULL; 933 } 934 } 935 936 if (m->m_len > 0) { 937 break; 938 } else { 939 m = m_free(m); 940 } 941 } 942 943 n = m->m_next; 944 while (n != NULL && n->m_len <= 0) { 945 n = m_free(n); 946 } 947 m->m_next = n; 948 949 return m; 950 } 951 952 static bool mpc5200_fec_transmit( 953 struct ifnet *ifp, 954 int bdCount, 955 TaskBD1_t *bdRing, 956 struct mbuf **mbufs, 957 int *bdIndexPtr, 958 struct mbuf **mPtr, 959 TaskBD1_t **firstPtr 960 ) 961 { 962 bool bdShortage = false; 963 int bdIndex = *bdIndexPtr; 964 struct mbuf *m = *mPtr; 965 TaskBD1_t *first = *firstPtr; 966 967 while (true) { 968 TaskBD1_t *bd = &bdRing [bdIndex]; 969 970 if (bd->Status == 0) { 971 struct mbuf *done = mbufs [bdIndex]; 972 bool isFirst = false; 973 974 if (done != NULL) { 975 m_free(done); 976 mbufs [bdIndex] = NULL; 977 } 978 979 m = mpc5200_fec_next_fragment(ifp, m, &isFirst); 980 if (m != NULL) { 981 uint32 status = (uint32) m->m_len; 982 983 mbufs [bdIndex] = m; 984 985 rtems_cache_flush_multiple_data_lines(mtod(m, void *), m->m_len); 986 987 if (isFirst) { 988 first = bd; 989 } else { 990 status |= FEC_BD_READY; 991 } 992 993 bd->DataPtr [0] = mtod(m, uint32); 994 995 if (m->m_next != NULL) { 996 bd->Status = status; 997 } else { 998 bd->Status = status | FEC_BD_INT | FEC_BD_LAST; 999 first->Status |= FEC_BD_READY; 1000 SDMA_TASK_ENABLE(SDMA_TCR, FEC_XMIT_TASK_NO); 1001 } 1002 1003 m = m->m_next; 1004 } else { 1005 break; 1006 } 1007 } else { 1008 bdShortage = true; 1009 break; 1010 } 1011 1012 if (bdIndex < bdCount - 1) { 1013 ++bdIndex; 1014 } else { 1015 bdIndex = 0; 1016 } 1017 } 1018 1019 *bdIndexPtr = bdIndex; 1020 *mPtr = m; 1021 *firstPtr = first; 1022 1023 return bdShortage; 1024 } 1025 1026 static void mpc5200_fec_tx_daemon(void *arg) 1027 { 1028 mpc5200_fec_context *self = arg; 1029 struct ifnet *ifp = &self->arpcom.ac_if; 1030 int bdIndex = 0; 1031 int bdCount = self->txBdCount; 1032 struct mbuf **mbufs = &self->txMbuf [0]; 1033 struct mbuf *m = NULL; 1034 TaskBD1_t *bdRing = mpc5200_fec_init_tx_dma(bdCount, mbufs); 1035 TaskBD1_t *first = NULL; 1036 bool bdShortage = false; 1037 1038 while (true) { 1039 if (bdShortage) { 1040 bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO); 1041 } 1042 mpc5200_fec_wait_for_event(); 1043 1044 if (self->state != FEC_STATE_NORMAL) { 1045 mpc5200_fec_reset_tx_dma(bdCount, bdRing, mbufs, m); 1046 mpc5200_fec_restart(self, self->rxDaemonTid); 1047 bdIndex = 0; 1048 m = NULL; 1049 first = NULL; 1050 } 1051 1052 bdShortage = mpc5200_fec_transmit( 1053 ifp, 1054 bdCount, 1055 bdRing, 1056 mbufs, 1057 &bdIndex, 1058 &m, 1059 &first 1060 ); 1061 } 1062 } 1063 1064 static struct mbuf *mpc5200_fec_add_mbuf(struct ifnet *ifp, TaskBD1_t *bd) 1065 { 1066 struct mbuf *m = NULL; 1067 1068 MGETHDR (m, M_WAIT, MT_DATA); 1069 MCLGET (m, M_WAIT); 1070 m->m_pkthdr.rcvif = ifp; 1071 1072 /* XXX: The dcbi operation does not work properly */ 1073 rtems_cache_flush_multiple_data_lines(mtod(m, void *), ETHER_MAX_LEN); 1074 1075 bd->DataPtr [0] = mtod(m, uint32); 1076 bd->Status = ETHER_MAX_LEN | FEC_BD_READY; 1077 1078 return m; 1079 } 1080 1081 static TaskBD1_t *mpc5200_fec_init_rx_dma( 1082 struct ifnet *ifp, 1083 int bdCount, 1084 struct mbuf **mbufs 1085 ) 1086 { 1087 TaskSetupParamSet_t param = { 1088 .NumBD = bdCount, 1089 .Size = { 1090 .MaxBuf = ETHER_MAX_LEN 1091 }, 1092 .Initiator = 0, 1093 .StartAddrSrc = (uint32) &mpc5200.rfifo_data, 1094 .IncrSrc = 0, 1095 .SzSrc = sizeof(uint32_t), 1096 .StartAddrDst = 0, 1097 .IncrDst = sizeof(uint32_t), 1098 .SzDst = sizeof(uint32_t) 1099 }; 1100 TaskBD1_t *bdRing = NULL; 1101 int bdIndex = 0; 1102 1103 TaskSetup(FEC_RECV_TASK_NO, ¶m); 1104 bdRing = (TaskBD1_t *) TaskGetBDRing(FEC_RECV_TASK_NO); 1105 1106 for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { 1107 mbufs [bdIndex] = mpc5200_fec_add_mbuf(ifp, &bdRing [bdIndex]); 1108 } 1109 1110 return bdRing; 1111 } 1112 1113 static void mpc5200_fec_reset_rx_dma(int bdCount, TaskBD1_t *bdRing) 1114 { 1115 int bdIndex = 0; 1116 1117 TaskStop(FEC_RECV_TASK_NO); 1118 TaskBDReset(FEC_RECV_TASK_NO); 1119 1120 for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { 1121 bdRing [bdIndex].Status = ETHER_MAX_LEN | FEC_BD_READY; 1122 } 1123 } 1124 1125 static int mpc5200_fec_ether_input( 1126 struct ifnet *ifp, 1127 int bdIndex, 1128 int bdCount, 1129 TaskBD1_t *bdRing, 1130 struct mbuf **mbufs 1131 ) 1132 { 1133 while (true) { 1134 TaskBD1_t *bd = &bdRing [bdIndex]; 1135 struct mbuf *m = mbufs [bdIndex]; 1136 uint32 status = 0; 1137 int len = 0; 1138 struct ether_header *eh = NULL; 1139 1140 SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, FEC_RECV_TASK_NO); 1141 status = bd->Status; 1142 1143 if ((status & FEC_BD_READY) != 0) { 1144 break; 1145 } 1146 1147 eh = mtod(m, struct ether_header *); 1148 1149 len = (status & 0xffff) - ETHER_HDR_LEN - ETHER_CRC_LEN; 1150 m->m_len = len; 1151 m->m_pkthdr.len = len; 1152 m->m_data = mtod(m, char *) + ETHER_HDR_LEN; 1153 1154 ether_input(ifp, eh, m); 1155 1156 mbufs [bdIndex] = mpc5200_fec_add_mbuf(ifp, bd); 1157 1158 if (bdIndex < bdCount - 1) { 1159 ++bdIndex; 1160 } else { 1161 bdIndex = 0; 1162 } 1163 } 1164 1165 return bdIndex; 1166 } 1167 1168 static void mpc5200_fec_rx_daemon(void *arg) 1169 { 1170 mpc5200_fec_context *self = arg; 1171 struct ifnet *ifp = &self->arpcom.ac_if; 1172 int bdIndex = 0; 1173 int bdCount = self->rxBdCount; 1174 struct mbuf **mbufs = &self->rxMbuf [0]; 1175 TaskBD1_t *bdRing = mpc5200_fec_init_rx_dma(ifp, bdCount, mbufs); 1176 1177 while (true) { 1178 bestcomm_glue_irq_enable(FEC_RECV_TASK_NO); 1179 mpc5200_fec_wait_for_event(); 1180 1181 bdIndex = mpc5200_fec_ether_input(ifp, bdIndex, bdCount, bdRing, mbufs); 1182 1183 if (self->state != FEC_STATE_NORMAL) { 1184 mpc5200_fec_reset_rx_dma(bdCount, bdRing); 1185 mpc5200_fec_restart(self, self->txDaemonTid); 1186 bdIndex = 0; 1187 } 1188 } 1189 } 1339 1190 1340 1191 /* … … 1343 1194 static void mpc5200_fec_init(void *arg) 1344 1195 { 1345 struct mpc5200_enet_struct *sc = (struct mpc5200_enet_struct *)arg; 1346 struct ifnet *ifp = &sc->arpcom.ac_if; 1347 rtems_irq_connect_data fec_irq_data = { 1348 BSP_SIU_IRQ_ETH, 1349 mpc5200_fec_irq_handler, /* rtems_irq_hdl */ 1350 (rtems_irq_hdl_param)sc, /* (rtems_irq_hdl_param) */ 1351 mpc5200_fec_irq_on, /* (rtems_irq_enable) */ 1352 mpc5200_fec_irq_off, /* (rtems_irq_disable) */ 1353 mpc5200_fec_irq_isOn /* (rtems_irq_is_enabled) */ 1354 }; 1355 1356 1357 if(sc->txDaemonTid == 0) 1196 rtems_status_code sc = RTEMS_SUCCESSFUL; 1197 mpc5200_fec_context *self = (mpc5200_fec_context *)arg; 1198 struct ifnet *ifp = &self->arpcom.ac_if; 1199 1200 if(self->txDaemonTid == 0) 1358 1201 { 1202 size_t rxMbufTableSize = self->rxBdCount * sizeof(*self->rxMbuf); 1203 size_t txMbufTableSize = self->txBdCount * sizeof(*self->txMbuf); 1204 1359 1205 /* 1360 1206 * Allocate a set of mbuf pointers 1361 1207 */ 1362 sc->rxMbuf = 1363 malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT); 1364 sc->txMbuf = 1365 malloc(sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT); 1366 1367 if(!sc->rxMbuf || !sc->txMbuf) 1208 self->rxMbuf = malloc(rxMbufTableSize, M_MBUF, M_NOWAIT); 1209 self->txMbuf = malloc(txMbufTableSize, M_MBUF, M_NOWAIT); 1210 1211 if(!self->rxMbuf || !self->txMbuf) 1368 1212 rtems_panic ("No memory for mbuf pointers"); 1369 1213 1214 /* 1215 * DMA setup 1216 */ 1370 1217 bestcomm_glue_init(); 1371 1372 mpc5200_sdma_task_setup(sc); 1218 mpc5200.sdma.ipr [0] = 4; /* always initiator */ 1219 mpc5200.sdma.ipr [3] = 6; /* eth rx initiator */ 1220 mpc5200.sdma.ipr [4] = 5; /* eth tx initiator */ 1373 1221 1374 1222 /* … … 1377 1225 bestcomm_glue_irq_install(FEC_RECV_TASK_NO, 1378 1226 mpc5200_smartcomm_rx_irq_handler, 1379 NULL);1227 self); 1380 1228 bestcomm_glue_irq_install(FEC_XMIT_TASK_NO, 1381 1229 mpc5200_smartcomm_tx_irq_handler, 1382 NULL); 1383 if(!BSP_install_rtems_irq_handler (&fec_irq_data)) { 1230 self); 1231 sc = rtems_interrupt_handler_install( 1232 BSP_SIU_IRQ_ETH, 1233 "FEC", 1234 RTEMS_INTERRUPT_UNIQUE, 1235 mpc5200_fec_irq_handler, 1236 self 1237 ); 1238 if(sc != RTEMS_SUCCESSFUL) { 1384 1239 rtems_panic ("Can't attach MPC5x00 FEX interrupt handler\n"); 1385 1240 } 1386 1387 /* mpc5200_fec_tx_bd_init(sc); */1388 mpc5200_fec_rx_bd_init(sc);1389 1390 /*1391 * reset and Set up mpc5200 FEC hardware1392 */1393 mpc5200_fec_initialize_hardware(sc);1394 /*1395 * Set up the phy1396 */1397 mpc5200_fec_initialize_phy(sc);1398 /*1399 * Set priority of different initiators1400 */1401 mpc5200.sdma.ipr [0] = 7; /* always initiator */1402 mpc5200.sdma.ipr [3] = 6; /* eth rx initiator */1403 mpc5200.sdma.ipr [4] = 5; /* eth tx initiator */1404 1241 1405 1242 /* 1406 1243 * Start driver tasks 1407 1244 */ 1408 sc->txDaemonTid = rtems_bsdnet_newproc("FEtx", 4096, mpc5200_fec_txDaemon, sc); 1409 sc->rxDaemonTid = rtems_bsdnet_newproc("FErx", 4096, mpc5200_fec_rxDaemon, sc); 1410 /* 1411 * Clear SmartDMA task interrupt pending bits. 1412 */ 1413 TaskIntClear( rxTaskId ); 1414 1415 /* 1416 * Enable the SmartDMA receive task. 1417 */ 1418 TaskStart( rxTaskId, 1, rxTaskId, 1 ); 1419 TaskStart( txTaskId, 1, txTaskId, 1 ); 1420 /* 1421 * Enable FEC-Lite controller 1422 */ 1423 mpc5200.ecntrl |= (FEC_ECNTRL_OE | FEC_ECNTRL_EN); 1424 1425 1426 } 1245 self->txDaemonTid = rtems_bsdnet_newproc("FEtx", 4096, mpc5200_fec_tx_daemon, self); 1246 self->rxDaemonTid = rtems_bsdnet_newproc("FErx", 4096, mpc5200_fec_rx_daemon, self); 1247 } 1248 1249 mpc5200_fec_request_restart(self); 1427 1250 1428 1251 /* … … 1440 1263 } 1441 1264 1442 1443 static void enet_stats (struct mpc5200_enet_struct *sc) 1444 { 1445 printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); 1446 printf (" Not First:%-8lu", sc->rxNotFirst); 1447 printf (" Not Last:%-8lu\n", sc->rxNotLast); 1448 printf (" Giant:%-8lu", sc->rxGiant); 1449 printf (" Non-octet:%-8lu\n", sc->rxNonOctet); 1450 printf (" Bad CRC:%-8lu", sc->rxBadCRC); 1451 printf (" Overrun:%-8lu", sc->rxOverrun); 1452 printf (" Collision:%-8lu\n", sc->rxCollision); 1453 1454 printf (" Tx Interrupts:%-8lu", sc->txInterrupts); 1455 printf (" Deferred:%-8lu", sc->txDeferred); 1456 printf (" Late Collision:%-8lu\n", sc->txLateCollision); 1457 printf (" Retransmit Limit:%-8lu", sc->txRetryLimit); 1458 printf (" Underrun:%-8lu", sc->txUnderrun); 1459 printf (" Misaligned:%-8lu\n", sc->txMisaligned); 1460 1461 } 1462 1463 /* 1464 * restart the driver, reinit the fec 1465 * this function is responsible to reinitialize the FEC in case a fatal 1466 * error has ocurred. This is needed, wen a RxFIFO Overrun or a TxFIFO underrun 1467 * has ocurred. In these cases, the FEC is automatically disabled, and 1468 * both FIFOs must be reset and the BestComm tasks must be restarted 1469 * 1470 * Note: the daemon tasks will continue to run 1471 * (in fact this function will be called in the context of the rx daemon task) 1472 */ 1473 #define NEW_SDMA_SETUP 1474 1475 static void mpc5200_fec_restart(struct mpc5200_enet_struct *sc) 1476 { 1477 /* 1478 * FIXME: bring Tx Daemon into idle state 1479 */ 1480 #ifdef NEW_SDMA_SETUP 1481 /* 1482 * cleanup remaining receive mbufs 1483 */ 1484 mpc5200_fec_rx_bd_cleanup(sc); 1485 #endif 1486 /* 1487 * Stop SDMA tasks 1488 */ 1489 TaskStop( rxTaskId); 1490 TaskStop( txTaskId); 1491 /* 1492 * FIXME: wait, until Tx Daemon is in idle state 1493 */ 1494 1495 /* 1496 * Disable transmit / receive interrupts 1497 */ 1498 bestcomm_glue_irq_disable(FEC_XMIT_TASK_NO); 1499 bestcomm_glue_irq_disable(FEC_RECV_TASK_NO); 1500 #ifdef NEW_SDMA_SETUP 1501 /* 1502 * recycle pending tx buffers 1503 * FIXME: try to extract pending Tx buffers 1504 */ 1505 #if 0 1506 mpc5200_fec_tx_bd_requeue(sc); 1507 #else 1508 mpc5200_fec_retire_tbd(sc,true); 1509 #endif 1510 #endif 1511 /* 1512 * re-initialize the FEC hardware 1513 */ 1514 mpc5200_fec_initialize_hardware(sc); 1515 1516 #ifdef NEW_SDMA_SETUP 1517 /* 1518 * completely reinitialize Bestcomm tasks 1519 */ 1520 mpc5200_sdma_task_setup(sc); 1521 1522 /* 1523 * reinit receive mbufs 1524 */ 1525 mpc5200_fec_rx_bd_init(sc); 1526 #endif 1527 /* 1528 * Clear SmartDMA task interrupt pending bits. 1529 */ 1530 TaskIntClear( rxTaskId ); 1531 1532 /* 1533 * Enable the SmartDMA receive/transmit task. 1534 */ 1535 TaskStart( rxTaskId, 1, rxTaskId, 1 ); 1536 TaskStart( txTaskId, 1, txTaskId, 1 ); 1537 /* 1538 * reenable rx/tx interrupts 1539 */ 1540 bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO); 1541 bestcomm_glue_irq_enable(FEC_RECV_TASK_NO); 1542 /* 1543 * (re-)init fec hardware 1544 */ 1545 mpc5200_fec_initialize_hardware(sc); 1546 /* 1547 * reenable fec FIFO error interrupts 1548 */ 1549 mpc5200.imask = FEC_INTR_MASK_USED; 1550 /* 1551 * Enable FEC-Lite controller 1552 */ 1553 mpc5200.ecntrl |= (FEC_ECNTRL_OE | FEC_ECNTRL_EN); 1265 static void enet_stats (mpc5200_fec_context *self) 1266 { 1267 if (self->phyAddr >= 0) { 1268 struct ifnet *ifp = &self->arpcom.ac_if; 1269 int media = IFM_MAKEWORD(0, 0, 0, self->phyAddr); 1270 int rv = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t) &media); 1271 1272 if (rv == 0) { 1273 rtems_ifmedia2str(media, NULL, 0); 1274 printf ("\n"); 1275 } else { 1276 printf ("PHY communication error\n"); 1277 } 1278 } 1279 printf (" Rx Interrupts:%-8lu", self->rxInterrupts); 1280 printf (" Rx Not First:%-8lu", self->rxNotFirst); 1281 printf (" Rx Not Last:%-8lu\n", self->rxNotLast); 1282 printf (" Rx Giant:%-8lu", self->rxGiant); 1283 printf (" Rx Non-octet:%-8lu", self->rxNonOctet); 1284 printf (" Rx Bad CRC:%-8lu\n", self->rxBadCRC); 1285 printf (" Rx FIFO Error:%-8lu", self->rxFIFOError); 1286 printf (" Rx Collision:%-8lu", self->rxCollision); 1287 1288 printf (" Tx Interrupts:%-8lu\n", self->txInterrupts); 1289 printf (" Tx Deferred:%-8lu", self->txDeferred); 1290 printf (" Tx Late Collision:%-8lu", self->txLateCollision); 1291 printf (" Tx Retransmit Limit:%-8lu\n", self->txRetryLimit); 1292 printf (" Tx Underrun:%-8lu", self->txUnderrun); 1293 printf (" Tx FIFO Error:%-8lu", self->txFIFOError); 1294 printf (" Tx Misaligned:%-8lu\n", self->txMisaligned); 1554 1295 } 1555 1296 1556 1297 int32_t mpc5200_fec_setMultiFilter(struct ifnet *ifp) 1557 1298 { 1558 /* struct mpc5200_enet_struct *sc= ifp->if_softc; */1299 /*mpc5200_fec_context *self = ifp->if_softc; */ 1559 1300 /* XXX anything to do? */ 1560 1301 return 0; … … 1567 1308 static int mpc5200_fec_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) 1568 1309 { 1569 struct mpc5200_enet_struct *sc= ifp->if_softc;1310 mpc5200_fec_context *self = ifp->if_softc; 1570 1311 int error = 0; 1571 1312 … … 1584 1325 struct ifreq* ifr = (struct ifreq*) data; 1585 1326 error = (command == SIOCADDMULTI) 1586 ? ether_addmulti(ifr, &s c->arpcom)1587 : ether_delmulti(ifr, &s c->arpcom);1327 ? ether_addmulti(ifr, &self->arpcom) 1328 : ether_delmulti(ifr, &self->arpcom); 1588 1329 1589 1330 if (error == ENETRESET) { … … 1603 1344 case IFF_RUNNING: 1604 1345 1605 mpc5200_fec_off(s c);1346 mpc5200_fec_off(self); 1606 1347 1607 1348 break; … … 1609 1350 case IFF_UP: 1610 1351 1611 mpc5200_fec_init(s c);1352 mpc5200_fec_init(self); 1612 1353 1613 1354 break; … … 1615 1356 case IFF_UP | IFF_RUNNING: 1616 1357 1617 mpc5200_fec_off(s c);1618 mpc5200_fec_init(s c);1358 mpc5200_fec_off(self); 1359 mpc5200_fec_init(self); 1619 1360 1620 1361 break; … … 1627 1368 break; 1628 1369 1370 case SIOCGIFMEDIA: 1371 case SIOCSIFMEDIA: 1372 error = rtems_mii_ioctl(&self->mdio, self, command, (int *) data); 1373 break; 1374 1629 1375 case SIO_RTEMS_SHOW_STATS: 1630 1376 1631 enet_stats(s c);1377 enet_stats(self); 1632 1378 1633 1379 break; … … 1654 1400 int rtems_mpc5200_fec_driver_attach(struct rtems_bsdnet_ifconfig *config) 1655 1401 { 1656 struct mpc5200_enet_struct *sc;1402 mpc5200_fec_context *self; 1657 1403 struct ifnet *ifp; 1658 1404 int mtu; … … 1677 1423 } 1678 1424 1679 s c= &enet_driver[unitNumber - 1];1680 ifp = &s c->arpcom.ac_if;1425 self = &enet_driver[unitNumber - 1]; 1426 ifp = &self->arpcom.ac_if; 1681 1427 1682 1428 if(ifp->if_softc != NULL) … … 1687 1433 1688 1434 } 1435 1436 self->mdio.mdio_r = mpc5200_eth_mii_read; 1437 self->mdio.mdio_w = mpc5200_eth_mii_write; 1689 1438 1690 1439 /* … … 1727 1476 1728 1477 /* Anything in the first three bytes indicates a non-zero entry, copy value */ 1729 memcpy((void *)s c->arpcom.ac_enaddr, &nvram->enaddr, ETHER_ADDR_LEN);1478 memcpy((void *)self->arpcom.ac_enaddr, &nvram->enaddr, ETHER_ADDR_LEN); 1730 1479 1731 1480 } … … 1735 1484 1736 1485 /* There is no entry in NVRAM, but there is in the ifconfig struct, so use it. */ 1737 memcpy((void *)s c->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);1486 memcpy((void *)self->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); 1738 1487 } 1739 1488 else … … 1750 1499 { 1751 1500 1752 memcpy(s c->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);1501 memcpy(self->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); 1753 1502 1754 1503 } … … 1765 1514 #endif /* NVRAM_CONFIGURE != 1 */ 1766 1515 #ifdef HAS_UBOOT 1767 if ((s c->arpcom.ac_enaddr[0] == 0) &&1768 (s c->arpcom.ac_enaddr[1] == 0) &&1769 (s c->arpcom.ac_enaddr[2] == 0)) {1516 if ((self->arpcom.ac_enaddr[0] == 0) && 1517 (self->arpcom.ac_enaddr[1] == 0) && 1518 (self->arpcom.ac_enaddr[2] == 0)) { 1770 1519 memcpy( 1771 (void *)s c->arpcom.ac_enaddr,1520 (void *)self->arpcom.ac_enaddr, 1772 1521 bsp_uboot_board_info.bi_enetaddr, 1773 1522 ETHER_ADDR_LEN … … 1781 1530 1782 1531 if(config->rbuf_count) 1783 s c->rxBdCount = config->rbuf_count;1532 self->rxBdCount = config->rbuf_count; 1784 1533 else 1785 s c->rxBdCount = RX_BUF_COUNT;1534 self->rxBdCount = RX_BUF_COUNT; 1786 1535 1787 1536 if(config->xbuf_count) 1788 s c->txBdCount = config->xbuf_count;1537 self->txBdCount = config->xbuf_count; 1789 1538 else 1790 s c->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;1791 1792 s c->acceptBroadcast = !config->ignore_broadcast;1539 self->txBdCount = TX_BUF_COUNT; 1540 1541 self->acceptBroadcast = !config->ignore_broadcast; 1793 1542 1794 1543 /* 1795 1544 * Set up network interface values 1796 1545 */ 1797 ifp->if_softc = s c;1546 ifp->if_softc = self; 1798 1547 ifp->if_unit = unitNumber; 1799 1548 ifp->if_name = unitName; -
c/src/lib/libbsp/powerpc/gen5200/start/start.S
r1dd95cc r25ed11d0 157 157 .extern boot_card 158 158 159 .section ".vectors", "ax" 160 bl start 161 .rep 63 162 .long 0x04000400 163 .endr 164 __vec2: b __vec2 165 .rep 63 166 .long 0x04000400 167 .endr 168 __vec3: b __vec3 169 .rep 63 170 .long 0x04000400 171 .endr 172 __vec4: b __vec4 173 .rep 63 174 .long 0x04000400 175 .endr 176 __vec5: b __vec5 177 .rep 63 178 .long 0x04000400 179 .endr 180 __vec6: b __vec6 181 .rep 63 182 .long 0x04000400 183 .endr 184 __vec7: b __vec7 185 .rep 63 186 .long 0x04000400 187 .endr 188 __vec8: b __vec8 189 .rep 63 190 .long 0x04000400 191 .endr 192 __vec9: b __vec9 193 .rep 63 194 .long 0x04000400 195 .endr 196 __veca: b __veca 197 .rep 63 198 .long 0x04000400 199 .endr 200 __vecb: b __vecb 201 .rep 63 202 .long 0x04000400 203 .endr 204 __vecc: b __vecc 205 .rep 63 206 .long 0x04000400 207 .endr 208 __vecd: b __vecd 209 .rep 63 210 .long 0x04000400 211 .endr 212 __vece: b __vece 213 .rep 63 214 .long 0x04000400 215 .endr 216 __vecf: b __vecf 217 .rep 63+1024 218 .long 0x04000400 219 .endr 220 159 221 .section ".entry" 160 222 PUBLIC_VAR (start) … … 244 306 stw r30, CS0STR(r31) /* Set CS0STR */ 245 307 246 LWI r30, bsp_rom_end 308 LWI r30, bsp_rom_end - 1 247 309 248 310 rlwinm r30, r30,17,15,31 … … 280 342 bl SDRAM_init /* Initialize SDRAM controller */ 281 343 282 /* init arbiter and stuff... */ 283 LWI r30, 0x8000a06e 284 stw r30, ARBCFG(r31) /* Set ARBCFG */ 285 286 LWI r30, 0x000000ff 287 stw r30, ARBMPREN(r31) /* Set ARBMPREN */ 288 289 LWI r30, 0x00001234 290 stw r30, ARBMPRIO(r31) /* Set ARBPRIO */ 291 292 LWI r30, 0x0000001e 293 stw r30, ARBSNOOP(r31) /* Set ARBSNOOP */ 344 bl XLB_init 294 345 /* copy .text section from ROM to RAM location (unique for ROM startup) */ 295 346 LA r30, bsp_section_text_start /* get start address of text section in RAM */ … … 396 447 bl clr_mem /* Clear onchip SRAM */ 397 448 449 #else /* defined(NEED_LOW_LEVEL_INIT) */ 450 bl XLB_init 398 451 #endif /* defined(NEED_LOW_LEVEL_INIT) */ 399 452 /* clear .bss section (unique for ROM startup) */ … … 844 897 blr /* return */ 845 898 846 847 899 XLB_init: 900 /* init arbiter and stuff... */ 901 LWI r30, 0x8000a06e 902 stw r30, ARBCFG(r31) /* Set ARBCFG */ 903 904 LWI r30, 0x000000ff 905 stw r30, ARBMPREN(r31) /* Set ARBMPREN */ 906 907 LWI r30, 0x00001234 908 stw r30, ARBMPRIO(r31) /* Set ARBPRIO */ 909 910 LWI r30, 0x0000001e 911 stw r30, ARBSNOOP(r31) /* Set ARBSNOOP */ 912 913 blr -
c/src/lib/libbsp/powerpc/gen5200/startup/bspstart.c
r1dd95cc r25ed11d0 104 104 #include <bsp/irq.h> 105 105 #include <bsp/irq-generic.h> 106 #include <bsp/mpc5200.h> 106 107 107 108 /* … … 144 145 145 146 cpu_init(); 147 148 if(get_ppc_cpu_revision() >= 0x2014) { 149 /* Special settings for MPC5200B (B variant) */ 150 uint32_t xlb_cfg = mpc5200.config; 151 152 /* XXX: The Freescale documentation for BSDIS seems to be wrong */ 153 xlb_cfg |= XLB_CFG_BSDIS; 154 155 xlb_cfg &= ~XLB_CFG_PLDIS; 156 157 mpc5200.config = xlb_cfg; 158 } 146 159 147 160 bsp_clicks_per_usec = (XLB_CLOCK/4000000); … … 167 180 BSP_panic("cannot initialize exceptions"); 168 181 } 182 ppc_exc_set_handler(ASM_ALIGN_VECTOR, ppc_exc_alignment_handler); 169 183 170 184 /* Initalize interrupt support */ -
c/src/lib/libbsp/powerpc/gen5200/startup/cpuinit.c
r1dd95cc r25ed11d0 170 170 171 171 /* 172 * Accesses (also speculative accesses) outside of the RAM area are a 173 * disaster especially in combination with the BestComm. For safety reasons 174 * we make the available RAM a little bit smaller to have an unused area at 175 * the end. 176 */ 177 bsp_uboot_board_info.bi_memsize -= 4 * 1024; 178 179 /* 172 180 * Program BAT0 for RAM 173 181 */ -
c/src/lib/libbsp/powerpc/gen5200/startup/linkcmds.brs5l
r1dd95cc r25ed11d0 6 6 7 7 MEMORY { 8 RAM : ORIGIN = 0x0, LENGTH = 128M 8 /* For the 4k adjustment see cpuinit.c */ 9 RAM : ORIGIN = 0x0, LENGTH = 128M - 4k 9 10 ROM : ORIGIN = 0xffe00000, LENGTH = 2M 10 11 DPRAM : ORIGIN = 0xff000000, LENGTH = 1k -
c/src/lib/libbsp/powerpc/gen5200/startup/linkcmds.dp2
r1dd95cc r25ed11d0 6 6 7 7 MEMORY { 8 RAM : ORIGIN = 0x0, LENGTH = 64M 8 /* For the 4k adjustment see cpuinit.c */ 9 RAM : ORIGIN = 0x0, LENGTH = 64M - 4k 9 10 ROM : ORIGIN = 0xffe00000, LENGTH = 2M 10 DPRAM : ORIGIN = 0xff000000, LENGTH = 1k11 11 REGS : ORIGIN = 0xf0000000, LENGTH = 64k 12 DPRAM : ORIGIN = 0x0, LENGTH = 0 12 13 NIRVANA : ORIGIN = 0x0, LENGTH = 0 13 14 } -
c/src/lib/libbsp/powerpc/gen5200/startup/linkcmds.icecube
r1dd95cc r25ed11d0 6 6 7 7 MEMORY { 8 RAM : ORIGIN = 0x0, LENGTH = 128M 8 /* For the 4k adjustment see cpuinit.c */ 9 RAM : ORIGIN = 0x0, LENGTH = 128M - 4k 9 10 ROM : ORIGIN = 0xffe00000, LENGTH = 2M 10 11 REGS : ORIGIN = 0xf0000000, LENGTH = 64k 12 DPRAM : ORIGIN = 0x0, LENGTH = 0 11 13 NIRVANA : ORIGIN = 0x0, LENGTH = 0 12 DPRAM : ORIGIN = 0x0, LENGTH = 013 14 } 14 15 -
c/src/lib/libbsp/powerpc/gen5200/startup/linkcmds.pm520_cr825
r1dd95cc r25ed11d0 6 6 7 7 MEMORY { 8 RAM : ORIGIN = 0x0, LENGTH = 64M 8 /* For the 4k adjustment see cpuinit.c */ 9 RAM : ORIGIN = 0x0, LENGTH = 64M - 4k 9 10 ROM : ORIGIN = 0xffe00000, LENGTH = 2M 11 REGS : ORIGIN = 0xf0000000, LENGTH = 64k 10 12 DPRAM : ORIGIN = 0xff000000, LENGTH = 1k 11 REGS : ORIGIN = 0xf0000000, LENGTH = 64k12 13 NIRVANA : ORIGIN = 0x0, LENGTH = 0 13 14 } -
c/src/lib/libbsp/powerpc/gen5200/startup/linkcmds.pm520_ze30
r1dd95cc r25ed11d0 6 6 7 7 MEMORY { 8 RAM : ORIGIN = 0x0, LENGTH = 64M 8 /* For the 4k adjustment see cpuinit.c */ 9 RAM : ORIGIN = 0x0, LENGTH = 64M - 4k 9 10 ROM : ORIGIN = 0xffe00000, LENGTH = 2M 11 REGS : ORIGIN = 0xf0000000, LENGTH = 64k 10 12 DPRAM : ORIGIN = 0xff000000, LENGTH = 1k 11 REGS : ORIGIN = 0xf0000000, LENGTH = 64k12 13 NIRVANA : ORIGIN = 0x0, LENGTH = 0 13 14 }
Note: See TracChangeset
for help on using the changeset viewer.