📄 at91rm9200_ether.c
字号:
{ diag_printf("EMAC_ROVR!\n"); }// return CYG_ISR_HANDLED; return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR);}static cyg_handle_t at91rm9200_IntHandle;static cyg_interrupt at91rm9200_IntObject;static int ethernetRunning;#if HavePHYinterruptstatic cyg_handle_t macPhyIntrHandle;static cyg_interrupt macPhyIntrObject;#endifstatic void at91rm9200_eth_deliver(struct eth_drv_sc *sc){ extern struct eth_drv_sc at91rm9200_sc; cyg_uint32 len; cyg_uint32 val; cyg_uint32 i;// diag_printf("at91rm9200_eth_deliver().......\n"); if (!(rbf_ptr->addr & RBF_OWNER)) { return; } len = rbf_ptr->len & RBF_LEN; /* Not include Ethernet header and FCS */// len -= (ETH_HEADER_SIZE + 2);/* diag_printf("deliver().. len=%d\n", len);*/ /* Call back: ((sc)->funs->eth_drv->recv)(sc, len) */ eth_drv_recv(&at91rm9200_sc, len);#if 0 /* xxx_recv() clear it */ rbf_ptr->addr &= ~RBF_OWNER; if (rbf_ptr->addr & RBF_WRAP) { rbf_ptr = &rbf_des[0]; } else { rbf_ptr++; } HAL_READ_UINT32((BASE_EMAC+EMAC_RSR), val); val |= C_EMAC_REC; HAL_WRITE_UINT32((BASE_EMAC+EMAC_RSR), val);#endif /* 0/1 */}static void installInterrupts(void){#if 0 extern struct eth_drv_sc at91rm9200_sc; static bool firstTime=true; debug1_printf("at91rm9200_ether: installInterrupts()\n"); if (!firstTime) return; firstTime = false; cyg_drv_mutex_init(&txMutex); cyg_drv_mutex_init(&oldRxMutex); cyg_drv_cond_init(&oldRxCond, &oldRxMutex); cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_EMAC, 0, (unsigned)&at91rm9200_sc, at91rm9200_eth_isr, eth_drv_dsr, &at91rm9200_IntHandle, &at91rm9200_IntObject);#if HavePHYinterrupt // FIXME#endif cyg_drv_interrupt_attach(at91rm9200_IntHandle);// cyg_drv_interrupt_attach(bdmaRxIntrHandle);// cyg_drv_interrupt_attach(bdmaTxIntrHandle);// cyg_drv_interrupt_attach(macRxIntrHandle);// cyg_drv_interrupt_attach(macTxIntrHandle);#if HavePHYinterrupt// cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_EXT0);// cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EXT0);#endif#endif /* 0/1 */}//======================================================================// Driver code that interfaces to the TCP/IP stack via the common// Ethernet interface.static bool at91rm9200_eth_init(struct cyg_netdevtab_entry *tab){ struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance; cyg_uint32 i; cyg_uint32 val; unsigned char myMacAddr[6] = { CYGPKG_DEVS_ETH_ARM_AT91RM9200_MACADDR }; bool ok; unsigned int phyid1, phyid2; unsigned int phy_id; hal_interrupt_mask(CYGNUM_HAL_INTERRUPT_EMAC);#ifdef CYGHWR_DEVS_ETH_ARM_AT91RM9200_GET_ESA // Get MAC address from RedBoot configuration variables// CYGHWR_DEVS_ETH_ARM_AT91RM9200_GET_ESA(&myMacAddr[0], ok); // If this call fails myMacAddr is unchanged and MAC address from CDL is used#endif// debug1_printf("at91rm9200_eth_init()\n"); debug1_printf(" MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",myMacAddr[0],myMacAddr[1],myMacAddr[2],myMacAddr[3],myMacAddr[4],myMacAddr[5]); /* FIXME: For RMII now */ /* ** Enable pins to be drived by peripheral, ** PA7 ~ PA16 */ HAL_WRITE_UINT32((BASE_PIOA+PIO_ASR), (C_PIO_PA07 | C_PIO_PA08 | C_PIO_PA09 | C_PIO_PA10 | C_PIO_PA11 | C_PIO_PA12 | C_PIO_PA13 | C_PIO_PA14 | C_PIO_PA15 | C_PIO_PA16)); HAL_WRITE_UINT32((BASE_PIOA+PIO_BSR), 0); /* Disables the PIO from controlling the corresponding pin (enables peripheral control of the pin). */ HAL_WRITE_UINT32((BASE_PIOA+PIO_PDR), (C_PIO_PA07 | C_PIO_PA08 | C_PIO_PA09 | C_PIO_PA10 | C_PIO_PA11 | C_PIO_PA12 | C_PIO_PA13 | C_PIO_PA14 | C_PIO_PA15 | C_PIO_PA16)); /* Peripheral Clock Enable Register */ HAL_WRITE_UINT32((BASE_PMC+PMC_PCER), PID24); /* Enable Peripheral clock in PMC for PIOA */ HAL_WRITE_UINT32((BASE_PMC+PMC_PCER), PID02); HAL_READ_UINT32((BASE_EMAC+EMAC_CTL), val); /* Clear statistics */ val |= C_EMAC_CSR; /* Enable Tx/Rx */ val |= C_EMAC_RE | C_EMAC_TE; HAL_WRITE_UINT32((BASE_EMAC+EMAC_CTL), val); /* FIXME: config it after PHY initialization and check */#if 1 /* Set CFG as 100 Mbit/sec, Full Duplex, HCLK divided by 32, RMII*/ val = (C_EMAC_SPD | C_EMAC_FD | C_EMAC_CLK_HCLK_32 | C_EMAC_RMII); val &= ~C_EMAC_CLK; HAL_WRITE_UINT32((BASE_EMAC+EMAC_CFG), val);#else /* Set CFG as 10 Mbit/sec, Half Duplex, HCLK divided by 32, RMII*//* val = (C_EMAC_CAF | C_EMAC_CLK_HCLK_32 | C_EMAC_RMII);*/ val = (C_EMAC_CLK_HCLK_32 | C_EMAC_RMII); val &= ~C_EMAC_CLK; HAL_WRITE_UINT32((BASE_EMAC+EMAC_CFG), val);#endif /* 0/1 */#if 0 /* Enable MAC interrupts */ HAL_WRITE_UINT32((BASE_EMAC+EMAC_IER), 0x0FFF);#else /* Disable MAC interrupts */ HAL_WRITE_UINT32((BASE_EMAC+EMAC_IDR), 0x0FFF);#endif /* 0/1 */ /* Initialize Ehternet Rx buffers */ rbf_des = (rbf_t *)RXBUFF_DES; for ( i = 0; i < RXBUF_NUM; i++) { rbf_des[i].addr = BASE_RXBUFF + RXBUFF_SIZE * i; rbf_des[i].len = 0; } rbf_des[RXBUF_NUM-1].addr |= RBF_WRAP; rbf_ptr = (rbf_t *)RXBUFF_DES; /* Set Receive Buffer Queue Pointer */ HAL_WRITE_UINT32((BASE_EMAC+EMAC_RBQP), RXBUFF_DES); /* Reset Receive Status Register */ HAL_WRITE_UINT32((BASE_EMAC+EMAC_RSR), (C_EMAC_BNA | C_EMAC_REC | C_EMAC_OVR)); enable_mdi(); phyid1 = read_phy(0, MII_PHYSID1); phyid2 = read_phy(0, MII_PHYSID2); disable_mdi(); phy_id = (phyid1 << 16) | (phyid2 & 0xFFF0); switch (phy_id) { /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */ case MII_DM9161_ID: debug1_printf("PHY: DM9161\n"); at91rm9200_priv_data.phy_type = MII_DM9161_ID; break; /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */ case MII_LXT971A_ID: debug1_printf("PHY: LXT971A\n"); at91rm9200_priv_data.phy_type = MII_LXT971A_ID; break; /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */ case MII_RTL8201_ID: debug1_printf("PHY: RTL8201\n"); at91rm9200_priv_data.phy_type = MII_RTL8201_ID; break; /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */ case MII_BCM5221_ID: debug1_printf("PHY: BCM5221\n"); at91rm9200_priv_data.phy_type = MII_BCM5221_ID; break; /* National Semiconductor DP83847: */ case MII_DP83847_ID: debug1_printf("PHY: DP83847\n"); at91rm9200_priv_data.phy_type = MII_DP83847_ID; break; default: debug1_printf("PHY: Unknown (%d)\n", phy_id); at91rm9200_priv_data.phy_type = 0; break; } init_phy();#if defined(CYGPKG_NET) ifStats.duplex = 1; //unknown ifStats.operational = 1; //unknown ifStats.tx_queue_len = MAX_TX_FRAME_DESCRIPTORS; strncpy(ifStats.description,"Ethernet device", sizeof(ifStats.description)); ifStats.snmp_chipset[0] = 0; ifStats.supports_dot3 = 1; // support dot3#endif installInterrupts(); EthInit(myMacAddr);// cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EMAC); configDone = 1; ethernetRunning = 1; eth_drv_init(sc, myMacAddr); return true;}static void at91rm9200_eth_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags){ debug2_printf("at91rm9200_eth_start()\n"); if (!ethernetRunning) { cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_EMAC); /* FIXME: PHY IRQ */ EthInit(enaddr); cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EMAC); /* FIXME: PHY IRQ */ ethernetRunning = 1; }}static void at91rm9200_eth_stop(struct eth_drv_sc *sc){ debug1_printf("at91rm9200_eth_stop()\n"); // cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_EMAC); ethernetRunning = 0;}static int at91rm9200_eth_control(struct eth_drv_sc *sc, unsigned long key, void *data, int len){#if 0 switch (key) {#if defined(CYGPKG_NET) case ETH_DRV_GET_IF_STATS_UD: case ETH_DRV_GET_IF_STATS: { struct ether_drv_stats *p = (struct ether_drv_stats*)data;#if CYGINT_DEVS_ETH_ARM_AT91RM9200_PHY unsigned linkStatus; // Read link status to be up to date linkStatus = PhyStatus(); if (linkStatus & PhyStatus_FullDuplex) ifStats.duplex = 3; else ifStats.duplex = 2; if (linkStatus & PhyStatus_LinkUp) ifStats.operational = 3; else ifStats.operational = 2; if (linkStatus & PhyStatus_100Mb) ifStats.speed = 100000000; else ifStats.speed = 10000000;#endif *p = ifStats; return 0; }#endif case ETH_DRV_SET_MAC_ADDRESS: { int act; if (ETHER_ADDR_LEN != len) return -1; debug1_printf("at91rm9200_eth_control: ETH_DRV_SET_MAC_ADDRESS.\n"); act = ethernetRunning; at91rm9200_eth_stop(sc); at91rm9200_eth_start(sc, data, 0); ethernetRunning = act; return 0; }#ifdef ETH_DRV_GET_MAC_ADDRESS case ETH_DRV_GET_MAC_ADDRESS: { if (len < ETHER_ADDR_LEN) return -1; debug1_printf("at91rm9200_eth_control: ETH_DRV_GET_MAC_ADDRESS.\n");// memcpy(data, (void *)CAM_BaseAddr, ETHER_ADDR_LEN); return 0; }#endif default: return -1; }#endif /* 0/1 */ return 0;}// In case there are multiple Tx frames waiting, we should// return how many empty Tx spots we have. For now we just// return 0 or 1.static int at91rm9200_eth_can_send(struct eth_drv_sc *sc){ cyg_uint32 val; HAL_READ_UINT32((BASE_EMAC+EMAC_TSR), val); if (val & C_EMAC_BNQ) { return 1; } else { return 0; }}static int at91rm9200_eth_send_count=0;static voidat91rm9200_eth_send( struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total_len, unsigned long key){ cyg_uint32 val; static cyg_uint8 buf_mem[2048]; cyg_uint32 len; cyg_uint8 *dest; if (total_len >= MAX_ETH_FRAME_SIZE) { eth_drv_tx_done(sc, key, -EINVAL); return; } ++at91rm9200_eth_send_count; while (1) { HAL_READ_UINT32((BASE_EMAC+EMAC_TSR), val); if (val & C_EMAC_BNQ) { break; } } /* FIXME: * Do NOT use block mechanism * Queue. */ // copy data from scatter/gather list into BDMA data buffer len = 0; dest = buf_mem; while (sg_len) { memcpy(dest, (unsigned char*)sg_list->buf, sg_list->len); len += sg_list->len; dest += sg_list->len; ++sg_list; --sg_len; } /* Must always be written in address-then-length order. */ HAL_WRITE_UINT32((BASE_EMAC+EMAC_TAR), buf_mem); HAL_WRITE_UINT32((BASE_EMAC+EMAC_TCR), total_len); /* Block/Waiting for sent */ while (1) { HAL_READ_UINT32((BASE_EMAC+EMAC_TCR), val); if (!(val & 0x7FF)) { break; } } /* Cleared by writing a one to this bit. (Transmit complete.) */ HAL_READ_UINT32((BASE_EMAC+EMAC_TSR), val); val |= C_EMAC_COMP; HAL_WRITE_UINT32((BASE_EMAC+EMAC_TSR), val); // tell upper layer that we're done with this sglist eth_drv_tx_done(sc, key, 0);}static voidat91rm9200_eth_recv( struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len){ extern struct eth_drv_sc at91rm9200_sc; cyg_uint32 len; cyg_uint32 val; //diag_printf("at91rm9200_eth_recv().......\n");/* diag_printf("recv(), sg_len = %d, sg_list->len=%d\n", sg_len, sg_list->len);*/ val = rbf_ptr->addr; val &= ~((cyg_uint32)0x03);// val += ETH_HEADER_SIZE; if (!(sg_list->buf)) diag_printf("recv(), sg_list->buf is NULL\n"); while (sg_len) { if (sg_list->buf) { memcpy((unsigned char*)sg_list->buf, val, sg_list->len); } ++sg_list; --sg_len; }#if 1 rbf_ptr->addr &= ~RBF_OWNER; if (rbf_ptr->addr & RBF_WRAP) { rbf_ptr = &rbf_des[0]; } else { rbf_ptr++; } HAL_READ_UINT32((BASE_EMAC+EMAC_RSR), val); val |= C_EMAC_REC; HAL_WRITE_UINT32((BASE_EMAC+EMAC_RSR), val);#endif /* 0/1 */}// routine called to handle ethernet controller in polled modestatic void at91rm9200_eth_poll(struct eth_drv_sc *sc){// diag_printf("at91rm9200_eth_poll().......\n"); // Call ISR routine at91rm9200_eth_isr(CYGNUM_HAL_INTERRUPT_EMAC, 0); at91rm9200_eth_deliver(sc); // handle rx frames at91rm9200_handle_tx_complete();/* my_interrupt_ISR(sc); HRDWR_deliver(struct eth_drv_sc *sc);*/}static int at91rm9200_eth_int_vector(struct eth_drv_sc *sc){ return CYGNUM_HAL_INTERRUPT_EMAC;}ETH_DRV_SC(at91rm9200_sc, &at91rm9200_priv_data, // Driver specific data "eth0", // Name for this interface at91rm9200_eth_start, at91rm9200_eth_stop, at91rm9200_eth_control, at91rm9200_eth_can_send, at91rm9200_eth_send, at91rm9200_eth_recv, at91rm9200_eth_deliver, at91rm9200_eth_poll, at91rm9200_eth_int_vector );NETDEVTAB_ENTRY(at91rm9200_netdev, "at91rm9200", at91rm9200_eth_init, &at91rm9200_sc);// EOF at91rm9200_ether.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -