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

Fork of libMiMic by Ryo Iizuka

Committer:
nyatla
Date:
Sun Oct 19 08:44:52 2014 +0000
Revision:
97:6ca5900a2d68
Parent:
92:4f77028cce64
Bugfix LPC4088 driver; Bugfix mDNS TTL;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nyatla 69:8c5f220441f5 1 #include "NyLPC_config.h"
nyatla 69:8c5f220441f5 2 #if NyLPC_MCU==NyLPC_MCU_LPC4088
nyatla 69:8c5f220441f5 3 #include "NyLPC_os.h"
nyatla 69:8c5f220441f5 4 #include "copy_of_ethernet_api.h"
nyatla 69:8c5f220441f5 5 #include "NyLPC_IEthernetDevice.h"
nyatla 69:8c5f220441f5 6 #include "NyLPC_cEthernetMM.h"
nyatla 69:8c5f220441f5 7
nyatla 69:8c5f220441f5 8
nyatla 69:8c5f220441f5 9
nyatla 69:8c5f220441f5 10 #define emacSHORT_DELAY_MS 10
nyatla 69:8c5f220441f5 11 #ifndef configEMAC_INTERRUPT_PRIORITY
nyatla 69:8c5f220441f5 12 #define configEMAC_INTERRUPT_PRIORITY 5
nyatla 69:8c5f220441f5 13 #endif
nyatla 69:8c5f220441f5 14 ////////////////////////////////////////////////////////////////////////////////
nyatla 69:8c5f220441f5 15 // Ethernet Memory
nyatla 69:8c5f220441f5 16 ////////////////////////////////////////////////////////////////////////////////
nyatla 69:8c5f220441f5 17
nyatla 69:8c5f220441f5 18 #define AHB_SRAM_BANK1_BASE 0x20004000UL
nyatla 69:8c5f220441f5 19 #define RX_DESC_BASE (AHB_SRAM_BANK1_BASE )
nyatla 69:8c5f220441f5 20 #define RX_STAT_BASE (RX_DESC_BASE + NUM_RX_FRAG*(2*4)) /* 2 * uint32_t, see RX_DESC_TypeDef */
nyatla 69:8c5f220441f5 21 #define TX_DESC_BASE (RX_STAT_BASE + NUM_RX_FRAG*(2*4)) /* 2 * uint32_t, see RX_STAT_TypeDef */
nyatla 69:8c5f220441f5 22 #define TX_STAT_BASE (TX_DESC_BASE + NUM_TX_FRAG*(2*4)) /* 2 * uint32_t, see TX_DESC_TypeDef */
nyatla 69:8c5f220441f5 23 #define ETH_BUF_BASE (TX_STAT_BASE + NUM_TX_FRAG*(1*4)) /* 1 * uint32_t, see TX_STAT_TypeDef */
nyatla 69:8c5f220441f5 24
nyatla 69:8c5f220441f5 25 /**
nyatla 69:8c5f220441f5 26 * 消費メモリ量は、
nyatla 69:8c5f220441f5 27 * descriptor = NUM_RX_FRAG*16+NUM_TX_FRAG*12.
nyatla 69:8c5f220441f5 28 * EthnetBuf=ETH_FRAG_SIZE*NUM_RX_FRAG
nyatla 69:8c5f220441f5 29 */
nyatla 69:8c5f220441f5 30
nyatla 69:8c5f220441f5 31 /* RX and TX descriptor and status definitions. */
nyatla 69:8c5f220441f5 32 #define RX_DESC_PACKET(i) (*(unsigned int *)(RX_DESC_BASE + 8*i))
nyatla 69:8c5f220441f5 33 #define RX_DESC_CTRL(i) (*(unsigned int *)(RX_DESC_BASE+4 + 8*i))
nyatla 69:8c5f220441f5 34 #define RX_STAT_INFO(i) (*(unsigned int *)(RX_STAT_BASE + 8*i))
nyatla 69:8c5f220441f5 35 #define RX_STAT_HASHCRC(i) (*(unsigned int *)(RX_STAT_BASE+4 + 8*i))
nyatla 69:8c5f220441f5 36 #define TX_DESC_PACKET(i) (*(unsigned int *)(TX_DESC_BASE + 8*i))
nyatla 69:8c5f220441f5 37 #define TX_DESC_CTRL(i) (*(unsigned int *)(TX_DESC_BASE+4 + 8*i))
nyatla 69:8c5f220441f5 38 #define TX_STAT_INFO(i) (*(unsigned int *)(TX_STAT_BASE + 4*i))
nyatla 69:8c5f220441f5 39 #define ETH_BUF(i) ( ETH_BUF_BASE + ETH_FRAG_SIZE*i )
nyatla 69:8c5f220441f5 40 #define ETH_TX_BUF_BASE ((void*)(ETH_BUF_BASE+ETH_FRAG_SIZE*NUM_RX_FRAG))
nyatla 69:8c5f220441f5 41
nyatla 69:8c5f220441f5 42
nyatla 69:8c5f220441f5 43 #define emacWAIT_FOR_LINK_TO_ESTABLISH_MS 500
nyatla 69:8c5f220441f5 44
nyatla 69:8c5f220441f5 45 ////////////////////////////////////////////////////////////////////////////////
nyatla 69:8c5f220441f5 46 // Ethernet interdface functions
nyatla 69:8c5f220441f5 47 ////////////////////////////////////////////////////////////////////////////////
nyatla 69:8c5f220441f5 48 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param);
nyatla 69:8c5f220441f5 49 static void stop(void);
nyatla 69:8c5f220441f5 50 static void* getRxEthFrame(unsigned short* o_len_of_data);
nyatla 69:8c5f220441f5 51 static void nextRxEthFrame(void);
nyatla 97:6ca5900a2d68 52 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size);
nyatla 92:4f77028cce64 53 static void releaseTxBuf(void* i_buf);
nyatla 92:4f77028cce64 54 static void sendTxEthFrame(void* i_buf,unsigned short i_size);
nyatla 69:8c5f220441f5 55 static void processTx(void);
nyatla 69:8c5f220441f5 56
nyatla 69:8c5f220441f5 57 ////////////////////////////////////////////////////////////////////////////////
nyatla 69:8c5f220441f5 58 // Private
nyatla 69:8c5f220441f5 59 ////////////////////////////////////////////////////////////////////////////////
nyatla 69:8c5f220441f5 60 static void emacIsrHandler(unsigned long i_status);
nyatla 69:8c5f220441f5 61 static unsigned int clockselect(void);
nyatla 69:8c5f220441f5 62 static int ethernet_link(void);
nyatla 69:8c5f220441f5 63 static int phy_write(unsigned int PhyReg, unsigned short Data);
nyatla 69:8c5f220441f5 64 static int phy_read(unsigned int PhyReg);
nyatla 69:8c5f220441f5 65 static void prevTxDescriptor(void);
nyatla 69:8c5f220441f5 66 static void prevRxDescriptor(void);
nyatla 69:8c5f220441f5 67 static NyLPC_TUInt32 waitForTxEthFrameEmpty(void);
nyatla 69:8c5f220441f5 68
nyatla 69:8c5f220441f5 69 /*-----------------------------------------------------------*/
nyatla 69:8c5f220441f5 70
nyatla 69:8c5f220441f5 71
nyatla 69:8c5f220441f5 72 const static struct TiEthernetDevice _interface_LAN8720=
nyatla 69:8c5f220441f5 73 {
nyatla 69:8c5f220441f5 74 "LAN8720",
nyatla 69:8c5f220441f5 75 start,
nyatla 69:8c5f220441f5 76 stop,
nyatla 69:8c5f220441f5 77 getRxEthFrame,
nyatla 69:8c5f220441f5 78 nextRxEthFrame,
nyatla 69:8c5f220441f5 79 allocTxBuf,
nyatla 69:8c5f220441f5 80 releaseTxBuf,
nyatla 69:8c5f220441f5 81 sendTxEthFrame,
nyatla 69:8c5f220441f5 82 processTx
nyatla 69:8c5f220441f5 83 };
nyatla 69:8c5f220441f5 84 const static struct TiEthernetDevice _interface_DP83848C=
nyatla 69:8c5f220441f5 85 {
nyatla 69:8c5f220441f5 86 "DP83848C",
nyatla 69:8c5f220441f5 87 start,
nyatla 69:8c5f220441f5 88 stop,
nyatla 69:8c5f220441f5 89 getRxEthFrame,
nyatla 69:8c5f220441f5 90 nextRxEthFrame,
nyatla 69:8c5f220441f5 91 allocTxBuf,
nyatla 69:8c5f220441f5 92 releaseTxBuf,
nyatla 69:8c5f220441f5 93 sendTxEthFrame,
nyatla 69:8c5f220441f5 94 processTx
nyatla 69:8c5f220441f5 95 };
nyatla 69:8c5f220441f5 96
nyatla 69:8c5f220441f5 97 static void* _event_param;
nyatla 69:8c5f220441f5 98 static NyLPC_TiEthernetDevice_onEvent _event_handler;
nyatla 69:8c5f220441f5 99 static unsigned int phy_id;
nyatla 69:8c5f220441f5 100
nyatla 69:8c5f220441f5 101 /*
nyatla 69:8c5f220441f5 102 * EthernetDeviceのファクトリー関数。インターフェイスを生成できればtrue
nyatla 69:8c5f220441f5 103 *
nyatla 69:8c5f220441f5 104 */
nyatla 69:8c5f220441f5 105 NyLPC_TBool EthDev_LPC4088_getInterface(
nyatla 69:8c5f220441f5 106 const struct TiEthernetDevice** o_dev)
nyatla 69:8c5f220441f5 107 {
nyatla 69:8c5f220441f5 108 int regv, tout;
nyatla 69:8c5f220441f5 109 unsigned int clock = clockselect();
nyatla 69:8c5f220441f5 110
nyatla 69:8c5f220441f5 111 LPC_SC->PCONP |= 0x40000000; /* Power Up the EMAC controller. */
nyatla 69:8c5f220441f5 112 LPC_IOCON->P1_0 &= ~0x07; /* ENET I/O config */
nyatla 69:8c5f220441f5 113 LPC_IOCON->P1_0 |= 0x01; /* ENET_TXD0 */
nyatla 69:8c5f220441f5 114 LPC_IOCON->P1_1 &= ~0x07;
nyatla 69:8c5f220441f5 115 LPC_IOCON->P1_1 |= 0x01; /* ENET_TXD1 */
nyatla 69:8c5f220441f5 116 LPC_IOCON->P1_4 &= ~0x07;
nyatla 69:8c5f220441f5 117 LPC_IOCON->P1_4 |= 0x01; /* ENET_TXEN */
nyatla 69:8c5f220441f5 118 LPC_IOCON->P1_8 &= ~0x07;
nyatla 69:8c5f220441f5 119 LPC_IOCON->P1_8 |= 0x01; /* ENET_CRS */
nyatla 69:8c5f220441f5 120 LPC_IOCON->P1_9 &= ~0x07;
nyatla 69:8c5f220441f5 121 LPC_IOCON->P1_9 |= 0x01; /* ENET_RXD0 */
nyatla 69:8c5f220441f5 122 LPC_IOCON->P1_10 &= ~0x07;
nyatla 69:8c5f220441f5 123 LPC_IOCON->P1_10 |= 0x01; /* ENET_RXD1 */
nyatla 69:8c5f220441f5 124 LPC_IOCON->P1_14 &= ~0x07;
nyatla 69:8c5f220441f5 125 LPC_IOCON->P1_14 |= 0x01; /* ENET_RX_ER */
nyatla 69:8c5f220441f5 126 LPC_IOCON->P1_15 &= ~0x07;
nyatla 69:8c5f220441f5 127 LPC_IOCON->P1_15 |= 0x01; /* ENET_REF_CLK */
nyatla 69:8c5f220441f5 128 LPC_IOCON->P1_16 &= ~0x07; /* ENET/PHY I/O config */
nyatla 69:8c5f220441f5 129 LPC_IOCON->P1_16 |= 0x01; /* ENET_MDC */
nyatla 69:8c5f220441f5 130 LPC_IOCON->P1_17 &= ~0x07;
nyatla 69:8c5f220441f5 131 LPC_IOCON->P1_17 |= 0x01; /* ENET_MDIO */
nyatla 69:8c5f220441f5 132
nyatla 69:8c5f220441f5 133 /* Reset all EMAC internal modules. */
nyatla 69:8c5f220441f5 134 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
nyatla 69:8c5f220441f5 135 LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
nyatla 69:8c5f220441f5 136 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */
nyatla 69:8c5f220441f5 137
nyatla 69:8c5f220441f5 138 /* Initialize MAC control registers. */
nyatla 69:8c5f220441f5 139 LPC_EMAC->MAC1 = MAC1_PASS_ALL;
nyatla 69:8c5f220441f5 140 LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
nyatla 69:8c5f220441f5 141 LPC_EMAC->MAXF = ETH_MAX_FLEN;
nyatla 69:8c5f220441f5 142 LPC_EMAC->CLRT = CLRT_DEF;
nyatla 69:8c5f220441f5 143 LPC_EMAC->IPGR = IPGR_DEF;
nyatla 69:8c5f220441f5 144
nyatla 69:8c5f220441f5 145 /* Enable Reduced MII interface. */
nyatla 69:8c5f220441f5 146 LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; /* Set clock */
nyatla 69:8c5f220441f5 147 LPC_EMAC->MCFG |= MCFG_RES_MII; /* and reset */
nyatla 69:8c5f220441f5 148 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM |CR_PASS_RX_FILT; /* Enable Reduced MII interface. */
nyatla 69:8c5f220441f5 149
nyatla 69:8c5f220441f5 150 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */
nyatla 69:8c5f220441f5 151
nyatla 69:8c5f220441f5 152 LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;
nyatla 69:8c5f220441f5 153 LPC_EMAC->MCMD = 0;
nyatla 69:8c5f220441f5 154 LPC_EMAC->SUPP = SUPP_RES_RMII; /* Reset Reduced MII Logic. */
nyatla 69:8c5f220441f5 155 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */
nyatla 69:8c5f220441f5 156 LPC_EMAC->SUPP = SUPP_SPEED;
nyatla 69:8c5f220441f5 157
nyatla 69:8c5f220441f5 158 phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */
nyatla 69:8c5f220441f5 159 for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */
nyatla 69:8c5f220441f5 160 regv = phy_read(PHY_REG_BMCR);
nyatla 69:8c5f220441f5 161 if(regv < 0 || tout == 0) {
nyatla 69:8c5f220441f5 162 return NyLPC_TBool_FALSE; /* Error */
nyatla 69:8c5f220441f5 163 }
nyatla 69:8c5f220441f5 164 if(!(regv & PHY_BMCR_RESET)) {
nyatla 69:8c5f220441f5 165 break; /* Reset complete. */
nyatla 69:8c5f220441f5 166 }
nyatla 69:8c5f220441f5 167 }
nyatla 69:8c5f220441f5 168
nyatla 69:8c5f220441f5 169 phy_id = (phy_read(PHY_REG_IDR1) << 16);
nyatla 69:8c5f220441f5 170 phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);
nyatla 69:8c5f220441f5 171
nyatla 69:8c5f220441f5 172 switch(phy_id){
nyatla 69:8c5f220441f5 173 case DP83848C_ID:
nyatla 69:8c5f220441f5 174 *o_dev=&_interface_DP83848C;
nyatla 69:8c5f220441f5 175 break;
nyatla 69:8c5f220441f5 176 case LAN8720_ID:
nyatla 69:8c5f220441f5 177 *o_dev=&_interface_LAN8720;
nyatla 69:8c5f220441f5 178 break;
nyatla 69:8c5f220441f5 179 default:
nyatla 69:8c5f220441f5 180 return NyLPC_TBool_FALSE; /* Error */
nyatla 69:8c5f220441f5 181 }
nyatla 69:8c5f220441f5 182 LPC_EMAC->TxProduceIndex = 0;
nyatla 69:8c5f220441f5 183 LPC_EMAC->RxConsumeIndex = 0;
nyatla 69:8c5f220441f5 184 return NyLPC_TBool_TRUE;
nyatla 69:8c5f220441f5 185 }
nyatla 69:8c5f220441f5 186
nyatla 69:8c5f220441f5 187
nyatla 69:8c5f220441f5 188
nyatla 69:8c5f220441f5 189 static NyLPC_TBool start(const struct NyLPC_TEthAddr* i_eth_addr,NyLPC_TiEthernetDevice_onEvent i_handler,void* i_param)
nyatla 69:8c5f220441f5 190 {
nyatla 69:8c5f220441f5 191 int i;
nyatla 69:8c5f220441f5 192 //ISRw割り込み設定
nyatla 69:8c5f220441f5 193 NyLPC_cIsr_setEnetISR(emacIsrHandler);
nyatla 69:8c5f220441f5 194 _event_handler=i_handler;
nyatla 69:8c5f220441f5 195 _event_param=i_param;
nyatla 69:8c5f220441f5 196 /* Set the Ethernet MAC Address registers */
nyatla 69:8c5f220441f5 197 LPC_EMAC->SA0 = (((uint32_t)(i_eth_addr->addr[0])) << 8 ) | i_eth_addr->addr[1];
nyatla 69:8c5f220441f5 198 LPC_EMAC->SA1 = (((uint32_t)(i_eth_addr->addr[2])) << 8 ) | i_eth_addr->addr[3];
nyatla 69:8c5f220441f5 199 LPC_EMAC->SA2 = (((uint32_t)(i_eth_addr->addr[4])) << 8 ) | i_eth_addr->addr[5];
nyatla 69:8c5f220441f5 200
nyatla 69:8c5f220441f5 201 //TXメモリマネージャの準備
nyatla 69:8c5f220441f5 202 NyLPC_cEthernetMM_initialize(ETH_TX_BUF_BASE);
nyatla 69:8c5f220441f5 203 /* Initialize Tx and Rx DMA Descriptors */
nyatla 69:8c5f220441f5 204 prevRxDescriptor();
nyatla 69:8c5f220441f5 205 prevTxDescriptor();
nyatla 69:8c5f220441f5 206 //wait for link up
nyatla 69:8c5f220441f5 207 for(i=0;i<5;i++){
nyatla 69:8c5f220441f5 208 if(ethernet_link()!=0){
nyatla 69:8c5f220441f5 209 break;
nyatla 69:8c5f220441f5 210 }
nyatla 69:8c5f220441f5 211 NyLPC_cThread_sleep(emacWAIT_FOR_LINK_TO_ESTABLISH_MS);
nyatla 69:8c5f220441f5 212 }
nyatla 69:8c5f220441f5 213
nyatla 69:8c5f220441f5 214 //setup Link
nyatla 69:8c5f220441f5 215 ethernet_set_link(-1, 0);
nyatla 69:8c5f220441f5 216
nyatla 69:8c5f220441f5 217 LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
nyatla 69:8c5f220441f5 218 /* Receive Broadcast, Perfect Match Packets */
nyatla 69:8c5f220441f5 219
nyatla 69:8c5f220441f5 220 //Ethernetの割込み開始設定
nyatla 69:8c5f220441f5 221 NyLPC_cIsr_enterCritical();
nyatla 69:8c5f220441f5 222 {
nyatla 69:8c5f220441f5 223 LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE; /* Enable EMAC interrupts. */
nyatla 69:8c5f220441f5 224 LPC_EMAC->IntClear = 0xFFFF; /* Reset all interrupts */
nyatla 69:8c5f220441f5 225
nyatla 69:8c5f220441f5 226 LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); /* Enable receive and transmit mode of MAC Ethernet core */
nyatla 69:8c5f220441f5 227 LPC_EMAC->MAC1 |= MAC1_REC_EN;
nyatla 69:8c5f220441f5 228
nyatla 69:8c5f220441f5 229 NVIC_SetPriority( ENET_IRQn, configEMAC_INTERRUPT_PRIORITY );
nyatla 69:8c5f220441f5 230 NVIC_EnableIRQ( ENET_IRQn );
nyatla 69:8c5f220441f5 231 }
nyatla 69:8c5f220441f5 232 NyLPC_cIsr_exitCritical();
nyatla 69:8c5f220441f5 233
nyatla 69:8c5f220441f5 234 return NyLPC_TBool_TRUE;
nyatla 69:8c5f220441f5 235 }
nyatla 69:8c5f220441f5 236
nyatla 69:8c5f220441f5 237
nyatla 69:8c5f220441f5 238 static void stop(void)
nyatla 69:8c5f220441f5 239 {
nyatla 69:8c5f220441f5 240 NyLPC_cIsr_enterCritical();
nyatla 69:8c5f220441f5 241 {
nyatla 69:8c5f220441f5 242 LPC_EMAC->IntEnable &= ~(INT_RX_DONE | INT_TX_DONE);
nyatla 69:8c5f220441f5 243 LPC_EMAC->IntClear = 0xFFFF;
nyatla 69:8c5f220441f5 244
nyatla 69:8c5f220441f5 245 NVIC_DisableIRQ( ENET_IRQn );
nyatla 69:8c5f220441f5 246 }
nyatla 69:8c5f220441f5 247 NyLPC_cIsr_exitCritical();
nyatla 69:8c5f220441f5 248 LPC_EMAC->Command &= ~( CR_RX_EN | CR_TX_EN );
nyatla 69:8c5f220441f5 249 LPC_EMAC->MAC1 &= ~MAC1_REC_EN;
nyatla 69:8c5f220441f5 250 //ISR割り込み解除
nyatla 69:8c5f220441f5 251 NyLPC_cIsr_setEnetISR(NULL);
nyatla 69:8c5f220441f5 252 //TXメモリマネージャの終了
nyatla 69:8c5f220441f5 253 NyLPC_cEthernetMM_finalize();
nyatla 69:8c5f220441f5 254 }
nyatla 69:8c5f220441f5 255
nyatla 92:4f77028cce64 256 static void* allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)
nyatla 69:8c5f220441f5 257 {
nyatla 69:8c5f220441f5 258 return NyLPC_cEthernetMM_alloc(i_hint,o_size);
nyatla 69:8c5f220441f5 259 }
nyatla 92:4f77028cce64 260 static void releaseTxBuf(void* i_buf)
nyatla 69:8c5f220441f5 261 {
nyatla 69:8c5f220441f5 262 NyLPC_cEthernetMM_release(i_buf);
nyatla 69:8c5f220441f5 263 }
nyatla 69:8c5f220441f5 264
nyatla 69:8c5f220441f5 265
nyatla 69:8c5f220441f5 266 /**
nyatla 69:8c5f220441f5 267 */
nyatla 69:8c5f220441f5 268 static void processTx(void)
nyatla 69:8c5f220441f5 269 {
nyatla 69:8c5f220441f5 270 waitForTxEthFrameEmpty();
nyatla 69:8c5f220441f5 271 }
nyatla 69:8c5f220441f5 272
nyatla 69:8c5f220441f5 273
nyatla 69:8c5f220441f5 274
nyatla 69:8c5f220441f5 275 /**
nyatla 69:8c5f220441f5 276 * Ethernetパケットを送信します。
nyatla 92:4f77028cce64 277 * allocTxBufで得たバッファを指定すること。
nyatla 69:8c5f220441f5 278 * <p>関数仕様</p>
nyatla 69:8c5f220441f5 279 * この関数は、i_bufが
nyatla 69:8c5f220441f5 280 * </div>
nyatla 69:8c5f220441f5 281 */
nyatla 92:4f77028cce64 282 static void sendTxEthFrame(void* i_buf,unsigned short i_size)
nyatla 69:8c5f220441f5 283 {
nyatla 69:8c5f220441f5 284 NyLPC_TUInt32 IndexNext,Index;
nyatla 92:4f77028cce64 285 struct NyLPC_TTxBufferHeader* bh=NyLPC_TTxBufferHeader_getBufferHeaderAddr(i_buf);
nyatla 69:8c5f220441f5 286
nyatla 69:8c5f220441f5 287 //サイズ0なら送信の必要なし
nyatla 69:8c5f220441f5 288 if(i_size == 0)
nyatla 69:8c5f220441f5 289 {
nyatla 69:8c5f220441f5 290 return;
nyatla 69:8c5f220441f5 291 }
nyatla 69:8c5f220441f5 292 //送信デスクリプタの反映
nyatla 69:8c5f220441f5 293 IndexNext =waitForTxEthFrameEmpty();
nyatla 69:8c5f220441f5 294
nyatla 69:8c5f220441f5 295 //送信対象のメモリブロックを送信中に設定。
nyatla 69:8c5f220441f5 296 // b=(i_buf+1);
nyatla 69:8c5f220441f5 297 //送信中のメモリブロックなら無視
nyatla 92:4f77028cce64 298 if(bh->is_lock){
nyatla 69:8c5f220441f5 299 return;
nyatla 69:8c5f220441f5 300 }
nyatla 69:8c5f220441f5 301 //送信中にセット
nyatla 92:4f77028cce64 302 bh->is_lock=NyLPC_TUInt8_TRUE;
nyatla 69:8c5f220441f5 303
nyatla 69:8c5f220441f5 304 //送信データのセット
nyatla 69:8c5f220441f5 305 Index = LPC_EMAC->TxProduceIndex;
nyatla 69:8c5f220441f5 306 if (i_size > ETH_FRAG_SIZE){
nyatla 69:8c5f220441f5 307 i_size = ETH_FRAG_SIZE;
nyatla 69:8c5f220441f5 308 }
nyatla 69:8c5f220441f5 309 //送信処理
nyatla 92:4f77028cce64 310 TX_DESC_PACKET( Index ) = ( unsigned long )i_buf;
nyatla 69:8c5f220441f5 311 //See UM10360.pdf Table 181. Transmit descriptor control word
nyatla 69:8c5f220441f5 312 TX_DESC_CTRL( Index ) = ((i_size-1) | TCTRL_LAST | TCTRL_INT );
nyatla 69:8c5f220441f5 313 LPC_EMAC->TxProduceIndex = IndexNext;
nyatla 69:8c5f220441f5 314 return;
nyatla 69:8c5f220441f5 315 }
nyatla 69:8c5f220441f5 316 /**
nyatla 69:8c5f220441f5 317 * 送信デスクリプタを準備します。
nyatla 69:8c5f220441f5 318 */
nyatla 69:8c5f220441f5 319 static void prevTxDescriptor(void)
nyatla 69:8c5f220441f5 320 {
nyatla 69:8c5f220441f5 321 long x;
nyatla 69:8c5f220441f5 322 //デスクリプタの設定
nyatla 69:8c5f220441f5 323 for( x = 0; x < NUM_TX_FRAG; x++ )
nyatla 69:8c5f220441f5 324 {
nyatla 69:8c5f220441f5 325 TX_DESC_PACKET( x ) = ( unsigned long ) NULL;
nyatla 69:8c5f220441f5 326 TX_DESC_CTRL( x ) = 0;
nyatla 69:8c5f220441f5 327 TX_STAT_INFO( x ) = 0;
nyatla 69:8c5f220441f5 328 }
nyatla 69:8c5f220441f5 329 /* Set LPC_EMAC Transmit Descriptor Registers. */
nyatla 69:8c5f220441f5 330 LPC_EMAC->TxDescriptor =TX_DESC_BASE;
nyatla 69:8c5f220441f5 331 LPC_EMAC->TxStatus = TX_STAT_BASE;
nyatla 69:8c5f220441f5 332 LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1;
nyatla 69:8c5f220441f5 333 }
nyatla 69:8c5f220441f5 334 static void prevRxDescriptor(void)
nyatla 69:8c5f220441f5 335 {
nyatla 69:8c5f220441f5 336 int x;
nyatla 69:8c5f220441f5 337 //デスクリプタの設定
nyatla 69:8c5f220441f5 338 for( x = 0; x < NUM_RX_FRAG; x++ )
nyatla 69:8c5f220441f5 339 {
nyatla 69:8c5f220441f5 340 /* Allocate the next Ethernet buffer to this descriptor. */
nyatla 69:8c5f220441f5 341 RX_DESC_PACKET(x) = ETH_BUF(x);
nyatla 69:8c5f220441f5 342 RX_DESC_CTRL(x) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 );
nyatla 69:8c5f220441f5 343 RX_STAT_INFO(x) = 0;
nyatla 69:8c5f220441f5 344 RX_STAT_HASHCRC(x) = 0;
nyatla 69:8c5f220441f5 345 }
nyatla 69:8c5f220441f5 346
nyatla 69:8c5f220441f5 347 /* Set LPC_EMAC Receive Descriptor Registers. */
nyatla 69:8c5f220441f5 348 LPC_EMAC->RxDescriptor = RX_DESC_BASE;
nyatla 69:8c5f220441f5 349 LPC_EMAC->RxStatus = RX_STAT_BASE;
nyatla 69:8c5f220441f5 350 LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1;
nyatla 69:8c5f220441f5 351
nyatla 69:8c5f220441f5 352 }
nyatla 69:8c5f220441f5 353
nyatla 69:8c5f220441f5 354
nyatla 69:8c5f220441f5 355 /**
nyatla 69:8c5f220441f5 356 * 受信キューの先頭にあるRXフレームのポインタを返します。
nyatla 69:8c5f220441f5 357 * 関数は、受信キューのポインタを操作しません。続けて読み出したとしても、同じポインターを返します。
nyatla 69:8c5f220441f5 358 * 制限として、返却したポインタの内容は、一時的に書き換え可としてください。(この制限は将来削除します。)
nyatla 69:8c5f220441f5 359 * @return
nyatla 69:8c5f220441f5 360 * 成功した場合、受信データを格納したバッファポインターです。
nyatla 69:8c5f220441f5 361 * 次回nextRxEthFrameを呼び出すまで有効です。
nyatla 69:8c5f220441f5 362 */
nyatla 69:8c5f220441f5 363 static void* getRxEthFrame(unsigned short* o_len_of_data)
nyatla 69:8c5f220441f5 364 {
nyatla 69:8c5f220441f5 365 if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )
nyatla 69:8c5f220441f5 366 {
nyatla 69:8c5f220441f5 367 //受信データを返却する。
nyatla 69:8c5f220441f5 368 *o_len_of_data = (unsigned short)(( RX_STAT_INFO( LPC_EMAC->RxConsumeIndex ) & RINFO_SIZE ) - 3);
nyatla 69:8c5f220441f5 369 return ( unsigned char * ) RX_DESC_PACKET( LPC_EMAC->RxConsumeIndex );
nyatla 69:8c5f220441f5 370 }
nyatla 69:8c5f220441f5 371 return NULL;
nyatla 69:8c5f220441f5 372 }
nyatla 69:8c5f220441f5 373
nyatla 69:8c5f220441f5 374
nyatla 69:8c5f220441f5 375 /**
nyatla 69:8c5f220441f5 376 * 受信キューを進行します。
nyatla 69:8c5f220441f5 377 */
nyatla 69:8c5f220441f5 378 static void nextRxEthFrame(void)
nyatla 69:8c5f220441f5 379 {
nyatla 69:8c5f220441f5 380 long lIndex;
nyatla 69:8c5f220441f5 381 if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )
nyatla 69:8c5f220441f5 382 {
nyatla 69:8c5f220441f5 383 //キューすすめる。
nyatla 69:8c5f220441f5 384 lIndex = LPC_EMAC->RxConsumeIndex;
nyatla 69:8c5f220441f5 385 lIndex++;
nyatla 69:8c5f220441f5 386 if( lIndex >= NUM_RX_FRAG )
nyatla 69:8c5f220441f5 387 {
nyatla 69:8c5f220441f5 388 lIndex = 0;
nyatla 69:8c5f220441f5 389 }
nyatla 69:8c5f220441f5 390 LPC_EMAC->RxConsumeIndex = lIndex;
nyatla 69:8c5f220441f5 391 }
nyatla 69:8c5f220441f5 392 }
nyatla 69:8c5f220441f5 393 /********************************************************************************
nyatla 69:8c5f220441f5 394 * Private functions
nyatla 69:8c5f220441f5 395 *******************************************************************************/
nyatla 69:8c5f220441f5 396
nyatla 69:8c5f220441f5 397
nyatla 69:8c5f220441f5 398
nyatla 69:8c5f220441f5 399 /**
nyatla 69:8c5f220441f5 400 * 送信中のイーサフレームを処理する機会を与えて、送信キューが空くまで待ちます。
nyatla 69:8c5f220441f5 401 * LPC1769の場合は、非同期に更新したディスクリプタの内容から、送信メモリのフラグを更新します。
nyatla 69:8c5f220441f5 402 * @return
nyatla 69:8c5f220441f5 403 * 次に書き込むことが出来る送信キュー。
nyatla 69:8c5f220441f5 404 */
nyatla 69:8c5f220441f5 405 static NyLPC_TUInt32 waitForTxEthFrameEmpty(void)
nyatla 69:8c5f220441f5 406 {
nyatla 69:8c5f220441f5 407 NyLPC_TUInt32 IndexNext;
nyatla 69:8c5f220441f5 408 struct NyLPC_TTxBufferHeader *b;
nyatla 69:8c5f220441f5 409 void* p;
nyatla 69:8c5f220441f5 410 NyLPC_TUInt32 i;
nyatla 69:8c5f220441f5 411
nyatla 69:8c5f220441f5 412 //送信キューの決定
nyatla 69:8c5f220441f5 413 IndexNext = (LPC_EMAC->TxProduceIndex + 1)%NUM_TX_FRAG;
nyatla 69:8c5f220441f5 414
nyatla 69:8c5f220441f5 415 //送信キューフルが解除されるまで待ち
nyatla 69:8c5f220441f5 416 while(IndexNext == LPC_EMAC->TxConsumeIndex)
nyatla 69:8c5f220441f5 417 {
nyatla 69:8c5f220441f5 418 //
nyatla 69:8c5f220441f5 419 NyLPC_cThread_sleep(emacSHORT_DELAY_MS);
nyatla 69:8c5f220441f5 420 }
nyatla 69:8c5f220441f5 421
nyatla 69:8c5f220441f5 422 //(TxProduceIndex+1)→TxConsumeIndexにあるデータのsentフラグを消去
nyatla 69:8c5f220441f5 423 for(i=IndexNext;i!=LPC_EMAC->TxConsumeIndex;i=(i+1)%NUM_TX_FRAG)
nyatla 69:8c5f220441f5 424 {
nyatla 69:8c5f220441f5 425 p=(void*)TX_DESC_PACKET(i);
nyatla 69:8c5f220441f5 426 if(p!=NULL){
nyatla 92:4f77028cce64 427 b=NyLPC_TTxBufferHeader_getBufferHeaderAddr(p);
nyatla 69:8c5f220441f5 428 b->is_lock=NyLPC_TUInt8_FALSE;
nyatla 69:8c5f220441f5 429 TX_DESC_PACKET(i)=0;
nyatla 69:8c5f220441f5 430 }
nyatla 69:8c5f220441f5 431 }
nyatla 69:8c5f220441f5 432 p=(void*)TX_DESC_PACKET(i);
nyatla 69:8c5f220441f5 433 if(p!=NULL){
nyatla 92:4f77028cce64 434 b=NyLPC_TTxBufferHeader_getBufferHeaderAddr(p);
nyatla 69:8c5f220441f5 435 b->is_lock=NyLPC_TUInt8_FALSE;
nyatla 69:8c5f220441f5 436 TX_DESC_PACKET(i)=0;
nyatla 69:8c5f220441f5 437 }
nyatla 69:8c5f220441f5 438 return IndexNext;
nyatla 69:8c5f220441f5 439 }
nyatla 69:8c5f220441f5 440
nyatla 69:8c5f220441f5 441 //--------------------------------------------------------------------------------
nyatla 69:8c5f220441f5 442 // ISR
nyatla 69:8c5f220441f5 443 //--------------------------------------------------------------------------------
nyatla 69:8c5f220441f5 444
nyatla 69:8c5f220441f5 445 static void ethernet_set_link(int speed, int duplex) {
nyatla 69:8c5f220441f5 446 unsigned short phy_data;
nyatla 69:8c5f220441f5 447 int tout;
nyatla 69:8c5f220441f5 448
nyatla 69:8c5f220441f5 449 if((speed < 0) || (speed > 1)) {
nyatla 69:8c5f220441f5 450 phy_data = PHY_AUTO_NEG;
nyatla 69:8c5f220441f5 451 } else {
nyatla 69:8c5f220441f5 452 phy_data = (((unsigned short) speed << 13) |
nyatla 69:8c5f220441f5 453 ((unsigned short) duplex << 8));
nyatla 69:8c5f220441f5 454 }
nyatla 69:8c5f220441f5 455
nyatla 69:8c5f220441f5 456 phy_write(PHY_REG_BMCR, phy_data);
nyatla 69:8c5f220441f5 457
nyatla 69:8c5f220441f5 458 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */
nyatla 69:8c5f220441f5 459
nyatla 69:8c5f220441f5 460 switch(phy_id) {
nyatla 69:8c5f220441f5 461 case DP83848C_ID:
nyatla 69:8c5f220441f5 462 phy_data = phy_read(PHY_REG_STS);
nyatla 69:8c5f220441f5 463
nyatla 69:8c5f220441f5 464 if(phy_data & PHY_STS_DUPLEX) {
nyatla 69:8c5f220441f5 465 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
nyatla 69:8c5f220441f5 466 LPC_EMAC->Command |= CR_FULL_DUP;
nyatla 69:8c5f220441f5 467 LPC_EMAC->IPGT = IPGT_FULL_DUP;
nyatla 69:8c5f220441f5 468 } else {
nyatla 69:8c5f220441f5 469 LPC_EMAC->MAC2 &= ~MAC2_FULL_DUP;
nyatla 69:8c5f220441f5 470 LPC_EMAC->Command &= ~CR_FULL_DUP;
nyatla 69:8c5f220441f5 471 LPC_EMAC->IPGT = IPGT_HALF_DUP;
nyatla 69:8c5f220441f5 472 }
nyatla 69:8c5f220441f5 473
nyatla 69:8c5f220441f5 474 if(phy_data & PHY_STS_SPEED) {
nyatla 69:8c5f220441f5 475 LPC_EMAC->SUPP &= ~SUPP_SPEED;
nyatla 69:8c5f220441f5 476 } else {
nyatla 69:8c5f220441f5 477 LPC_EMAC->SUPP |= SUPP_SPEED;
nyatla 69:8c5f220441f5 478 }
nyatla 69:8c5f220441f5 479 break;
nyatla 69:8c5f220441f5 480
nyatla 69:8c5f220441f5 481 case LAN8720_ID:
nyatla 69:8c5f220441f5 482 phy_data = phy_read(PHY_REG_SCSR);
nyatla 69:8c5f220441f5 483
nyatla 69:8c5f220441f5 484 if (phy_data & PHY_SCSR_DUPLEX) {
nyatla 69:8c5f220441f5 485 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
nyatla 69:8c5f220441f5 486 LPC_EMAC->Command |= CR_FULL_DUP;
nyatla 69:8c5f220441f5 487 LPC_EMAC->IPGT = IPGT_FULL_DUP;
nyatla 69:8c5f220441f5 488 } else {
nyatla 69:8c5f220441f5 489 LPC_EMAC->Command &= ~CR_FULL_DUP;
nyatla 69:8c5f220441f5 490 LPC_EMAC->IPGT = IPGT_HALF_DUP;
nyatla 69:8c5f220441f5 491 }
nyatla 69:8c5f220441f5 492
nyatla 69:8c5f220441f5 493 if(phy_data & PHY_SCSR_100MBIT) {
nyatla 69:8c5f220441f5 494 LPC_EMAC->SUPP |= SUPP_SPEED;
nyatla 69:8c5f220441f5 495 } else {
nyatla 69:8c5f220441f5 496 LPC_EMAC->SUPP &= ~SUPP_SPEED;
nyatla 69:8c5f220441f5 497 }
nyatla 69:8c5f220441f5 498
nyatla 69:8c5f220441f5 499 break;
nyatla 69:8c5f220441f5 500 }
nyatla 69:8c5f220441f5 501 }
nyatla 69:8c5f220441f5 502
nyatla 69:8c5f220441f5 503 static int phy_write(unsigned int PhyReg, unsigned short Data) {
nyatla 69:8c5f220441f5 504 unsigned int timeOut;
nyatla 69:8c5f220441f5 505
nyatla 69:8c5f220441f5 506 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
nyatla 69:8c5f220441f5 507 LPC_EMAC->MWTD = Data;
nyatla 69:8c5f220441f5 508
nyatla 69:8c5f220441f5 509 for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) { /* Wait until operation completed */
nyatla 69:8c5f220441f5 510 if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
nyatla 69:8c5f220441f5 511 return 0;
nyatla 69:8c5f220441f5 512 }
nyatla 69:8c5f220441f5 513 }
nyatla 69:8c5f220441f5 514
nyatla 69:8c5f220441f5 515 return -1;
nyatla 69:8c5f220441f5 516 }
nyatla 69:8c5f220441f5 517
nyatla 69:8c5f220441f5 518
nyatla 69:8c5f220441f5 519 static int phy_read(unsigned int PhyReg) {
nyatla 69:8c5f220441f5 520 unsigned int timeOut;
nyatla 69:8c5f220441f5 521
nyatla 69:8c5f220441f5 522 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
nyatla 69:8c5f220441f5 523 LPC_EMAC->MCMD = MCMD_READ;
nyatla 69:8c5f220441f5 524
nyatla 69:8c5f220441f5 525 for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */
nyatla 69:8c5f220441f5 526 if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
nyatla 69:8c5f220441f5 527 LPC_EMAC->MCMD = 0;
nyatla 69:8c5f220441f5 528 return LPC_EMAC->MRDD; /* Return a 16-bit value. */
nyatla 69:8c5f220441f5 529 }
nyatla 69:8c5f220441f5 530 }
nyatla 69:8c5f220441f5 531
nyatla 69:8c5f220441f5 532 return -1;
nyatla 69:8c5f220441f5 533 }
nyatla 69:8c5f220441f5 534
nyatla 69:8c5f220441f5 535
nyatla 69:8c5f220441f5 536 //extern unsigned int SystemFrequency;
nyatla 69:8c5f220441f5 537 static unsigned int clockselect(void)
nyatla 69:8c5f220441f5 538 {
nyatla 69:8c5f220441f5 539 if(SystemCoreClock < 10000000) {
nyatla 69:8c5f220441f5 540 return 1;
nyatla 69:8c5f220441f5 541 } else if(SystemCoreClock < 15000000) {
nyatla 69:8c5f220441f5 542 return 2;
nyatla 69:8c5f220441f5 543 } else if(SystemCoreClock < 20000000) {
nyatla 69:8c5f220441f5 544 return 3;
nyatla 69:8c5f220441f5 545 } else if(SystemCoreClock < 25000000) {
nyatla 69:8c5f220441f5 546 return 4;
nyatla 69:8c5f220441f5 547 } else if(SystemCoreClock < 35000000) {
nyatla 69:8c5f220441f5 548 return 5;
nyatla 69:8c5f220441f5 549 } else if(SystemCoreClock < 50000000) {
nyatla 69:8c5f220441f5 550 return 6;
nyatla 69:8c5f220441f5 551 } else if(SystemCoreClock < 70000000) {
nyatla 69:8c5f220441f5 552 return 7;
nyatla 69:8c5f220441f5 553 } else if(SystemCoreClock < 80000000) {
nyatla 69:8c5f220441f5 554 return 8;
nyatla 69:8c5f220441f5 555 } else if(SystemCoreClock < 90000000) {
nyatla 69:8c5f220441f5 556 return 9;
nyatla 69:8c5f220441f5 557 } else if(SystemCoreClock < 100000000) {
nyatla 69:8c5f220441f5 558 return 10;
nyatla 69:8c5f220441f5 559 } else if(SystemCoreClock < 120000000) {
nyatla 69:8c5f220441f5 560 return 11;
nyatla 69:8c5f220441f5 561 } else if(SystemCoreClock < 130000000) {
nyatla 69:8c5f220441f5 562 return 12;
nyatla 69:8c5f220441f5 563 } else if(SystemCoreClock < 140000000) {
nyatla 69:8c5f220441f5 564 return 13;
nyatla 69:8c5f220441f5 565 } else if(SystemCoreClock < 150000000) {
nyatla 69:8c5f220441f5 566 return 15;
nyatla 69:8c5f220441f5 567 } else if(SystemCoreClock < 160000000) {
nyatla 69:8c5f220441f5 568 return 16;
nyatla 69:8c5f220441f5 569 } else {
nyatla 69:8c5f220441f5 570 return 0;
nyatla 69:8c5f220441f5 571 }
nyatla 69:8c5f220441f5 572 }
nyatla 69:8c5f220441f5 573
nyatla 69:8c5f220441f5 574 static int ethernet_link(void)
nyatla 69:8c5f220441f5 575 {
nyatla 69:8c5f220441f5 576
nyatla 69:8c5f220441f5 577 if (phy_id == DP83848C_ID) {
nyatla 69:8c5f220441f5 578 return (phy_read(PHY_REG_STS) & PHY_STS_LINK);
nyatla 69:8c5f220441f5 579 }
nyatla 69:8c5f220441f5 580 else { // LAN8720_ID
nyatla 69:8c5f220441f5 581 return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);
nyatla 69:8c5f220441f5 582 }
nyatla 69:8c5f220441f5 583 }
nyatla 69:8c5f220441f5 584 //--------------------------------------------------------------------------------
nyatla 69:8c5f220441f5 585 // ISR
nyatla 69:8c5f220441f5 586 //--------------------------------------------------------------------------------
nyatla 69:8c5f220441f5 587
nyatla 69:8c5f220441f5 588
nyatla 69:8c5f220441f5 589 /**
nyatla 69:8c5f220441f5 590 * EMACからのハンドラ
nyatla 69:8c5f220441f5 591 */
nyatla 69:8c5f220441f5 592 static void emacIsrHandler(unsigned long i_status)
nyatla 69:8c5f220441f5 593 {
nyatla 69:8c5f220441f5 594 if( i_status & INT_RX_DONE )
nyatla 69:8c5f220441f5 595 {
nyatla 69:8c5f220441f5 596 _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_RX);
nyatla 69:8c5f220441f5 597 }
nyatla 69:8c5f220441f5 598 if( i_status & INT_TX_DONE )
nyatla 69:8c5f220441f5 599 {
nyatla 69:8c5f220441f5 600 _event_handler(_event_param,NyLPC_TiEthernetDevice_EVENT_ON_TX);
nyatla 69:8c5f220441f5 601 }
nyatla 69:8c5f220441f5 602 }
nyatla 69:8c5f220441f5 603
nyatla 69:8c5f220441f5 604 #endif
nyatla 69:8c5f220441f5 605
nyatla 69:8c5f220441f5 606
nyatla 69:8c5f220441f5 607