--- /dev/null
+#include "NyLPC_config.h"\r
+#if NyLPC_MCU==NyLPC_MCU_LPC4088\r
+#include "NyLPC_os.h"\r
+#include "copy_of_ethernet_api.h"\r
+#include "NyLPC_IEthernetDevice.h"\r
+#include "NyLPC_cEthernetMM.h"\r
+\r
+\r
+\r
+#define emacSHORT_DELAY_MS 10\r
+#ifndef configEMAC_INTERRUPT_PRIORITY\r
+ #define configEMAC_INTERRUPT_PRIORITY 5\r
+#endif\r
+////////////////////////////////////////////////////////////////////////////////\r
+// Ethernet Memory\r
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+#define AHB_SRAM_BANK1_BASE 0x20004000UL\r
+#define RX_DESC_BASE (AHB_SRAM_BANK1_BASE )\r
+#define RX_STAT_BASE (RX_DESC_BASE + NUM_RX_FRAG*(2*4)) /* 2 * uint32_t, see RX_DESC_TypeDef */\r
+#define TX_DESC_BASE (RX_STAT_BASE + NUM_RX_FRAG*(2*4)) /* 2 * uint32_t, see RX_STAT_TypeDef */\r
+#define TX_STAT_BASE (TX_DESC_BASE + NUM_TX_FRAG*(2*4)) /* 2 * uint32_t, see TX_DESC_TypeDef */\r
+#define ETH_BUF_BASE (TX_STAT_BASE + NUM_TX_FRAG*(1*4)) /* 1 * uint32_t, see TX_STAT_TypeDef */\r
+\r
+/**\r
+ * 消費メモリ量は、\r
+ * descriptor = NUM_RX_FRAG*16+NUM_TX_FRAG*12.\r
+ * EthnetBuf=ETH_FRAG_SIZE*NUM_RX_FRAG\r
+ */\r
+\r
+/* RX and TX descriptor and status definitions. */\r
+#define RX_DESC_PACKET(i) (*(unsigned int *)(RX_DESC_BASE + 8*i))\r
+#define RX_DESC_CTRL(i) (*(unsigned int *)(RX_DESC_BASE+4 + 8*i))\r
+#define RX_STAT_INFO(i) (*(unsigned int *)(RX_STAT_BASE + 8*i))\r
+#define RX_STAT_HASHCRC(i) (*(unsigned int *)(RX_STAT_BASE+4 + 8*i))\r
+#define TX_DESC_PACKET(i) (*(unsigned int *)(TX_DESC_BASE + 8*i))\r
+#define TX_DESC_CTRL(i) (*(unsigned int *)(TX_DESC_BASE+4 + 8*i))\r
+#define TX_STAT_INFO(i) (*(unsigned int *)(TX_STAT_BASE + 4*i))\r
+#define ETH_BUF(i) ( ETH_BUF_BASE + ETH_FRAG_SIZE*i )\r
+#define ETH_TX_BUF_BASE ((void*)(ETH_BUF_BASE+ETH_FRAG_SIZE*NUM_RX_FRAG))\r
+\r
+\r
+#define emacWAIT_FOR_LINK_TO_ESTABLISH_MS 500\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+// Ethernet interdface functions\r
+////////////////////////////////////////////////////////////////////////////////\r
+static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param);\r
+static void stop(void);\r
+static void* getRxEthFrame(unsigned short* o_len_of_data);\r
+static void nextRxEthFrame(void);\r
+static struct NyLPC_TTxBufferHeader* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size);\r
+static void releaseTxBuf(struct NyLPC_TTxBufferHeader* i_buf);\r
+static void sendTxEthFrame(struct NyLPC_TTxBufferHeader* i_buf,unsigned short i_size);\r
+static void processTx(void);\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+// Private\r
+////////////////////////////////////////////////////////////////////////////////\r
+static void emacIsrHandler(unsigned long i_status);\r
+static unsigned int clockselect(void);\r
+static int ethernet_link(void);\r
+static int phy_write(unsigned int PhyReg, unsigned short Data);\r
+static int phy_read(unsigned int PhyReg);\r
+static void prevTxDescriptor(void);\r
+static void prevRxDescriptor(void);\r
+static NyLPC_TUInt32 waitForTxEthFrameEmpty(void);\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
+const static struct TiEthernetDevice _interface_LAN8720=\r
+{\r
+ "LAN8720",\r
+ start,\r
+ stop,\r
+ getRxEthFrame,\r
+ nextRxEthFrame,\r
+ allocTxBuf,\r
+ releaseTxBuf,\r
+ sendTxEthFrame,\r
+ processTx\r
+};\r
+const static struct TiEthernetDevice _interface_DP83848C=\r
+{\r
+ "DP83848C",\r
+ start,\r
+ stop,\r
+ getRxEthFrame,\r
+ nextRxEthFrame,\r
+ allocTxBuf,\r
+ releaseTxBuf,\r
+ sendTxEthFrame,\r
+ processTx\r
+};\r
+\r
+static void* _event_param;\r
+static NyLPC_TiEthernetDevice_onEvent _event_handler;\r
+static unsigned int phy_id;\r
+\r
+/*\r
+ * EthernetDeviceのファクトリー関数。インターフェイスを生成できればtrue\r
+ *\r
+ */\r
+NyLPC_TBool EthDev_LPC4088_getInterface(\r
+ const struct TiEthernetDevice** o_dev)\r
+{\r
+ int regv, tout;\r
+ unsigned int clock = clockselect();\r
+\r
+ LPC_SC->PCONP |= 0x40000000; /* Power Up the EMAC controller. */\r
+ LPC_IOCON->P1_0 &= ~0x07; /* ENET I/O config */\r
+ LPC_IOCON->P1_0 |= 0x01; /* ENET_TXD0 */\r
+ LPC_IOCON->P1_1 &= ~0x07;\r
+ LPC_IOCON->P1_1 |= 0x01; /* ENET_TXD1 */\r
+ LPC_IOCON->P1_4 &= ~0x07;\r
+ LPC_IOCON->P1_4 |= 0x01; /* ENET_TXEN */\r
+ LPC_IOCON->P1_8 &= ~0x07;\r
+ LPC_IOCON->P1_8 |= 0x01; /* ENET_CRS */\r
+ LPC_IOCON->P1_9 &= ~0x07;\r
+ LPC_IOCON->P1_9 |= 0x01; /* ENET_RXD0 */\r
+ LPC_IOCON->P1_10 &= ~0x07;\r
+ LPC_IOCON->P1_10 |= 0x01; /* ENET_RXD1 */\r
+ LPC_IOCON->P1_14 &= ~0x07;\r
+ LPC_IOCON->P1_14 |= 0x01; /* ENET_RX_ER */\r
+ LPC_IOCON->P1_15 &= ~0x07;\r
+ LPC_IOCON->P1_15 |= 0x01; /* ENET_REF_CLK */\r
+ LPC_IOCON->P1_16 &= ~0x07; /* ENET/PHY I/O config */\r
+ LPC_IOCON->P1_16 |= 0x01; /* ENET_MDC */\r
+ LPC_IOCON->P1_17 &= ~0x07;\r
+ LPC_IOCON->P1_17 |= 0x01; /* ENET_MDIO */\r
+\r
+ /* Reset all EMAC internal modules. */\r
+ LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;\r
+ LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;\r
+for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */\r
+\r
+ /* Initialize MAC control registers. */\r
+ LPC_EMAC->MAC1 = MAC1_PASS_ALL;\r
+ LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;\r
+ LPC_EMAC->MAXF = ETH_MAX_FLEN;\r
+ LPC_EMAC->CLRT = CLRT_DEF;\r
+ LPC_EMAC->IPGR = IPGR_DEF;\r
+\r
+ /* Enable Reduced MII interface. */\r
+ LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; /* Set clock */\r
+ LPC_EMAC->MCFG |= MCFG_RES_MII; /* and reset */\r
+ LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM |CR_PASS_RX_FILT; /* Enable Reduced MII interface. */\r
+\r
+for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */\r
+\r
+ LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;\r
+ LPC_EMAC->MCMD = 0;\r
+ LPC_EMAC->SUPP = SUPP_RES_RMII; /* Reset Reduced MII Logic. */\r
+for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */\r
+ LPC_EMAC->SUPP = SUPP_SPEED;\r
+\r
+ phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */\r
+ for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */\r
+ regv = phy_read(PHY_REG_BMCR);\r
+ if(regv < 0 || tout == 0) {\r
+ return NyLPC_TBool_FALSE; /* Error */\r
+ }\r
+ if(!(regv & PHY_BMCR_RESET)) {\r
+ break; /* Reset complete. */\r
+ }\r
+ }\r
+\r
+ phy_id = (phy_read(PHY_REG_IDR1) << 16);\r
+ phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);\r
+\r
+ switch(phy_id){\r
+ case DP83848C_ID:\r
+ *o_dev=&_interface_DP83848C;\r
+ break;\r
+ case LAN8720_ID:\r
+ *o_dev=&_interface_LAN8720;\r
+ break;\r
+ default:\r
+ return NyLPC_TBool_FALSE; /* Error */\r
+ }\r
+ LPC_EMAC->TxProduceIndex = 0;\r
+ LPC_EMAC->RxConsumeIndex = 0;\r
+ return NyLPC_TBool_TRUE;\r
+}\r
+\r
+\r
+\r
+static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param)\r
+{\r
+ int i;\r
+ //ISRw割り込み設定\r
+ NyLPC_cIsr_setEnetISR(emacIsrHandler);\r
+ _event_handler=i_handler;\r
+ _event_param=i_param;\r
+ /* Set the Ethernet MAC Address registers */\r
+ LPC_EMAC->SA0 = (((uint32_t)(i_eth_addr->addr[0])) << 8 ) | i_eth_addr->addr[1];\r
+ LPC_EMAC->SA1 = (((uint32_t)(i_eth_addr->addr[2])) << 8 ) | i_eth_addr->addr[3];\r
+ LPC_EMAC->SA2 = (((uint32_t)(i_eth_addr->addr[4])) << 8 ) | i_eth_addr->addr[5];\r
+\r
+ //TXメモリマネージャの準備\r
+ NyLPC_cEthernetMM_initialize(ETH_TX_BUF_BASE);\r
+ /* Initialize Tx and Rx DMA Descriptors */\r
+ prevRxDescriptor();\r
+ prevTxDescriptor();\r
+ //wait for link up\r
+ for(i=0;i<5;i++){\r
+ if(ethernet_link()!=0){\r
+ break;\r
+ }\r
+ NyLPC_cThread_sleep(emacWAIT_FOR_LINK_TO_ESTABLISH_MS);\r
+ }\r
+\r
+ //setup Link\r
+ ethernet_set_link(-1, 0);\r
+\r
+ LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;\r
+ /* Receive Broadcast, Perfect Match Packets */\r
+\r
+ //Ethernetの割込み開始設定\r
+ NyLPC_cIsr_enterCritical();\r
+ {\r
+ LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE; /* Enable EMAC interrupts. */\r
+ LPC_EMAC->IntClear = 0xFFFF; /* Reset all interrupts */\r
+\r
+ LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); /* Enable receive and transmit mode of MAC Ethernet core */\r
+ LPC_EMAC->MAC1 |= MAC1_REC_EN;\r
+\r
+ NVIC_SetPriority( ENET_IRQn, configEMAC_INTERRUPT_PRIORITY );\r
+ NVIC_EnableIRQ( ENET_IRQn );\r
+ }\r
+ NyLPC_cIsr_exitCritical();\r
+\r
+ return NyLPC_TBool_TRUE;\r
+}\r
+\r
+\r
+static void stop(void)\r
+{\r
+ NyLPC_cIsr_enterCritical();\r
+ {\r
+ LPC_EMAC->IntEnable &= ~(INT_RX_DONE | INT_TX_DONE);\r
+ LPC_EMAC->IntClear = 0xFFFF;\r
+\r
+ NVIC_DisableIRQ( ENET_IRQn );\r
+ }\r
+ NyLPC_cIsr_exitCritical();\r
+ LPC_EMAC->Command &= ~( CR_RX_EN | CR_TX_EN );\r
+ LPC_EMAC->MAC1 &= ~MAC1_REC_EN;\r
+ //ISR割り込み解除\r
+ NyLPC_cIsr_setEnetISR(NULL);\r
+ //TXメモリマネージャの終了\r
+ NyLPC_cEthernetMM_finalize();\r
+}\r
+\r
+static struct NyLPC_TTxBufferHeader* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)\r
+{\r
+ return NyLPC_cEthernetMM_alloc(i_hint,o_size);\r
+}\r
+static void releaseTxBuf(struct NyLPC_TTxBufferHeader* i_buf)\r
+{\r
+ NyLPC_cEthernetMM_release(i_buf);\r
+}\r
+\r
+\r
+/**\r
+*/\r
+static void processTx(void)\r
+{\r
+ waitForTxEthFrameEmpty();\r
+}\r
+\r
+\r
+\r
+/**\r
+ * Ethernetパケットを送信します。\r
+ * allocTxBufで得たバッファか、NyLPC_TTxBufferHeaderのペイロード部分を指定すること。\r
+ * <p>関数仕様</p>\r
+ * この関数は、i_bufが\r
+ * </div>\r
+ */\r
+static void sendTxEthFrame(struct NyLPC_TTxBufferHeader* i_buf,unsigned short i_size)\r
+{\r
+ NyLPC_TUInt32 IndexNext,Index;\r
+\r
+ //サイズ0なら送信の必要なし\r
+ if(i_size == 0)\r
+ {\r
+ return;\r
+ }\r
+ //送信デスクリプタの反映\r
+ IndexNext =waitForTxEthFrameEmpty();\r
+\r
+ //送信対象のメモリブロックを送信中に設定。\r
+// b=(i_buf+1);\r
+ //送信中のメモリブロックなら無視\r
+ if(i_buf->is_lock){\r
+ return;\r
+ }\r
+ //送信中にセット\r
+ i_buf->is_lock=NyLPC_TUInt8_TRUE;\r
+\r
+ //送信データのセット\r
+ Index = LPC_EMAC->TxProduceIndex;\r
+ if (i_size > ETH_FRAG_SIZE){\r
+ i_size = ETH_FRAG_SIZE;\r
+ }\r
+ //送信処理\r
+ TX_DESC_PACKET( Index ) = ( unsigned long )(i_buf+1);\r
+ //See UM10360.pdf Table 181. Transmit descriptor control word\r
+ TX_DESC_CTRL( Index ) = ((i_size-1) | TCTRL_LAST | TCTRL_INT );\r
+ LPC_EMAC->TxProduceIndex = IndexNext;\r
+ return;\r
+}\r
+/**\r
+ * 送信デスクリプタを準備します。\r
+ */\r
+static void prevTxDescriptor(void)\r
+{\r
+ long x;\r
+ //デスクリプタの設定\r
+ for( x = 0; x < NUM_TX_FRAG; x++ )\r
+ {\r
+ TX_DESC_PACKET( x ) = ( unsigned long ) NULL;\r
+ TX_DESC_CTRL( x ) = 0;\r
+ TX_STAT_INFO( x ) = 0;\r
+ }\r
+ /* Set LPC_EMAC Transmit Descriptor Registers. */\r
+ LPC_EMAC->TxDescriptor =TX_DESC_BASE;\r
+ LPC_EMAC->TxStatus = TX_STAT_BASE;\r
+ LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1;\r
+}\r
+static void prevRxDescriptor(void)\r
+{\r
+ int x;\r
+ //デスクリプタの設定\r
+ for( x = 0; x < NUM_RX_FRAG; x++ )\r
+ {\r
+ /* Allocate the next Ethernet buffer to this descriptor. */\r
+ RX_DESC_PACKET(x) = ETH_BUF(x);\r
+ RX_DESC_CTRL(x) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 );\r
+ RX_STAT_INFO(x) = 0;\r
+ RX_STAT_HASHCRC(x) = 0;\r
+ }\r
+\r
+ /* Set LPC_EMAC Receive Descriptor Registers. */\r
+ LPC_EMAC->RxDescriptor = RX_DESC_BASE;\r
+ LPC_EMAC->RxStatus = RX_STAT_BASE;\r
+ LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1;\r
+\r
+}\r
+\r
+\r
+/**\r
+ * 受信キューの先頭にあるRXフレームのポインタを返します。\r
+ * 関数は、受信キューのポインタを操作しません。続けて読み出したとしても、同じポインターを返します。\r
+ * 制限として、返却したポインタの内容は、一時的に書き換え可としてください。(この制限は将来削除します。)\r
+ * @return\r
+ * 成功した場合、受信データを格納したバッファポインターです。\r
+ * 次回nextRxEthFrameを呼び出すまで有効です。\r
+ */\r
+static void* getRxEthFrame(unsigned short* o_len_of_data)\r
+{\r
+ if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )\r
+ {\r
+ //受信データを返却する。\r
+ *o_len_of_data = (unsigned short)(( RX_STAT_INFO( LPC_EMAC->RxConsumeIndex ) & RINFO_SIZE ) - 3);\r
+ return ( unsigned char * ) RX_DESC_PACKET( LPC_EMAC->RxConsumeIndex );\r
+ }\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ * 受信キューを進行します。\r
+ */\r
+static void nextRxEthFrame(void)\r
+{\r
+ long lIndex;\r
+ if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )\r
+ {\r
+ //キューすすめる。\r
+ lIndex = LPC_EMAC->RxConsumeIndex;\r
+ lIndex++;\r
+ if( lIndex >= NUM_RX_FRAG )\r
+ {\r
+ lIndex = 0;\r
+ }\r
+ LPC_EMAC->RxConsumeIndex = lIndex;\r
+ }\r
+}\r
+/********************************************************************************\r
+ * Private functions\r
+ *******************************************************************************/\r
+\r
+\r
+\r
+/**\r
+ * 送信中のイーサフレームを処理する機会を与えて、送信キューが空くまで待ちます。\r
+ * LPC1769の場合は、非同期に更新したディスクリプタの内容から、送信メモリのフラグを更新します。\r
+ * @return\r
+ * 次に書き込むことが出来る送信キュー。\r
+ */\r
+static NyLPC_TUInt32 waitForTxEthFrameEmpty(void)\r
+{\r
+ NyLPC_TUInt32 IndexNext;\r
+ struct NyLPC_TTxBufferHeader *b;\r
+ void* p;\r
+ NyLPC_TUInt32 i;\r
+\r
+ //送信キューの決定\r
+ IndexNext = (LPC_EMAC->TxProduceIndex + 1)%NUM_TX_FRAG;\r
+\r
+ //送信キューフルが解除されるまで待ち\r
+ while(IndexNext == LPC_EMAC->TxConsumeIndex)\r
+ {\r
+ //\r
+ NyLPC_cThread_sleep(emacSHORT_DELAY_MS);\r
+ }\r
+\r
+ //(TxProduceIndex+1)→TxConsumeIndexにあるデータのsentフラグを消去\r
+ for(i=IndexNext;i!=LPC_EMAC->TxConsumeIndex;i=(i+1)%NUM_TX_FRAG)\r
+ {\r
+ p=(void*)TX_DESC_PACKET(i);\r
+ if(p!=NULL){\r
+ b=((struct NyLPC_TTxBufferHeader*)p)-1;\r
+ b->is_lock=NyLPC_TUInt8_FALSE;\r
+ TX_DESC_PACKET(i)=0;\r
+ }\r
+ }\r
+ p=(void*)TX_DESC_PACKET(i);\r
+ if(p!=NULL){\r
+ b=((struct NyLPC_TTxBufferHeader*)p)-1;\r
+ b->is_lock=NyLPC_TUInt8_FALSE;\r
+ TX_DESC_PACKET(i)=0;\r
+ }\r
+ return IndexNext;\r
+}\r
+\r
+//--------------------------------------------------------------------------------\r
+// ISR\r
+//--------------------------------------------------------------------------------\r
+\r
+static void ethernet_set_link(int speed, int duplex) {\r
+ unsigned short phy_data;\r
+ int tout;\r
+\r
+ if((speed < 0) || (speed > 1)) {\r
+ phy_data = PHY_AUTO_NEG;\r
+ } else {\r
+ phy_data = (((unsigned short) speed << 13) |\r
+ ((unsigned short) duplex << 8));\r
+ }\r
+\r
+ phy_write(PHY_REG_BMCR, phy_data);\r
+\r
+ for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */\r
+\r
+ switch(phy_id) {\r
+ case DP83848C_ID:\r
+ phy_data = phy_read(PHY_REG_STS);\r
+\r
+ if(phy_data & PHY_STS_DUPLEX) {\r
+ LPC_EMAC->MAC2 |= MAC2_FULL_DUP;\r
+ LPC_EMAC->Command |= CR_FULL_DUP;\r
+ LPC_EMAC->IPGT = IPGT_FULL_DUP;\r
+ } else {\r
+ LPC_EMAC->MAC2 &= ~MAC2_FULL_DUP;\r
+ LPC_EMAC->Command &= ~CR_FULL_DUP;\r
+ LPC_EMAC->IPGT = IPGT_HALF_DUP;\r
+ }\r
+\r
+ if(phy_data & PHY_STS_SPEED) {\r
+ LPC_EMAC->SUPP &= ~SUPP_SPEED;\r
+ } else {\r
+ LPC_EMAC->SUPP |= SUPP_SPEED;\r
+ }\r
+ break;\r
+\r
+ case LAN8720_ID:\r
+ phy_data = phy_read(PHY_REG_SCSR);\r
+\r
+ if (phy_data & PHY_SCSR_DUPLEX) {\r
+ LPC_EMAC->MAC2 |= MAC2_FULL_DUP;\r
+ LPC_EMAC->Command |= CR_FULL_DUP;\r
+ LPC_EMAC->IPGT = IPGT_FULL_DUP;\r
+ } else {\r
+ LPC_EMAC->Command &= ~CR_FULL_DUP;\r
+ LPC_EMAC->IPGT = IPGT_HALF_DUP;\r
+ }\r
+\r
+ if(phy_data & PHY_SCSR_100MBIT) {\r
+ LPC_EMAC->SUPP |= SUPP_SPEED;\r
+ } else {\r
+ LPC_EMAC->SUPP &= ~SUPP_SPEED;\r
+ }\r
+\r
+ break;\r
+ }\r
+}\r
+\r
+static int phy_write(unsigned int PhyReg, unsigned short Data) {\r
+ unsigned int timeOut;\r
+\r
+ LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;\r
+ LPC_EMAC->MWTD = Data;\r
+\r
+ for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) { /* Wait until operation completed */\r
+ if((LPC_EMAC->MIND & MIND_BUSY) == 0) {\r
+ return 0;\r
+ }\r
+ }\r
+\r
+ return -1;\r
+}\r
+\r
+\r
+static int phy_read(unsigned int PhyReg) {\r
+ unsigned int timeOut;\r
+\r
+ LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;\r
+ LPC_EMAC->MCMD = MCMD_READ;\r
+\r
+ for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */\r
+ if((LPC_EMAC->MIND & MIND_BUSY) == 0) {\r
+ LPC_EMAC->MCMD = 0;\r
+ return LPC_EMAC->MRDD; /* Return a 16-bit value. */\r
+ }\r
+ }\r
+\r
+ return -1;\r
+}\r
+\r
+\r
+//extern unsigned int SystemFrequency;\r
+static unsigned int clockselect(void)\r
+{\r
+ if(SystemCoreClock < 10000000) {\r
+ return 1;\r
+ } else if(SystemCoreClock < 15000000) {\r
+ return 2;\r
+ } else if(SystemCoreClock < 20000000) {\r
+ return 3;\r
+ } else if(SystemCoreClock < 25000000) {\r
+ return 4;\r
+ } else if(SystemCoreClock < 35000000) {\r
+ return 5;\r
+ } else if(SystemCoreClock < 50000000) {\r
+ return 6;\r
+ } else if(SystemCoreClock < 70000000) {\r
+ return 7;\r
+ } else if(SystemCoreClock < 80000000) {\r
+ return 8;\r
+ } else if(SystemCoreClock < 90000000) {\r
+ return 9;\r
+ } else if(SystemCoreClock < 100000000) {\r
+ return 10;\r
+ } else if(SystemCoreClock < 120000000) {\r
+ return 11;\r
+ } else if(SystemCoreClock < 130000000) {\r
+ return 12;\r
+ } else if(SystemCoreClock < 140000000) {\r
+ return 13;\r
+ } else if(SystemCoreClock < 150000000) {\r
+ return 15;\r
+ } else if(SystemCoreClock < 160000000) {\r
+ return 16;\r
+ } else {\r
+ return 0;\r
+ }\r
+}\r
+\r
+static int ethernet_link(void)\r
+{\r
+\r
+ if (phy_id == DP83848C_ID) {\r
+ return (phy_read(PHY_REG_STS) & PHY_STS_LINK);\r
+ }\r
+ else { // LAN8720_ID\r
+ return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);\r
+ }\r
+}\r
+//--------------------------------------------------------------------------------\r
+// ISR\r
+//--------------------------------------------------------------------------------\r
+\r
+\r
+/**\r
+ * EMACからのハンドラ\r
+ */\r
+static void emacIsrHandler(unsigned long i_status)\r
+{\r
+ if( i_status & INT_RX_DONE )\r
+ {\r
+ _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_RX);\r
+ }\r
+ if( i_status & INT_TX_DONE )\r
+ {\r
+ _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_TX);\r
+ }\r
+}\r
+\r
+#endif\r
+\r
+\r
+\r
--- /dev/null
+//Copy from mbed HAL\r
+//https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC408X/ethernet_api.c\r
+\r
+#include <string.h>\r
+\r
+#include "ethernet_api.h"\r
+#include "cmsis.h"\r
+#include "mbed_interface.h"\r
+#include "toolchain.h"\r
+#include "error.h"\r
+\r
+#define NUM_RX_FRAG 3 /* Num.of RX Fragments. */\r
+#define NUM_TX_FRAG 16 /* Num.of TX Fragments. */\r
+#define ETH_FRAG_SIZE 1536 /* Packet Fragment size 1536 Bytes */\r
+\r
+#define ETH_MAX_FLEN 1536 /* Max. Ethernet Frame Size */\r
+\r
+#define ETHERNET_ADDR_SIZE 6\r
+\r
+PACKED struct RX_DESC_TypeDef { /* RX Descriptor struct */\r
+ unsigned int Packet;\r
+ unsigned int Ctrl;\r
+};\r
+typedef struct RX_DESC_TypeDef RX_DESC_TypeDef;\r
+\r
+PACKED struct RX_STAT_TypeDef { /* RX Status struct */\r
+ unsigned int Info;\r
+ unsigned int HashCRC;\r
+};\r
+typedef struct RX_STAT_TypeDef RX_STAT_TypeDef;\r
+\r
+PACKED struct TX_DESC_TypeDef { /* TX Descriptor struct */\r
+ unsigned int Packet;\r
+ unsigned int Ctrl;\r
+};\r
+typedef struct TX_DESC_TypeDef TX_DESC_TypeDef;\r
+\r
+PACKED struct TX_STAT_TypeDef { /* TX Status struct */\r
+ unsigned int Info;\r
+};\r
+typedef struct TX_STAT_TypeDef TX_STAT_TypeDef;\r
+\r
+/* MAC Configuration Register 1 */\r
+#define MAC1_REC_EN 0x00000001 /* Receive Enable */\r
+#define MAC1_PASS_ALL 0x00000002 /* Pass All Receive Frames */\r
+#define MAC1_RX_FLOWC 0x00000004 /* RX Flow Control */\r
+#define MAC1_TX_FLOWC 0x00000008 /* TX Flow Control */\r
+#define MAC1_LOOPB 0x00000010 /* Loop Back Mode */\r
+#define MAC1_RES_TX 0x00000100 /* Reset TX Logic */\r
+#define MAC1_RES_MCS_TX 0x00000200 /* Reset MAC TX Control Sublayer */\r
+#define MAC1_RES_RX 0x00000400 /* Reset RX Logic */\r
+#define MAC1_RES_MCS_RX 0x00000800 /* Reset MAC RX Control Sublayer */\r
+#define MAC1_SIM_RES 0x00004000 /* Simulation Reset */\r
+#define MAC1_SOFT_RES 0x00008000 /* Soft Reset MAC */\r
+\r
+/* MAC Configuration Register 2 */\r
+#define MAC2_FULL_DUP 0x00000001 /* Full Duplex Mode */\r
+#define MAC2_FRM_LEN_CHK 0x00000002 /* Frame Length Checking */\r
+#define MAC2_HUGE_FRM_EN 0x00000004 /* Huge Frame Enable */\r
+#define MAC2_DLY_CRC 0x00000008 /* Delayed CRC Mode */\r
+#define MAC2_CRC_EN 0x00000010 /* Append CRC to every Frame */\r
+#define MAC2_PAD_EN 0x00000020 /* Pad all Short Frames */\r
+#define MAC2_VLAN_PAD_EN 0x00000040 /* VLAN Pad Enable */\r
+#define MAC2_ADET_PAD_EN 0x00000080 /* Auto Detect Pad Enable */\r
+#define MAC2_PPREAM_ENF 0x00000100 /* Pure Preamble Enforcement */\r
+#define MAC2_LPREAM_ENF 0x00000200 /* Long Preamble Enforcement */\r
+#define MAC2_NO_BACKOFF 0x00001000 /* No Backoff Algorithm */\r
+#define MAC2_BACK_PRESSURE 0x00002000 /* Backoff Presurre / No Backoff */\r
+#define MAC2_EXCESS_DEF 0x00004000 /* Excess Defer */\r
+\r
+/* Back-to-Back Inter-Packet-Gap Register */\r
+#define IPGT_FULL_DUP 0x00000015 /* Recommended value for Full Duplex */\r
+#define IPGT_HALF_DUP 0x00000012 /* Recommended value for Half Duplex */\r
+\r
+/* Non Back-to-Back Inter-Packet-Gap Register */\r
+#define IPGR_DEF 0x00000012 /* Recommended value */\r
+\r
+/* Collision Window/Retry Register */\r
+#define CLRT_DEF 0x0000370F /* Default value */\r
+\r
+/* PHY Support Register */\r
+#define SUPP_SPEED 0x00000100 /* Reduced MII Logic Current Speed */\r
+//#define SUPP_RES_RMII 0x00000800 /* Reset Reduced MII Logic */\r
+#define SUPP_RES_RMII 0x00000000 /* Reset Reduced MII Logic */\r
+\r
+/* Test Register */\r
+#define TEST_SHCUT_PQUANTA 0x00000001 /* Shortcut Pause Quanta */\r
+#define TEST_TST_PAUSE 0x00000002 /* Test Pause */\r
+#define TEST_TST_BACKP 0x00000004 /* Test Back Pressure */\r
+\r
+/* MII Management Configuration Register */\r
+#define MCFG_SCAN_INC 0x00000001 /* Scan Increment PHY Address */\r
+#define MCFG_SUPP_PREAM 0x00000002 /* Suppress Preamble */\r
+#define MCFG_CLK_SEL 0x0000003C /* Clock Select Mask */\r
+#define MCFG_RES_MII 0x00008000 /* Reset MII Management Hardware */\r
+\r
+/* MII Management Command Register */\r
+#define MCMD_READ 0x00000001 /* MII Read */\r
+#define MCMD_SCAN 0x00000002 /* MII Scan continuously */\r
+\r
+#define MII_WR_TOUT 0x00050000 /* MII Write timeout count */\r
+#define MII_RD_TOUT 0x00050000 /* MII Read timeout count */\r
+\r
+/* MII Management Address Register */\r
+#define MADR_REG_ADR 0x0000001F /* MII Register Address Mask */\r
+#define MADR_PHY_ADR 0x00001F00 /* PHY Address Mask */\r
+\r
+/* MII Management Indicators Register */\r
+#define MIND_BUSY 0x00000001 /* MII is Busy */\r
+#define MIND_SCAN 0x00000002 /* MII Scanning in Progress */\r
+#define MIND_NOT_VAL 0x00000004 /* MII Read Data not valid */\r
+#define MIND_MII_LINK_FAIL 0x00000008 /* MII Link Failed */\r
+\r
+/* Command Register */\r
+#define CR_RX_EN 0x00000001 /* Enable Receive */\r
+#define CR_TX_EN 0x00000002 /* Enable Transmit */\r
+#define CR_REG_RES 0x00000008 /* Reset Host Registers */\r
+#define CR_TX_RES 0x00000010 /* Reset Transmit Datapath */\r
+#define CR_RX_RES 0x00000020 /* Reset Receive Datapath */\r
+#define CR_PASS_RUNT_FRM 0x00000040 /* Pass Runt Frames */\r
+#define CR_PASS_RX_FILT 0x00000080 /* Pass RX Filter */\r
+#define CR_TX_FLOW_CTRL 0x00000100 /* TX Flow Control */\r
+#define CR_RMII 0x00000200 /* Reduced MII Interface */\r
+#define CR_FULL_DUP 0x00000400 /* Full Duplex */\r
+\r
+/* Status Register */\r
+#define SR_RX_EN 0x00000001 /* Enable Receive */\r
+#define SR_TX_EN 0x00000002 /* Enable Transmit */\r
+\r
+/* Transmit Status Vector 0 Register */\r
+#define TSV0_CRC_ERR 0x00000001 /* CRC error */\r
+#define TSV0_LEN_CHKERR 0x00000002 /* Length Check Error */\r
+#define TSV0_LEN_OUTRNG 0x00000004 /* Length Out of Range */\r
+#define TSV0_DONE 0x00000008 /* Tramsmission Completed */\r
+#define TSV0_MCAST 0x00000010 /* Multicast Destination */\r
+#define TSV0_BCAST 0x00000020 /* Broadcast Destination */\r
+#define TSV0_PKT_DEFER 0x00000040 /* Packet Deferred */\r
+#define TSV0_EXC_DEFER 0x00000080 /* Excessive Packet Deferral */\r
+#define TSV0_EXC_COLL 0x00000100 /* Excessive Collision */\r
+#define TSV0_LATE_COLL 0x00000200 /* Late Collision Occured */\r
+#define TSV0_GIANT 0x00000400 /* Giant Frame */\r
+#define TSV0_UNDERRUN 0x00000800 /* Buffer Underrun */\r
+#define TSV0_BYTES 0x0FFFF000 /* Total Bytes Transferred */\r
+#define TSV0_CTRL_FRAME 0x10000000 /* Control Frame */\r
+#define TSV0_PAUSE 0x20000000 /* Pause Frame */\r
+#define TSV0_BACK_PRESS 0x40000000 /* Backpressure Method Applied */\r
+#define TSV0_VLAN 0x80000000 /* VLAN Frame */\r
+\r
+/* Transmit Status Vector 1 Register */\r
+#define TSV1_BYTE_CNT 0x0000FFFF /* Transmit Byte Count */\r
+#define TSV1_COLL_CNT 0x000F0000 /* Transmit Collision Count */\r
+\r
+/* Receive Status Vector Register */\r
+#define RSV_BYTE_CNT 0x0000FFFF /* Receive Byte Count */\r
+#define RSV_PKT_IGNORED 0x00010000 /* Packet Previously Ignored */\r
+#define RSV_RXDV_SEEN 0x00020000 /* RXDV Event Previously Seen */\r
+#define RSV_CARR_SEEN 0x00040000 /* Carrier Event Previously Seen */\r
+#define RSV_REC_CODEV 0x00080000 /* Receive Code Violation */\r
+#define RSV_CRC_ERR 0x00100000 /* CRC Error */\r
+#define RSV_LEN_CHKERR 0x00200000 /* Length Check Error */\r
+#define RSV_LEN_OUTRNG 0x00400000 /* Length Out of Range */\r
+#define RSV_REC_OK 0x00800000 /* Frame Received OK */\r
+#define RSV_MCAST 0x01000000 /* Multicast Frame */\r
+#define RSV_BCAST 0x02000000 /* Broadcast Frame */\r
+#define RSV_DRIB_NIBB 0x04000000 /* Dribble Nibble */\r
+#define RSV_CTRL_FRAME 0x08000000 /* Control Frame */\r
+#define RSV_PAUSE 0x10000000 /* Pause Frame */\r
+#define RSV_UNSUPP_OPC 0x20000000 /* Unsupported Opcode */\r
+#define RSV_VLAN 0x40000000 /* VLAN Frame */\r
+\r
+/* Flow Control Counter Register */\r
+#define FCC_MIRR_CNT 0x0000FFFF /* Mirror Counter */\r
+#define FCC_PAUSE_TIM 0xFFFF0000 /* Pause Timer */\r
+\r
+/* Flow Control Status Register */\r
+#define FCS_MIRR_CNT 0x0000FFFF /* Mirror Counter Current */\r
+\r
+/* Receive Filter Control Register */\r
+#define RFC_UCAST_EN 0x00000001 /* Accept Unicast Frames Enable */\r
+#define RFC_BCAST_EN 0x00000002 /* Accept Broadcast Frames Enable */\r
+#define RFC_MCAST_EN 0x00000004 /* Accept Multicast Frames Enable */\r
+#define RFC_UCAST_HASH_EN 0x00000008 /* Accept Unicast Hash Filter Frames */\r
+#define RFC_MCAST_HASH_EN 0x00000010 /* Accept Multicast Hash Filter Fram.*/\r
+#define RFC_PERFECT_EN 0x00000020 /* Accept Perfect Match Enable */\r
+#define RFC_MAGP_WOL_EN 0x00001000 /* Magic Packet Filter WoL Enable */\r
+#define RFC_PFILT_WOL_EN 0x00002000 /* Perfect Filter WoL Enable */\r
+\r
+/* Receive Filter WoL Status/Clear Registers */\r
+#define WOL_UCAST 0x00000001 /* Unicast Frame caused WoL */\r
+#define WOL_BCAST 0x00000002 /* Broadcast Frame caused WoL */\r
+#define WOL_MCAST 0x00000004 /* Multicast Frame caused WoL */\r
+#define WOL_UCAST_HASH 0x00000008 /* Unicast Hash Filter Frame WoL */\r
+#define WOL_MCAST_HASH 0x00000010 /* Multicast Hash Filter Frame WoL */\r
+#define WOL_PERFECT 0x00000020 /* Perfect Filter WoL */\r
+#define WOL_RX_FILTER 0x00000080 /* RX Filter caused WoL */\r
+#define WOL_MAG_PACKET 0x00000100 /* Magic Packet Filter caused WoL */\r
+\r
+/* Interrupt Status/Enable/Clear/Set Registers */\r
+#define INT_RX_OVERRUN 0x00000001 /* Overrun Error in RX Queue */\r
+#define INT_RX_ERR 0x00000002 /* Receive Error */\r
+#define INT_RX_FIN 0x00000004 /* RX Finished Process Descriptors */\r
+#define INT_RX_DONE 0x00000008 /* Receive Done */\r
+#define INT_TX_UNDERRUN 0x00000010 /* Transmit Underrun */\r
+#define INT_TX_ERR 0x00000020 /* Transmit Error */\r
+#define INT_TX_FIN 0x00000040 /* TX Finished Process Descriptors */\r
+#define INT_TX_DONE 0x00000080 /* Transmit Done */\r
+#define INT_SOFT_INT 0x00001000 /* Software Triggered Interrupt */\r
+#define INT_WAKEUP 0x00002000 /* Wakeup Event Interrupt */\r
+\r
+/* Power Down Register */\r
+#define PD_POWER_DOWN 0x80000000 /* Power Down MAC */\r
+\r
+/* RX Descriptor Control Word */\r
+#define RCTRL_SIZE 0x000007FF /* Buffer size mask */\r
+#define RCTRL_INT 0x80000000 /* Generate RxDone Interrupt */\r
+\r
+/* RX Status Hash CRC Word */\r
+#define RHASH_SA 0x000001FF /* Hash CRC for Source Address */\r
+#define RHASH_DA 0x001FF000 /* Hash CRC for Destination Address */\r
+\r
+/* RX Status Information Word */\r
+#define RINFO_SIZE 0x000007FF /* Data size in bytes */\r
+#define RINFO_CTRL_FRAME 0x00040000 /* Control Frame */\r
+#define RINFO_VLAN 0x00080000 /* VLAN Frame */\r
+#define RINFO_FAIL_FILT 0x00100000 /* RX Filter Failed */\r
+#define RINFO_MCAST 0x00200000 /* Multicast Frame */\r
+#define RINFO_BCAST 0x00400000 /* Broadcast Frame */\r
+#define RINFO_CRC_ERR 0x00800000 /* CRC Error in Frame */\r
+#define RINFO_SYM_ERR 0x01000000 /* Symbol Error from PHY */\r
+#define RINFO_LEN_ERR 0x02000000 /* Length Error */\r
+#define RINFO_RANGE_ERR 0x04000000 /* Range Error (exceeded max. size) */\r
+#define RINFO_ALIGN_ERR 0x08000000 /* Alignment Error */\r
+#define RINFO_OVERRUN 0x10000000 /* Receive overrun */\r
+#define RINFO_NO_DESCR 0x20000000 /* No new Descriptor available */\r
+#define RINFO_LAST_FLAG 0x40000000 /* Last Fragment in Frame */\r
+#define RINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */\r
+\r
+//#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_CRC_ERR | RINFO_SYM_ERR | RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN)\r
+#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_SYM_ERR | RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN)\r
+\r
+\r
+/* TX Descriptor Control Word */\r
+#define TCTRL_SIZE 0x000007FF /* Size of data buffer in bytes */\r
+#define TCTRL_OVERRIDE 0x04000000 /* Override Default MAC Registers */\r
+#define TCTRL_HUGE 0x08000000 /* Enable Huge Frame */\r
+#define TCTRL_PAD 0x10000000 /* Pad short Frames to 64 bytes */\r
+#define TCTRL_CRC 0x20000000 /* Append a hardware CRC to Frame */\r
+#define TCTRL_LAST 0x40000000 /* Last Descriptor for TX Frame */\r
+#define TCTRL_INT 0x80000000 /* Generate TxDone Interrupt */\r
+\r
+/* TX Status Information Word */\r
+#define TINFO_COL_CNT 0x01E00000 /* Collision Count */\r
+#define TINFO_DEFER 0x02000000 /* Packet Deferred (not an error) */\r
+#define TINFO_EXCESS_DEF 0x04000000 /* Excessive Deferral */\r
+#define TINFO_EXCESS_COL 0x08000000 /* Excessive Collision */\r
+#define TINFO_LATE_COL 0x10000000 /* Late Collision Occured */\r
+#define TINFO_UNDERRUN 0x20000000 /* Transmit Underrun */\r
+#define TINFO_NO_DESCR 0x40000000 /* No new Descriptor available */\r
+#define TINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */\r
+\r
+/* ENET Device Revision ID */\r
+#define OLD_EMAC_MODULE_ID 0x39022000 /* Rev. ID for first rev '-' */\r
+\r
+/* DP83848C PHY Registers */\r
+#define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */\r
+#define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */\r
+#define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */\r
+#define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */\r
+#define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */\r
+#define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */\r
+#define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */\r
+#define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */\r
+\r
+/* PHY Extended Registers */\r
+#define PHY_REG_STS 0x10 /* Status Register */\r
+#define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */\r
+#define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */\r
+#define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */\r
+#define PHY_REG_RECR 0x15 /* Receive Error Counter */\r
+#define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */\r
+#define PHY_REG_RBR 0x17 /* RMII and Bypass Register */\r
+#define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */\r
+#define PHY_REG_PHYCR 0x19 /* PHY Control Register */\r
+#define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */\r
+#define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */\r
+#define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */\r
+\r
+#define PHY_REG_SCSR 0x1F /* PHY Special Control/Status Register */\r
+\r
+#define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */\r
+#define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */\r
+#define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */\r
+#define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */\r
+#define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */\r
+\r
+#define DP83848C_DEF_ADR 0x0100 /* Default PHY device address */\r
+#define DP83848C_ID 0x20005C90 /* PHY Identifier - DP83848C */\r
+\r
+#define LAN8720_ID 0x0007C0F0 /* PHY Identifier - LAN8720 */\r
+\r
+#define PHY_STS_LINK 0x0001 /* PHY Status Link Mask */\r
+#define PHY_STS_SPEED 0x0002 /* PHY Status Speed Mask */\r
+#define PHY_STS_DUPLEX 0x0004 /* PHY Status Duplex Mask */\r
+\r
+#define PHY_BMCR_RESET 0x8000 /* PHY Reset */\r
+\r
+#define PHY_BMSR_LINK 0x0004 /* PHY BMSR Link valid */\r
+\r
+#define PHY_SCSR_100MBIT 0x0008 /* Speed: 1=100 MBit, 0=10Mbit */\r
+#define PHY_SCSR_DUPLEX 0x0010 /* PHY Duplex Mask */\r