This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

Dependents:   MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EthDev_LPC4088.c Source File

EthDev_LPC4088.c

00001 #include "NyLPC_config.h"
00002 #if NyLPC_MCU==NyLPC_MCU_LPC4088
00003 #include "NyLPC_os.h"
00004 #include "copy_of_ethernet_api.h"
00005 #include "NyLPC_IEthernetDevice.h"
00006 #include "NyLPC_cEthernetMM.h"
00007 
00008 
00009 
00010 #define emacSHORT_DELAY_MS                 10
00011 #ifndef configEMAC_INTERRUPT_PRIORITY
00012     #define configEMAC_INTERRUPT_PRIORITY       5
00013 #endif
00014 ////////////////////////////////////////////////////////////////////////////////
00015 // Ethernet Memory
00016 ////////////////////////////////////////////////////////////////////////////////
00017 
00018 #define AHB_SRAM_BANK1_BASE  0x20004000UL
00019 #define RX_DESC_BASE        (AHB_SRAM_BANK1_BASE         )
00020 #define RX_STAT_BASE        (RX_DESC_BASE + NUM_RX_FRAG*(2*4))     /* 2 * uint32_t, see RX_DESC_TypeDef */
00021 #define TX_DESC_BASE        (RX_STAT_BASE + NUM_RX_FRAG*(2*4))     /* 2 * uint32_t, see RX_STAT_TypeDef */
00022 #define TX_STAT_BASE        (TX_DESC_BASE + NUM_TX_FRAG*(2*4))     /* 2 * uint32_t, see TX_DESC_TypeDef */
00023 #define ETH_BUF_BASE        (TX_STAT_BASE + NUM_TX_FRAG*(1*4))     /* 1 * uint32_t, see TX_STAT_TypeDef */
00024 
00025 /**
00026  * 消費メモリ量は、
00027  * descriptor = NUM_RX_FRAG*16+NUM_TX_FRAG*12.
00028  * EthnetBuf=ETH_FRAG_SIZE*NUM_RX_FRAG
00029  */
00030 
00031 /* RX and TX descriptor and status definitions. */
00032 #define RX_DESC_PACKET(i)   (*(unsigned int *)(RX_DESC_BASE   + 8*i))
00033 #define RX_DESC_CTRL(i)     (*(unsigned int *)(RX_DESC_BASE+4 + 8*i))
00034 #define RX_STAT_INFO(i)     (*(unsigned int *)(RX_STAT_BASE   + 8*i))
00035 #define RX_STAT_HASHCRC(i)  (*(unsigned int *)(RX_STAT_BASE+4 + 8*i))
00036 #define TX_DESC_PACKET(i)   (*(unsigned int *)(TX_DESC_BASE   + 8*i))
00037 #define TX_DESC_CTRL(i)     (*(unsigned int *)(TX_DESC_BASE+4 + 8*i))
00038 #define TX_STAT_INFO(i)     (*(unsigned int *)(TX_STAT_BASE   + 4*i))
00039 #define ETH_BUF(i)          ( ETH_BUF_BASE + ETH_FRAG_SIZE*i )
00040 #define ETH_TX_BUF_BASE ((void*)(ETH_BUF_BASE+ETH_FRAG_SIZE*NUM_RX_FRAG))
00041 
00042 
00043 #define emacWAIT_FOR_LINK_TO_ESTABLISH_MS 500
00044 
00045 ////////////////////////////////////////////////////////////////////////////////
00046 // Ethernet interdface functions
00047 ////////////////////////////////////////////////////////////////////////////////
00048 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param);
00049 static void stop(void);
00050 static void* getRxEthFrame(unsigned short* o_len_of_data);
00051 static void nextRxEthFrame(void);
00052 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size);
00053 static void releaseTxBuf(void* i_buf);
00054 static void sendTxEthFrame(void* i_buf,unsigned short i_size);
00055 static void processTx(void);
00056 
00057 ////////////////////////////////////////////////////////////////////////////////
00058 // Private
00059 ////////////////////////////////////////////////////////////////////////////////
00060 static void emacIsrHandler(unsigned long i_status);
00061 static unsigned int clockselect(void);
00062 static int ethernet_link(void);
00063 static int phy_write(unsigned int PhyReg, unsigned short Data);
00064 static int phy_read(unsigned int PhyReg);
00065 static void prevTxDescriptor(void);
00066 static void prevRxDescriptor(void);
00067 static NyLPC_TUInt32 waitForTxEthFrameEmpty(void);
00068 
00069 /*-----------------------------------------------------------*/
00070 
00071 
00072 const static struct TiEthernetDevice _interface_LAN8720=
00073 {
00074     "LAN8720",
00075     start,
00076     stop,
00077     getRxEthFrame,
00078     nextRxEthFrame,
00079     allocTxBuf,
00080     releaseTxBuf,
00081     sendTxEthFrame,
00082     processTx
00083 };
00084 const static struct TiEthernetDevice _interface_DP83848C=
00085 {
00086     "DP83848C",
00087     start,
00088     stop,
00089     getRxEthFrame,
00090     nextRxEthFrame,
00091     allocTxBuf,
00092     releaseTxBuf,
00093     sendTxEthFrame,
00094     processTx
00095 };
00096 
00097 static void* _event_param;
00098 static NyLPC_TiEthernetDevice_onEvent _event_handler;
00099 static unsigned int phy_id;
00100 
00101 /*
00102  * EthernetDeviceのファクトリー関数。インターフェイスを生成できればtrue
00103  *
00104  */
00105 NyLPC_TBool EthDev_LPC4088_getInterface(
00106     const struct TiEthernetDevice** o_dev)
00107 {
00108     int regv, tout;
00109     unsigned int clock = clockselect();
00110     
00111     LPC_SC->PCONP |= 0x40000000; /* Power Up the EMAC controller. */
00112     LPC_IOCON->P1_0 &= ~0x07; /* ENET I/O config */
00113     LPC_IOCON->P1_0 |= 0x01; /* ENET_TXD0 */
00114     LPC_IOCON->P1_1 &= ~0x07;
00115     LPC_IOCON->P1_1 |= 0x01; /* ENET_TXD1 */
00116     LPC_IOCON->P1_4 &= ~0x07;
00117     LPC_IOCON->P1_4 |= 0x01; /* ENET_TXEN */
00118     LPC_IOCON->P1_8 &= ~0x07;
00119     LPC_IOCON->P1_8 |= 0x01; /* ENET_CRS */
00120     LPC_IOCON->P1_9 &= ~0x07;
00121     LPC_IOCON->P1_9 |= 0x01; /* ENET_RXD0 */
00122     LPC_IOCON->P1_10 &= ~0x07;
00123     LPC_IOCON->P1_10 |= 0x01; /* ENET_RXD1 */
00124     LPC_IOCON->P1_14 &= ~0x07;
00125     LPC_IOCON->P1_14 |= 0x01; /* ENET_RX_ER */
00126     LPC_IOCON->P1_15 &= ~0x07;
00127     LPC_IOCON->P1_15 |= 0x01; /* ENET_REF_CLK */
00128     LPC_IOCON->P1_16 &= ~0x07; /* ENET/PHY I/O config */
00129     LPC_IOCON->P1_16 |= 0x01; /* ENET_MDC */
00130     LPC_IOCON->P1_17 &= ~0x07;
00131     LPC_IOCON->P1_17 |= 0x01; /* ENET_MDIO */
00132   
00133     /* Reset all EMAC internal modules. */
00134     LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
00135     LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;      
00136 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */
00137     
00138     /* Initialize MAC control registers. */
00139     LPC_EMAC->MAC1 = MAC1_PASS_ALL; 
00140     LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
00141     LPC_EMAC->MAXF = ETH_MAX_FLEN;
00142     LPC_EMAC->CLRT = CLRT_DEF;
00143     LPC_EMAC->IPGR = IPGR_DEF;
00144     
00145     /* Enable Reduced MII interface. */
00146     LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; /* Set clock */
00147     LPC_EMAC->MCFG |= MCFG_RES_MII; /* and reset */
00148     LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM |CR_PASS_RX_FILT; /* Enable Reduced MII interface. */
00149     
00150 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */
00151 
00152     LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;
00153     LPC_EMAC->MCMD = 0;
00154     LPC_EMAC->SUPP = SUPP_RES_RMII; /* Reset Reduced MII Logic. */
00155 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */
00156     LPC_EMAC->SUPP = SUPP_SPEED;
00157     
00158     phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */
00159     for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */
00160         regv = phy_read(PHY_REG_BMCR);
00161         if(regv < 0 || tout == 0) {
00162             return NyLPC_TBool_FALSE; /* Error */
00163         }
00164         if(!(regv & PHY_BMCR_RESET)) {
00165             break; /* Reset complete. */
00166         }
00167     }
00168 
00169     phy_id = (phy_read(PHY_REG_IDR1) << 16);
00170     phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);
00171 
00172     switch(phy_id){
00173     case DP83848C_ID:
00174         *o_dev=&_interface_DP83848C;
00175         break;
00176     case LAN8720_ID:
00177         *o_dev=&_interface_LAN8720;
00178         break;
00179     default:
00180         return NyLPC_TBool_FALSE; /* Error */
00181     }
00182     LPC_EMAC->TxProduceIndex = 0;
00183     LPC_EMAC->RxConsumeIndex = 0;   
00184     return NyLPC_TBool_TRUE;
00185 }
00186 
00187 
00188 
00189 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param)
00190 {
00191     int i;
00192     //ISRw割り込み設定
00193     NyLPC_cIsr_setEnetISR(emacIsrHandler);
00194     _event_handler=i_handler;
00195     _event_param=i_param;
00196     /* Set the Ethernet MAC Address registers */
00197     LPC_EMAC->SA0 = (((uint32_t)(i_eth_addr->addr[0])) << 8 ) | i_eth_addr->addr[1];
00198     LPC_EMAC->SA1 = (((uint32_t)(i_eth_addr->addr[2])) << 8 ) | i_eth_addr->addr[3];
00199     LPC_EMAC->SA2 = (((uint32_t)(i_eth_addr->addr[4])) << 8 ) | i_eth_addr->addr[5];
00200 
00201     //TXメモリマネージャの準備
00202     NyLPC_cEthernetMM_initialize(ETH_TX_BUF_BASE);
00203     /* Initialize Tx and Rx DMA Descriptors */
00204     prevRxDescriptor();
00205     prevTxDescriptor();
00206     //wait for link up 
00207     for(i=0;i<5;i++){
00208         if(ethernet_link()!=0){
00209             break;
00210         }
00211         NyLPC_cThread_sleep(emacWAIT_FOR_LINK_TO_ESTABLISH_MS);
00212     }
00213 
00214     //setup Link
00215     ethernet_set_link(-1, 0);
00216 
00217     LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
00218     /* Receive Broadcast, Perfect Match Packets */
00219 
00220     //Ethernetの割込み開始設定
00221     NyLPC_cIsr_enterCritical();
00222     {
00223         LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE; /* Enable EMAC interrupts. */
00224         LPC_EMAC->IntClear = 0xFFFF; /* Reset all interrupts */
00225       
00226         LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); /* Enable receive and transmit mode of MAC Ethernet core */
00227         LPC_EMAC->MAC1 |= MAC1_REC_EN;
00228 
00229         NVIC_SetPriority( ENET_IRQn, configEMAC_INTERRUPT_PRIORITY );
00230         NVIC_EnableIRQ( ENET_IRQn );
00231     }
00232     NyLPC_cIsr_exitCritical();
00233 
00234     return NyLPC_TBool_TRUE;
00235 }
00236 
00237 
00238 static void stop(void)
00239 {
00240     NyLPC_cIsr_enterCritical();
00241     {
00242         LPC_EMAC->IntEnable &= ~(INT_RX_DONE | INT_TX_DONE);
00243         LPC_EMAC->IntClear = 0xFFFF;
00244         
00245         NVIC_DisableIRQ( ENET_IRQn );
00246     }
00247     NyLPC_cIsr_exitCritical();
00248     LPC_EMAC->Command &= ~( CR_RX_EN | CR_TX_EN );
00249     LPC_EMAC->MAC1 &= ~MAC1_REC_EN;
00250     //ISR割り込み解除
00251     NyLPC_cIsr_setEnetISR(NULL);
00252     //TXメモリマネージャの終了
00253     NyLPC_cEthernetMM_finalize();
00254 }
00255 
00256 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)
00257 {
00258     return NyLPC_cEthernetMM_alloc(i_hint,o_size);
00259 }
00260 static void releaseTxBuf(void* i_buf)
00261 {
00262     NyLPC_cEthernetMM_release(i_buf);
00263 }
00264 
00265 
00266 /**
00267 */
00268 static void processTx(void)
00269 {
00270     waitForTxEthFrameEmpty();
00271 }
00272 
00273 
00274 
00275 /**
00276  * Ethernetパケットを送信します。
00277  * allocTxBufで得たバッファを指定すること。
00278  * <p>関数仕様</p>
00279  * この関数は、i_bufが
00280  * </div>
00281  */
00282 static void sendTxEthFrame(void* i_buf,unsigned short i_size)
00283 {
00284     NyLPC_TUInt32   IndexNext,Index;
00285     struct NyLPC_TTxBufferHeader* bh=NyLPC_TTxBufferHeader_getBufferHeaderAddr(i_buf);
00286 
00287     //サイズ0なら送信の必要なし
00288     if(i_size == 0)
00289     {
00290         return;
00291     }
00292     //送信デスクリプタの反映
00293     IndexNext =waitForTxEthFrameEmpty();
00294 
00295     //送信対象のメモリブロックを送信中に設定。
00296 //  b=(i_buf+1);
00297     //送信中のメモリブロックなら無視
00298     if(bh->is_lock){
00299         return;
00300     }
00301     //送信中にセット
00302     bh->is_lock=NyLPC_TUInt8_TRUE;
00303 
00304     //送信データのセット
00305     Index = LPC_EMAC->TxProduceIndex;
00306     if (i_size > ETH_FRAG_SIZE){
00307         i_size = ETH_FRAG_SIZE;
00308     }
00309     //送信処理
00310     TX_DESC_PACKET( Index ) = ( unsigned long )i_buf;
00311     //See UM10360.pdf Table 181. Transmit descriptor control word
00312     TX_DESC_CTRL( Index ) = ((i_size-1) | TCTRL_LAST | TCTRL_INT );
00313     LPC_EMAC->TxProduceIndex = IndexNext;
00314     return;
00315 }
00316 /**
00317  * 送信デスクリプタを準備します。
00318  */
00319 static void prevTxDescriptor(void)
00320 {
00321     long x;
00322     //デスクリプタの設定
00323     for( x = 0; x < NUM_TX_FRAG; x++ )
00324     {
00325         TX_DESC_PACKET( x ) = ( unsigned long ) NULL;
00326         TX_DESC_CTRL( x ) = 0;
00327         TX_STAT_INFO( x ) = 0;
00328     }
00329     /* Set LPC_EMAC Transmit Descriptor Registers. */
00330     LPC_EMAC->TxDescriptor =TX_DESC_BASE;
00331     LPC_EMAC->TxStatus = TX_STAT_BASE;
00332     LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1;
00333 }
00334 static void prevRxDescriptor(void)
00335 {
00336     int x;
00337     //デスクリプタの設定
00338     for( x = 0; x < NUM_RX_FRAG; x++ )
00339     {
00340         /* Allocate the next Ethernet buffer to this descriptor. */
00341         RX_DESC_PACKET(x) = ETH_BUF(x);
00342         RX_DESC_CTRL(x) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 );
00343         RX_STAT_INFO(x) = 0;
00344         RX_STAT_HASHCRC(x) = 0;
00345     }
00346 
00347     /* Set LPC_EMAC Receive Descriptor Registers. */
00348     LPC_EMAC->RxDescriptor = RX_DESC_BASE;
00349     LPC_EMAC->RxStatus = RX_STAT_BASE;
00350     LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1;
00351 
00352 }
00353 
00354 
00355 /**
00356  * 受信キューの先頭にあるRXフレームのポインタを返します。
00357  * 関数は、受信キューのポインタを操作しません。続けて読み出したとしても、同じポインターを返します。
00358  * 制限として、返却したポインタの内容は、一時的に書き換え可としてください。(この制限は将来削除します。)
00359  * @return
00360  * 成功した場合、受信データを格納したバッファポインターです。
00361  * 次回nextRxEthFrameを呼び出すまで有効です。
00362  */
00363 static void* getRxEthFrame(unsigned short* o_len_of_data)
00364 {
00365     if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )
00366     {
00367         //受信データを返却する。
00368         *o_len_of_data = (unsigned short)(( RX_STAT_INFO( LPC_EMAC->RxConsumeIndex ) & RINFO_SIZE ) - 3);
00369         return ( unsigned char * ) RX_DESC_PACKET( LPC_EMAC->RxConsumeIndex );
00370     }
00371     return NULL;
00372 }
00373 
00374 
00375 /**
00376  * 受信キューを進行します。
00377  */
00378 static void nextRxEthFrame(void)
00379 {
00380     long lIndex;
00381     if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )
00382     {
00383         //キューすすめる。
00384         lIndex = LPC_EMAC->RxConsumeIndex;
00385         lIndex++;
00386         if( lIndex >= NUM_RX_FRAG )
00387         {
00388             lIndex = 0;
00389         }
00390         LPC_EMAC->RxConsumeIndex = lIndex;
00391     }
00392 }
00393 /********************************************************************************
00394  * Private functions
00395  *******************************************************************************/
00396 
00397 
00398 
00399 /**
00400  * 送信中のイーサフレームを処理する機会を与えて、送信キューが空くまで待ちます。
00401  * LPC1769の場合は、非同期に更新したディスクリプタの内容から、送信メモリのフラグを更新します。
00402  * @return
00403  * 次に書き込むことが出来る送信キュー。
00404  */
00405 static NyLPC_TUInt32 waitForTxEthFrameEmpty(void)
00406 {
00407     NyLPC_TUInt32   IndexNext;
00408     struct NyLPC_TTxBufferHeader *b;
00409     void* p;
00410     NyLPC_TUInt32 i;
00411 
00412     //送信キューの決定
00413     IndexNext = (LPC_EMAC->TxProduceIndex + 1)%NUM_TX_FRAG;
00414 
00415     //送信キューフルが解除されるまで待ち
00416     while(IndexNext == LPC_EMAC->TxConsumeIndex)
00417     {
00418         //
00419         NyLPC_cThread_sleep(emacSHORT_DELAY_MS);
00420     }
00421 
00422     //(TxProduceIndex+1)→TxConsumeIndexにあるデータのsentフラグを消去
00423     for(i=IndexNext;i!=LPC_EMAC->TxConsumeIndex;i=(i+1)%NUM_TX_FRAG)
00424     {
00425         p=(void*)TX_DESC_PACKET(i);
00426         if(p!=NULL){
00427             b=NyLPC_TTxBufferHeader_getBufferHeaderAddr(p);
00428             b->is_lock=NyLPC_TUInt8_FALSE;
00429             TX_DESC_PACKET(i)=0;
00430         }
00431     }
00432     p=(void*)TX_DESC_PACKET(i);
00433     if(p!=NULL){
00434         b=NyLPC_TTxBufferHeader_getBufferHeaderAddr(p);
00435         b->is_lock=NyLPC_TUInt8_FALSE;
00436         TX_DESC_PACKET(i)=0;
00437     }
00438     return IndexNext;
00439 }
00440 
00441 //--------------------------------------------------------------------------------
00442 // ISR
00443 //--------------------------------------------------------------------------------
00444 
00445 static void ethernet_set_link(int speed, int duplex) {
00446     unsigned short phy_data;
00447     int tout;
00448     
00449     if((speed < 0) || (speed > 1)) {
00450         phy_data = PHY_AUTO_NEG;
00451     } else {
00452         phy_data = (((unsigned short) speed << 13) |
00453                     ((unsigned short) duplex << 8));
00454     }
00455     
00456     phy_write(PHY_REG_BMCR, phy_data);
00457     
00458     for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */
00459     
00460     switch(phy_id) {
00461         case DP83848C_ID:
00462             phy_data = phy_read(PHY_REG_STS);
00463             
00464             if(phy_data & PHY_STS_DUPLEX) {
00465                 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
00466                 LPC_EMAC->Command |= CR_FULL_DUP;
00467                 LPC_EMAC->IPGT = IPGT_FULL_DUP;
00468             } else {
00469             LPC_EMAC->MAC2 &= ~MAC2_FULL_DUP;
00470                 LPC_EMAC->Command &= ~CR_FULL_DUP;
00471                 LPC_EMAC->IPGT = IPGT_HALF_DUP;
00472             }
00473             
00474             if(phy_data & PHY_STS_SPEED) {
00475                 LPC_EMAC->SUPP &= ~SUPP_SPEED;
00476             } else {
00477                 LPC_EMAC->SUPP |= SUPP_SPEED;
00478             }
00479             break;
00480         
00481         case LAN8720_ID:
00482             phy_data = phy_read(PHY_REG_SCSR);
00483             
00484             if (phy_data & PHY_SCSR_DUPLEX) {
00485                 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
00486                 LPC_EMAC->Command |= CR_FULL_DUP;
00487                 LPC_EMAC->IPGT = IPGT_FULL_DUP;
00488             } else {
00489                 LPC_EMAC->Command &= ~CR_FULL_DUP;
00490                 LPC_EMAC->IPGT = IPGT_HALF_DUP;
00491             }
00492             
00493             if(phy_data & PHY_SCSR_100MBIT) {
00494                 LPC_EMAC->SUPP |= SUPP_SPEED;
00495             } else {
00496                 LPC_EMAC->SUPP &= ~SUPP_SPEED;
00497             }
00498             
00499             break;
00500     }
00501 }
00502 
00503 static int phy_write(unsigned int PhyReg, unsigned short Data) {
00504     unsigned int timeOut;
00505 
00506     LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
00507     LPC_EMAC->MWTD = Data;
00508 
00509     for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) { /* Wait until operation completed */
00510         if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
00511             return 0;
00512         }
00513     }
00514 
00515     return -1;
00516 }
00517 
00518 
00519 static int phy_read(unsigned int PhyReg) {
00520     unsigned int timeOut;
00521 
00522     LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
00523     LPC_EMAC->MCMD = MCMD_READ;
00524 
00525     for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */
00526         if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
00527             LPC_EMAC->MCMD = 0;
00528             return LPC_EMAC->MRDD; /* Return a 16-bit value. */
00529         }
00530     }
00531 
00532     return -1;
00533 }
00534 
00535 
00536 //extern unsigned int SystemFrequency;
00537 static unsigned int clockselect(void)
00538 {
00539   if(SystemCoreClock < 10000000) {
00540     return 1;
00541   } else if(SystemCoreClock < 15000000) {
00542     return 2;
00543   } else if(SystemCoreClock < 20000000) {
00544     return 3;
00545   } else if(SystemCoreClock < 25000000) {
00546     return 4;
00547   } else if(SystemCoreClock < 35000000) {
00548     return 5;
00549   } else if(SystemCoreClock < 50000000) {
00550     return 6;
00551   } else if(SystemCoreClock < 70000000) {
00552     return 7;
00553   } else if(SystemCoreClock < 80000000) {
00554     return 8;
00555   } else if(SystemCoreClock < 90000000) {
00556     return 9;
00557   } else if(SystemCoreClock < 100000000) {
00558     return 10;
00559   } else if(SystemCoreClock < 120000000) {
00560     return 11;
00561   } else if(SystemCoreClock < 130000000) {
00562     return 12;
00563   } else if(SystemCoreClock < 140000000) {
00564     return 13;
00565   } else if(SystemCoreClock < 150000000) {
00566     return 15;
00567   } else if(SystemCoreClock < 160000000) {
00568     return 16;
00569   } else {
00570     return 0;
00571   }
00572 }
00573 
00574 static int ethernet_link(void)
00575 {
00576 
00577     if (phy_id == DP83848C_ID) {
00578       return (phy_read(PHY_REG_STS) & PHY_STS_LINK);
00579     }
00580     else { // LAN8720_ID
00581       return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);
00582     }
00583 }
00584 //--------------------------------------------------------------------------------
00585 // ISR
00586 //--------------------------------------------------------------------------------
00587 
00588 
00589 /**
00590  * EMACからのハンドラ
00591  */
00592 static void emacIsrHandler(unsigned long i_status)
00593 {
00594     if( i_status & INT_RX_DONE )
00595     {
00596         _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_RX);
00597     }
00598     if( i_status & INT_TX_DONE )
00599     {
00600         _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_TX);
00601     }
00602 }
00603 
00604 #endif
00605 
00606 
00607