// Function to initialize the device. Called at bootstrap time. static bool quicc_sxx_serial_init(struct cyg_devtab_entry *tab) { serial_channel *chan = (serial_channel *)tab->priv; quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; volatile EPPC *eppc = (volatile EPPC *)eppc_base(); int TxBD, RxBD; int cache_state; HAL_DCACHE_IS_ENABLED(cache_state); HAL_DCACHE_SYNC(); HAL_DCACHE_DISABLE(); #ifdef CYGDBG_IO_INIT diag_printf("QUICC_SMC SERIAL init - dev: %x.%d = %s\n", smc_chan->channel, smc_chan->int_num, tab->name); #endif #ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC1 if (chan == &quicc_sxx_serial_channel_smc1) { TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxNUM); RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_RxNUM); quicc_smc_serial_init_info(&quicc_sxx_serial_info_smc1, &eppc->pram[2].scc.pothers.smc_modem.psmc.u, // PRAM &eppc->smc_regs[0], // Control registers TxBD, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxNUM, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxSIZE, &quicc_smc1_txbuf[0], RxBD, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_RxNUM, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_RxSIZE, &quicc_smc1_rxbuf[0], 0xC0, // PortB mask QUICC_CPM_SMC1 ); } #endif #ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC2 if (chan == &quicc_sxx_serial_channel_smc2) { TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxNUM); RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_RxNUM); quicc_smc_serial_init_info(&quicc_sxx_serial_info_smc2, &eppc->pram[3].scc.pothers.smc_modem.psmc.u, // PRAM &eppc->smc_regs[1], // Control registers TxBD, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxNUM, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxSIZE, &quicc_smc2_txbuf[0], RxBD, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_RxNUM, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_RxSIZE, &quicc_smc2_rxbuf[0], 0xC00, // PortB mask QUICC_CPM_SMC2 ); } #endif #ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC1 if (chan == &quicc_sxx_serial_channel_scc1) { TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxNUM); RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxNUM); quicc_scc_serial_init_info(&quicc_sxx_serial_info_scc1, &eppc->pram[0].scc.pscc.u, // PRAM &eppc->scc_regs[0], // Control registersn TxBD, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxNUM, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxSIZE, &quicc_scc1_txbuf[0], RxBD, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxNUM, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxSIZE, &quicc_scc1_rxbuf[0], 0x0003, // PortA mask 0x1000, // PortB mask 0x0800, // PortC mask QUICC_CPM_SCC1 ); } #endif #ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC2 if (chan == &quicc_sxx_serial_channel_scc2) { TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxNUM); RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxNUM); quicc_scc_serial_init_info(&quicc_sxx_serial_info_scc2, &eppc->pram[1].scc.pscc.u, // PRAM &eppc->scc_regs[1], // Control registersn TxBD, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxNUM, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxSIZE, &quicc_scc2_txbuf[0], RxBD, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxNUM, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxSIZE, &quicc_scc2_rxbuf[0], 0x000C, // PortA mask 0x2000, // PortB mask 0x0C00, // PortC mask QUICC_CPM_SCC2 ); } #endif #ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC3 if (chan == &quicc_sxx_serial_channel_scc3) { TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxNUM); RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxNUM); quicc_scc_serial_init_info(&quicc_sxx_serial_info_scc3, &eppc->pram[2].scc.pscc.u, // PRAM &eppc->scc_regs[2], // Control registersn TxBD, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxNUM, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxSIZE, &quicc_scc3_txbuf[0], RxBD, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxNUM, CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxSIZE, &quicc_scc3_rxbuf[0], #if defined(CYGHWR_HAL_POWERPC_MPC8XX_850) 0x0000, // PortA mask 0x00C0, // PortB mask 0x0000, // PortC mask #elif defined(CYGHWR_HAL_POWERPC_MPC8XX_852T) 0x0030, // PortA mask 0x0000, // PortB mask 0x0000, // PortC mask #elif defined(CYGHWR_HAL_POWERPC_MPC8XX_823) 0x0000, // PortA mask 0x00C0, // PortB mask 0x0000, // PortC mask #else #error "Cannot route SCC3" #endif QUICC_CPM_SCC3 ); } #endif (chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices if (chan->out_cbuf.len != 0) { cyg_drv_interrupt_create(smc_chan->int_num, CYGARC_SIU_PRIORITY_HIGH, // Priority - unused (but asserted) (cyg_addrword_t)chan, // Data item passed to interrupt handler quicc_sxx_serial_ISR, quicc_sxx_serial_DSR, &smc_chan->serial_interrupt_handle, &smc_chan->serial_interrupt); cyg_drv_interrupt_attach(smc_chan->serial_interrupt_handle); cyg_drv_interrupt_unmask(smc_chan->int_num); } if (smc_chan->type == _SMC_CHAN) { quicc_smc_serial_config_port(chan, &chan->config, true); } else { quicc_scc_serial_config_port(chan, &chan->config, true); } if (cache_state) HAL_DCACHE_ENABLE(); return true; }
/* * Initialize SMCX as a uart. * * Comments below reference Motorola's "MPC860 User Manual". * The basic initialization steps are from Section 16.15.8 * of that manual. */ static void cyg_hal_smcx_init_channel(struct port_info *info, int port) { EPPC *eppc = eppc_base(); int i; volatile struct smc_uart_pram *uart_pram = (volatile struct smc_uart_pram *)((char *)eppc + info->pram); volatile struct smc_regs *regs = (volatile struct smc_regs *)((char *)eppc + info->regs); struct cp_bufdesc *txbd, *rxbd; if (info->init) return; info->init = 1; switch (port) { #if CYGNUM_HAL_QUICC_SMC1 > 0 case QUICC_CPM_SMC1: /* * Set up the PortB pins for UART operation. * Set PAR and DIR to allow SMCTXD1 and SMRXD1 * (Table 16-39) */ eppc->pip_pbpar |= 0xc0; eppc->pip_pbdir &= ~0xc0; break; #endif #if CYGNUM_HAL_QUICC_SMC2 > 0 case QUICC_CPM_SMC2: /* * Set up the PortA pins for UART operation. * Set PAR and DIR to allow SMCTXD2 and SMRXD2 * (Table 16-39) */ eppc->pio_papar |= 0xc0; eppc->pio_padir &= ~0xc0; eppc->pio_paodr &= ~0xc0; break; #endif } // Set up baud rate generator. These are allocated from a // pool, based on the port number and type. The allocator // will arrange to have the selected baud rate clock steered // to this device. info->brg = _mpc8xx_allocate_brg(port); *(info->brg) = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1); /* * Set pointers to buffer descriptors. * (Sections 16.15.4.1, 16.15.7.12, and 16.15.7.13) */ uart_pram->rbase = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*info->Rxnum + info->Rxnum); uart_pram->tbase = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*info->Txnum + info->Txnum); /* * SDMA & LCD bus request level 5 * (Section 16.10.2.1) */ eppc->dma_sdcr = 1; /* * Set Rx and Tx function code * (Section 16.15.4.2) */ uart_pram->rfcr = 0x18; uart_pram->tfcr = 0x18; /* max receive buffer length */ uart_pram->mrblr = 1; /* disable max_idle feature */ uart_pram->max_idl = 0; /* no last brk char received */ uart_pram->brkln = 0; /* no break condition occurred */ uart_pram->brkec = 0; /* 1 break char sent on top XMIT */ uart_pram->brkcr = 1; /* setup RX buffer descriptors */ rxbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase); info->next_rxbd = rxbd; for (i = 0; i < info->Rxnum; i++) { rxbd->length = 0; rxbd->buffer = ((char *)eppc + (uart_pram->rbase+(info->Rxnum*sizeof(struct cp_bufdesc))))+i; rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int; rxbd++; } rxbd--; rxbd->ctrl |= QUICC_BD_CTL_Wrap; /* setup TX buffer descriptor */ txbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase); txbd->length = 1; txbd->buffer = ((char *)eppc + (uart_pram->tbase+(info->Txnum*sizeof(struct cp_bufdesc)))); txbd->ctrl = 0x2000; /* * Clear any previous events. Mask interrupts. * (Section 16.15.7.14 and 16.15.7.15) */ regs->smc_smce = 0xff; regs->smc_smcm = 1; // RX interrupts only, for ctrl-c /* * Set 8,n,1 characters, then also enable rx and tx. * (Section 16.15.7.11) */ regs->smc_smcmr = 0x4820; regs->smc_smcmr = 0x4823; /* * Init Rx & Tx params for SMCx */ eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | port | QUICC_CPM_CR_BUSY; info->irq = 0; // Interrupts not enabled }
/* * Initialize an SCC as a uart. * * Comments below reference Motorola's "MPC860 User Manual". * The basic initialization steps are from Section 16.15.8 * of that manual. */ static void cyg_hal_sccx_init_channel(struct port_info *info, int port) { EPPC *eppc = eppc_base(); int i; volatile struct uart_pram *uart_pram = (volatile struct uart_pram *)((char *)eppc + info->pram); volatile struct scc_regs *regs = (volatile struct scc_regs *)((char *)eppc + info->regs); struct cp_bufdesc *txbd, *rxbd; if (info->init) return; info->init = 1; /* * Set up the Port pins for UART operation. */ switch (port) { #if CYGNUM_HAL_QUICC_SCC1 > 0 case QUICC_CPM_SCC1: eppc->pio_papar |= 0x03; eppc->pio_padir &= ~0x03; eppc->pio_paodr &= ~0x03; /* CTS on PortC.11 */ eppc->pio_pcdir &= 0x800; eppc->pio_pcpar &= 0x800; eppc->pio_pcso |= 0x800; /* RTS on PortB.19 */ eppc->pip_pbpar |= 0x1000; eppc->pip_pbdir |= 0x1000; break; #endif #if CYGNUM_HAL_QUICC_SCC2 > 0 case QUICC_CPM_SCC2: #error FIXME eppc->pio_papar |= 0x0C; eppc->pio_padir &= ~0x0C; eppc->pio_paodr &= ~0x0C; /* CTS on PortC.11 */ eppc->pio_pcdir &= 0xC00; eppc->pio_pcpar &= 0xC00; eppc->pio_pcso |= 0xC00; /* RTS on PortB.19 */ eppc->pip_pbpar |= 0x2000; eppc->pip_pbdir |= 0x2000; break; #endif #if CYGNUM_HAL_QUICC_SCC3 > 0 case QUICC_CPM_SCC3: #if defined(CYGHWR_HAL_POWERPC_MPC8XX_850) #if 0 // CAUTION! Enabling these bits made the port get stuck :-( /* CTS/RTS/CD on PortC.4/5/13 */ eppc->pio_pcdir &= 0x0C04; eppc->pio_pcpar &= 0x0C00; // eppc->pio_pcpar |= 0x0004; eppc->pio_pcso |= 0x0C00; #endif /* RxD/TxD on PortB.24/25 */ eppc->pip_pbpar |= 0x00C0; eppc->pip_pbdir |= 0x00C0; eppc->pip_pbodr &= ~0x00C0; #elif defined(CYGHWR_HAL_POWERPC_MPC8XX_852T) eppc->pio_papar |= 0x30; eppc->pio_padir &= ~0x30; eppc->pio_paodr &= ~0x30; #else #error "Cannot route SCC3 I/O" #endif // 850T break; #endif // SCC3 } // Set up baud rate generator. These are allocated from a // pool, based on the port number and type. The allocator // will arrange to have the selected baud rate clock steered // to this device. info->brg = _mpc8xx_allocate_brg(port); *(info->brg) = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1); /* * Set pointers to buffer descriptors. */ uart_pram->rbase = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*info->Rxnum + info->Rxnum); uart_pram->tbase = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*info->Txnum + info->Txnum); /* * SDMA & LCD bus request level 5 */ eppc->dma_sdcr = 1; /* * Set Rx and Tx function code */ uart_pram->rfcr = 0x18; uart_pram->tfcr = 0x18; /* max receive buffer length */ uart_pram->mrblr = 1; /* disable max_idle feature */ uart_pram->max_idl = 0; /* no last brk char received */ uart_pram->brkln = 0; /* no break condition occurred */ uart_pram->brkec = 0; /* 1 break char sent on top XMIT */ uart_pram->brkcr = 1; /* character mask */ uart_pram->rccm = 0xC0FF; /* control characters */ for (i = 0; i < 8; i++) { uart_pram->cc[i] = 0x8000; // Mark unused } /* setup RX buffer descriptors */ rxbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase); info->next_rxbd = rxbd; for (i = 0; i < info->Rxnum; i++) { rxbd->length = 0; rxbd->buffer = ((char *)eppc + (uart_pram->rbase+(info->Rxnum*sizeof(struct cp_bufdesc))))+i; rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int; rxbd++; } rxbd--; rxbd->ctrl |= QUICC_BD_CTL_Wrap; /* setup TX buffer descriptor */ txbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase); txbd->length = 0; txbd->buffer = ((char *)eppc + (uart_pram->tbase+(info->Txnum*sizeof(struct cp_bufdesc)))); txbd->ctrl = 0x2000; /* * Clear any previous events. Mask interrupts. * (Section 16.15.7.14 and 16.15.7.15) */ regs->scc_scce = 0xffff; regs->scc_sccm = 1; // RX interrupts only, for ctrl-c /* * Set 8,n,1 characters */ regs->scc_psmr = (3<<12); regs->scc_gsmr_h = 0x20; // 8bit FIFO regs->scc_gsmr_l = 0x00028004; // 16x TxCLK, 16x RxCLK, UART /* * Init Rx & Tx params for SCCX */ eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | port | QUICC_CPM_CR_BUSY; regs->scc_gsmr_l |= 0x30; // Enable Rx, Tx info->irq = 0; }
// // Initialize the interface - performed at system startup // This function must set up the interface, including arranging to // handle interrupts, etc, so that it may be "started" cheaply later. // static bool quicc_eth_init(struct cyg_netdevtab_entry *tab) { struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; struct quicc_eth_info *qi = (struct quicc_eth_info *)sc->driver_private; volatile EPPC *eppc = (volatile EPPC *)eppc_base(); struct cp_bufdesc *rxbd, *txbd; unsigned char *RxBUF, *TxBUF, *ep, *ap; volatile struct ethernet_pram *enet_pram; volatile struct scc_regs *scc; int TxBD, RxBD; int cache_state; int i; bool esa_ok = false; #ifdef QUICC_ETH_FETCH_ESA QUICC_ETH_FETCH_ESA(esa_ok); #endif if (!esa_ok) { #if defined(CYGPKG_REDBOOT) && \ defined(CYGSEM_REDBOOT_FLASH_CONFIG) esa_ok = flash_get_config("quicc_esa", enaddr, CONFIG_ESA); #else esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, "quicc_esa", enaddr, CONFIG_ESA); #endif if (!esa_ok) { // Can't figure out ESA diag_printf("QUICC_ETH - Warning! ESA unknown\n"); memcpy(&enaddr, &_default_enaddr, sizeof(enaddr)); } } // Ensure consistent state between cache and what the QUICC sees HAL_DCACHE_IS_ENABLED(cache_state); HAL_DCACHE_SYNC(); HAL_DCACHE_DISABLE(); #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED // Set up to handle interrupts cyg_drv_interrupt_create(QUICC_ETH_INT, CYGARC_SIU_PRIORITY_HIGH, (cyg_addrword_t)sc, // Data item passed to interrupt handler (cyg_ISR_t *)quicc_eth_isr, (cyg_DSR_t *)eth_drv_dsr, &quicc_eth_interrupt_handle, &quicc_eth_interrupt); cyg_drv_interrupt_attach(quicc_eth_interrupt_handle); cyg_drv_interrupt_acknowledge(QUICC_ETH_INT); cyg_drv_interrupt_unmask(QUICC_ETH_INT); #endif qi->pram = enet_pram = &eppc->pram[QUICC_ETH_SCC].enet_scc; qi->ctl = scc = &eppc->scc_regs[QUICC_ETH_SCC]; // Use SCCx // Shut down ethernet, in case it is already running scc->scc_gsmr_l &= ~(QUICC_SCC_GSML_ENR | QUICC_SCC_GSML_ENT); memset((void *)enet_pram, 0, sizeof(*enet_pram)); TxBD = _mpc8xx_allocBd(CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM * sizeof(struct cp_bufdesc)); RxBD = _mpc8xx_allocBd(CYGNUM_DEVS_ETH_POWERPC_QUICC_RxNUM * sizeof(struct cp_bufdesc)); txbd = (struct cp_bufdesc *)((char *)eppc + TxBD); rxbd = (struct cp_bufdesc *)((char *)eppc + RxBD); qi->tbase = txbd; qi->txbd = txbd; qi->tnext = txbd; qi->rbase = rxbd; qi->rxbd = rxbd; qi->rnext = rxbd; qi->txactive = 0; RxBUF = &quicc_eth_rxbufs[0][0]; TxBUF = &quicc_eth_txbufs[0][0]; // setup buffer descriptors for (i = 0; i < CYGNUM_DEVS_ETH_POWERPC_QUICC_RxNUM; i++) { rxbd->length = 0; rxbd->buffer = RxBUF; rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int; RxBUF += CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE; rxbd++; } rxbd--; rxbd->ctrl |= QUICC_BD_CTL_Wrap; // Last buffer for (i = 0; i < CYGNUM_DEVS_ETH_POWERPC_QUICC_TxNUM; i++) { txbd->length = 0; txbd->buffer = TxBUF; txbd->ctrl = 0; TxBUF += CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE; txbd++; } txbd--; txbd->ctrl |= QUICC_BD_CTL_Wrap; // Last buffer // Set up parallel ports for connection to ethernet tranceiver eppc->pio_papar |= (QUICC_ETH_PA_RXD | QUICC_ETH_PA_TXD); eppc->pio_padir &= ~(QUICC_ETH_PA_RXD | QUICC_ETH_PA_TXD); eppc->pio_paodr &= ~QUICC_ETH_PA_TXD; eppc->pio_pcpar &= ~(QUICC_ETH_PC_COLLISION | QUICC_ETH_PC_Rx_ENABLE); eppc->pio_pcdir &= ~(QUICC_ETH_PC_COLLISION | QUICC_ETH_PC_Rx_ENABLE); eppc->pio_pcso |= (QUICC_ETH_PC_COLLISION | QUICC_ETH_PC_Rx_ENABLE); eppc->pio_papar |= (QUICC_ETH_PA_Tx_CLOCK | QUICC_ETH_PA_Rx_CLOCK); eppc->pio_padir &= ~(QUICC_ETH_PA_Tx_CLOCK | QUICC_ETH_PA_Rx_CLOCK); // Set up clock routing eppc->si_sicr &= ~QUICC_ETH_SICR_MASK; eppc->si_sicr |= QUICC_ETH_SICR_ENET; eppc->si_sicr &= ~QUICC_ETH_SICR_ENABLE; // Set up DMA mode eppc->dma_sdcr = 0x0001; // Initialize shared PRAM enet_pram->rbase = RxBD; enet_pram->tbase = TxBD; // Set Big Endian mode enet_pram->rfcr = QUICC_SCC_FCR_BE; enet_pram->tfcr = QUICC_SCC_FCR_BE; // Size of receive buffers enet_pram->mrblr = CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE; // Initialize CRC calculations enet_pram->c_pres = 0xFFFFFFFF; enet_pram->c_mask = 0xDEBB20E3; // Actual CRC formula enet_pram->crcec = 0; enet_pram->alec = 0; enet_pram->disfc = 0; // Frame padding enet_pram->pads = 0x8888; enet_pram->pads = 0x0000; // Retries enet_pram->ret_lim = 15; enet_pram->ret_cnt = 0; // Frame sizes enet_pram->mflr = IEEE_8023_MAX_FRAME; enet_pram->minflr = IEEE_8023_MIN_FRAME; enet_pram->maxd1 = CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE; enet_pram->maxd2 = CYGNUM_DEVS_ETH_POWERPC_QUICC_BUFSIZE; // Group address hash enet_pram->gaddr1 = 0; enet_pram->gaddr2 = 0; enet_pram->gaddr3 = 0; enet_pram->gaddr4 = 0; // Device physical address ep = &enaddr[sizeof(enaddr)]; ap = (unsigned char *)&enet_pram->paddr_h; for (i = 0; i < sizeof(enaddr); i++) { *ap++ = *--ep; } // Persistence counter enet_pram->p_per = 0; // Individual address filter enet_pram->iaddr1 = 0; enet_pram->iaddr2 = 0; enet_pram->iaddr3 = 0; enet_pram->iaddr4 = 0; // Temp address enet_pram->taddr_h = 0; enet_pram->taddr_m = 0; enet_pram->taddr_l = 0; // Initialize the CPM (set up buffer pointers, etc). eppc->cp_cr = QUICC_CPM_SCCx | QUICC_CPM_CR_INIT_TXRX | QUICC_CPM_CR_BUSY; while (eppc->cp_cr & QUICC_CPM_CR_BUSY) ; // Clear any pending interrupt/exceptions scc->scc_scce = 0xFFFF; // Enable interrupts scc->scc_sccm = QUICC_SCCE_INTS | QUICC_SCCE_GRC | QUICC_SCCE_BSY; // Set up SCCx to run in ethernet mode scc->scc_gsmr_h = 0; scc->scc_gsmr_l = QUICC_SCC_GSML_TCI | QUICC_SCC_GSML_TPL_48 | QUICC_SCC_GSML_TPP_01 | QUICC_SCC_GSML_MODE_ENET; // Sync delimiters scc->scc_dsr = 0xD555; // Protocol specifics (as if GSML wasn't enough) scc->scc_psmr = QUICC_PMSR_ENET_CRC | QUICC_PMSR_SEARCH_AFTER_22 | QUICC_PMSR_RCV_SHORT_FRAMES; #ifdef QUICC_ETH_ENABLE QUICC_ETH_ENABLE(); #endif #ifdef QUICC_ETH_RESET_PHY QUICC_ETH_RESET_PHY(); #endif // Enable ethernet interface #ifdef QUICC_ETH_PC_Tx_ENABLE eppc->pio_pcpar |= QUICC_ETH_PC_Tx_ENABLE; eppc->pio_pcdir &= ~QUICC_ETH_PC_Tx_ENABLE; #else eppc->pip_pbpar |= QUICC_ETH_PB_Tx_ENABLE; eppc->pip_pbdir |= QUICC_ETH_PB_Tx_ENABLE; #endif if (cache_state) HAL_DCACHE_ENABLE(); // Initialize upper level driver (sc->funs->eth_drv->init)(sc, (unsigned char *)&enaddr); // Set LED state clear_led(LED_TxACTIVE); clear_led(LED_RxACTIVE); return true; }