mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Tue Dec 16 08:15:08 2014 +0000
Revision:
440:8a0b45cd594f
Parent:
285:31249416b6f9
Synchronized with git revision 67fbbf0b635d0c0d93fbe433306c537c2ad206aa

Full URL: https://github.com/mbedmicro/mbed/commit/67fbbf0b635d0c0d93fbe433306c537c2ad206aa/

Targets: nrf51 - updating app_timer.c from Norid'c SDKv7.1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emilmont 10:3bc89ef62ce7 1 /* mbed Microcontroller Library
emilmont 10:3bc89ef62ce7 2 * Copyright (c) 2006-2013 ARM Limited
emilmont 10:3bc89ef62ce7 3 *
emilmont 10:3bc89ef62ce7 4 * Licensed under the Apache License, Version 2.0 (the "License");
emilmont 10:3bc89ef62ce7 5 * you may not use this file except in compliance with the License.
emilmont 10:3bc89ef62ce7 6 * You may obtain a copy of the License at
emilmont 10:3bc89ef62ce7 7 *
emilmont 10:3bc89ef62ce7 8 * http://www.apache.org/licenses/LICENSE-2.0
emilmont 10:3bc89ef62ce7 9 *
emilmont 10:3bc89ef62ce7 10 * Unless required by applicable law or agreed to in writing, software
emilmont 10:3bc89ef62ce7 11 * distributed under the License is distributed on an "AS IS" BASIS,
emilmont 10:3bc89ef62ce7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
emilmont 10:3bc89ef62ce7 13 * See the License for the specific language governing permissions and
emilmont 10:3bc89ef62ce7 14 * limitations under the License.
emilmont 10:3bc89ef62ce7 15 */
emilmont 10:3bc89ef62ce7 16 #include "ethernet_api.h"
emilmont 10:3bc89ef62ce7 17
emilmont 10:3bc89ef62ce7 18 #include <string.h>
emilmont 10:3bc89ef62ce7 19 #include "cmsis.h"
emilmont 10:3bc89ef62ce7 20 #include "mbed_interface.h"
emilmont 10:3bc89ef62ce7 21 #include "toolchain.h"
mbed_official 285:31249416b6f9 22 #include "mbed_error.h"
emilmont 10:3bc89ef62ce7 23
emilmont 10:3bc89ef62ce7 24 #define NEW_LOGIC 0
emilmont 10:3bc89ef62ce7 25 #define NEW_ETH_BUFFER 0
emilmont 10:3bc89ef62ce7 26
emilmont 10:3bc89ef62ce7 27 #if NEW_ETH_BUFFER
emilmont 10:3bc89ef62ce7 28
emilmont 10:3bc89ef62ce7 29 #define NUM_RX_FRAG 4 // Number of Rx Fragments (== packets)
emilmont 10:3bc89ef62ce7 30 #define NUM_TX_FRAG 3 // Number of Tx Fragments (== packets)
emilmont 10:3bc89ef62ce7 31
emilmont 10:3bc89ef62ce7 32 #define ETH_MAX_FLEN 1536 // Maximum Ethernet Frame Size
emilmont 10:3bc89ef62ce7 33 #define ETH_FRAG_SIZE ETH_MAX_FLEN // Packet Fragment size (same as packet length)
emilmont 10:3bc89ef62ce7 34
emilmont 10:3bc89ef62ce7 35 #else
emilmont 10:3bc89ef62ce7 36
emilmont 10:3bc89ef62ce7 37 // Memfree calculation:
emilmont 10:3bc89ef62ce7 38 // (16 * 1024) - ((2 * 4 * NUM_RX) + (2 * 4 * NUM_RX) + (0x300 * NUM_RX) +
emilmont 10:3bc89ef62ce7 39 // (2 * 4 * NUM_TX) + (1 * 4 * NUM_TX) + (0x300 * NUM_TX)) = 8556
emilmont 10:3bc89ef62ce7 40 /* EMAC Memory Buffer configuration for 16K Ethernet RAM. */
emilmont 10:3bc89ef62ce7 41 #define NUM_RX_FRAG 4 /* Num.of RX Fragments 4*1536= 6.0kB */
emilmont 10:3bc89ef62ce7 42 #define NUM_TX_FRAG 3 /* Num.of TX Fragments 3*1536= 4.6kB */
emilmont 10:3bc89ef62ce7 43 //#define ETH_FRAG_SIZE 1536 /* Packet Fragment size 1536 Bytes */
emilmont 10:3bc89ef62ce7 44
emilmont 10:3bc89ef62ce7 45 //#define ETH_MAX_FLEN 1536 /* Max. Ethernet Frame Size */
emilmont 10:3bc89ef62ce7 46 #define ETH_FRAG_SIZE 0x300 /* Packet Fragment size 1536/2 Bytes */
emilmont 10:3bc89ef62ce7 47 #define ETH_MAX_FLEN 0x300 /* Max. Ethernet Frame Size */
emilmont 10:3bc89ef62ce7 48
emilmont 10:3bc89ef62ce7 49 const int ethernet_MTU_SIZE = 0x300;
emilmont 10:3bc89ef62ce7 50
emilmont 10:3bc89ef62ce7 51 #endif
emilmont 10:3bc89ef62ce7 52
emilmont 10:3bc89ef62ce7 53 #define ETHERNET_ADDR_SIZE 6
emilmont 10:3bc89ef62ce7 54
mbed_official 212:34d62c0b2af6 55 struct RX_DESC_TypeDef { /* RX Descriptor struct */
emilmont 10:3bc89ef62ce7 56 unsigned int Packet;
emilmont 10:3bc89ef62ce7 57 unsigned int Ctrl;
mbed_official 212:34d62c0b2af6 58 } PACKED;
emilmont 10:3bc89ef62ce7 59 typedef struct RX_DESC_TypeDef RX_DESC_TypeDef;
emilmont 10:3bc89ef62ce7 60
mbed_official 212:34d62c0b2af6 61 struct RX_STAT_TypeDef { /* RX Status struct */
emilmont 10:3bc89ef62ce7 62 unsigned int Info;
emilmont 10:3bc89ef62ce7 63 unsigned int HashCRC;
mbed_official 212:34d62c0b2af6 64 } PACKED;
emilmont 10:3bc89ef62ce7 65 typedef struct RX_STAT_TypeDef RX_STAT_TypeDef;
emilmont 10:3bc89ef62ce7 66
mbed_official 212:34d62c0b2af6 67 struct TX_DESC_TypeDef { /* TX Descriptor struct */
emilmont 10:3bc89ef62ce7 68 unsigned int Packet;
emilmont 10:3bc89ef62ce7 69 unsigned int Ctrl;
mbed_official 212:34d62c0b2af6 70 } PACKED;
emilmont 10:3bc89ef62ce7 71 typedef struct TX_DESC_TypeDef TX_DESC_TypeDef;
emilmont 10:3bc89ef62ce7 72
mbed_official 212:34d62c0b2af6 73 struct TX_STAT_TypeDef { /* TX Status struct */
emilmont 10:3bc89ef62ce7 74 unsigned int Info;
mbed_official 212:34d62c0b2af6 75 } PACKED;
emilmont 10:3bc89ef62ce7 76 typedef struct TX_STAT_TypeDef TX_STAT_TypeDef;
emilmont 10:3bc89ef62ce7 77
emilmont 10:3bc89ef62ce7 78 /* MAC Configuration Register 1 */
emilmont 10:3bc89ef62ce7 79 #define MAC1_REC_EN 0x00000001 /* Receive Enable */
emilmont 10:3bc89ef62ce7 80 #define MAC1_PASS_ALL 0x00000002 /* Pass All Receive Frames */
emilmont 10:3bc89ef62ce7 81 #define MAC1_RX_FLOWC 0x00000004 /* RX Flow Control */
emilmont 10:3bc89ef62ce7 82 #define MAC1_TX_FLOWC 0x00000008 /* TX Flow Control */
emilmont 10:3bc89ef62ce7 83 #define MAC1_LOOPB 0x00000010 /* Loop Back Mode */
emilmont 10:3bc89ef62ce7 84 #define MAC1_RES_TX 0x00000100 /* Reset TX Logic */
emilmont 10:3bc89ef62ce7 85 #define MAC1_RES_MCS_TX 0x00000200 /* Reset MAC TX Control Sublayer */
emilmont 10:3bc89ef62ce7 86 #define MAC1_RES_RX 0x00000400 /* Reset RX Logic */
emilmont 10:3bc89ef62ce7 87 #define MAC1_RES_MCS_RX 0x00000800 /* Reset MAC RX Control Sublayer */
emilmont 10:3bc89ef62ce7 88 #define MAC1_SIM_RES 0x00004000 /* Simulation Reset */
emilmont 10:3bc89ef62ce7 89 #define MAC1_SOFT_RES 0x00008000 /* Soft Reset MAC */
emilmont 10:3bc89ef62ce7 90
emilmont 10:3bc89ef62ce7 91 /* MAC Configuration Register 2 */
emilmont 10:3bc89ef62ce7 92 #define MAC2_FULL_DUP 0x00000001 /* Full Duplex Mode */
emilmont 10:3bc89ef62ce7 93 #define MAC2_FRM_LEN_CHK 0x00000002 /* Frame Length Checking */
emilmont 10:3bc89ef62ce7 94 #define MAC2_HUGE_FRM_EN 0x00000004 /* Huge Frame Enable */
emilmont 10:3bc89ef62ce7 95 #define MAC2_DLY_CRC 0x00000008 /* Delayed CRC Mode */
emilmont 10:3bc89ef62ce7 96 #define MAC2_CRC_EN 0x00000010 /* Append CRC to every Frame */
emilmont 10:3bc89ef62ce7 97 #define MAC2_PAD_EN 0x00000020 /* Pad all Short Frames */
emilmont 10:3bc89ef62ce7 98 #define MAC2_VLAN_PAD_EN 0x00000040 /* VLAN Pad Enable */
emilmont 10:3bc89ef62ce7 99 #define MAC2_ADET_PAD_EN 0x00000080 /* Auto Detect Pad Enable */
emilmont 10:3bc89ef62ce7 100 #define MAC2_PPREAM_ENF 0x00000100 /* Pure Preamble Enforcement */
emilmont 10:3bc89ef62ce7 101 #define MAC2_LPREAM_ENF 0x00000200 /* Long Preamble Enforcement */
emilmont 10:3bc89ef62ce7 102 #define MAC2_NO_BACKOFF 0x00001000 /* No Backoff Algorithm */
emilmont 10:3bc89ef62ce7 103 #define MAC2_BACK_PRESSURE 0x00002000 /* Backoff Presurre / No Backoff */
emilmont 10:3bc89ef62ce7 104 #define MAC2_EXCESS_DEF 0x00004000 /* Excess Defer */
emilmont 10:3bc89ef62ce7 105
emilmont 10:3bc89ef62ce7 106 /* Back-to-Back Inter-Packet-Gap Register */
emilmont 10:3bc89ef62ce7 107 #define IPGT_FULL_DUP 0x00000015 /* Recommended value for Full Duplex */
emilmont 10:3bc89ef62ce7 108 #define IPGT_HALF_DUP 0x00000012 /* Recommended value for Half Duplex */
emilmont 10:3bc89ef62ce7 109
emilmont 10:3bc89ef62ce7 110 /* Non Back-to-Back Inter-Packet-Gap Register */
emilmont 10:3bc89ef62ce7 111 #define IPGR_DEF 0x00000012 /* Recommended value */
emilmont 10:3bc89ef62ce7 112
emilmont 10:3bc89ef62ce7 113 /* Collision Window/Retry Register */
emilmont 10:3bc89ef62ce7 114 #define CLRT_DEF 0x0000370F /* Default value */
emilmont 10:3bc89ef62ce7 115
emilmont 10:3bc89ef62ce7 116 /* PHY Support Register */
emilmont 10:3bc89ef62ce7 117 #define SUPP_SPEED 0x00000100 /* Reduced MII Logic Current Speed */
emilmont 10:3bc89ef62ce7 118 //#define SUPP_RES_RMII 0x00000800 /* Reset Reduced MII Logic */
emilmont 10:3bc89ef62ce7 119 #define SUPP_RES_RMII 0x00000000 /* Reset Reduced MII Logic */
emilmont 10:3bc89ef62ce7 120
emilmont 10:3bc89ef62ce7 121 /* Test Register */
emilmont 10:3bc89ef62ce7 122 #define TEST_SHCUT_PQUANTA 0x00000001 /* Shortcut Pause Quanta */
emilmont 10:3bc89ef62ce7 123 #define TEST_TST_PAUSE 0x00000002 /* Test Pause */
emilmont 10:3bc89ef62ce7 124 #define TEST_TST_BACKP 0x00000004 /* Test Back Pressure */
emilmont 10:3bc89ef62ce7 125
emilmont 10:3bc89ef62ce7 126 /* MII Management Configuration Register */
emilmont 10:3bc89ef62ce7 127 #define MCFG_SCAN_INC 0x00000001 /* Scan Increment PHY Address */
emilmont 10:3bc89ef62ce7 128 #define MCFG_SUPP_PREAM 0x00000002 /* Suppress Preamble */
emilmont 10:3bc89ef62ce7 129 #define MCFG_CLK_SEL 0x0000003C /* Clock Select Mask */
emilmont 10:3bc89ef62ce7 130 #define MCFG_RES_MII 0x00008000 /* Reset MII Management Hardware */
emilmont 10:3bc89ef62ce7 131
emilmont 10:3bc89ef62ce7 132 /* MII Management Command Register */
emilmont 10:3bc89ef62ce7 133 #define MCMD_READ 0x00000001 /* MII Read */
emilmont 10:3bc89ef62ce7 134 #define MCMD_SCAN 0x00000002 /* MII Scan continuously */
emilmont 10:3bc89ef62ce7 135
emilmont 10:3bc89ef62ce7 136 #define MII_WR_TOUT 0x00050000 /* MII Write timeout count */
emilmont 10:3bc89ef62ce7 137 #define MII_RD_TOUT 0x00050000 /* MII Read timeout count */
emilmont 10:3bc89ef62ce7 138
emilmont 10:3bc89ef62ce7 139 /* MII Management Address Register */
emilmont 10:3bc89ef62ce7 140 #define MADR_REG_ADR 0x0000001F /* MII Register Address Mask */
emilmont 10:3bc89ef62ce7 141 #define MADR_PHY_ADR 0x00001F00 /* PHY Address Mask */
emilmont 10:3bc89ef62ce7 142
emilmont 10:3bc89ef62ce7 143 /* MII Management Indicators Register */
emilmont 10:3bc89ef62ce7 144 #define MIND_BUSY 0x00000001 /* MII is Busy */
emilmont 10:3bc89ef62ce7 145 #define MIND_SCAN 0x00000002 /* MII Scanning in Progress */
emilmont 10:3bc89ef62ce7 146 #define MIND_NOT_VAL 0x00000004 /* MII Read Data not valid */
emilmont 10:3bc89ef62ce7 147 #define MIND_MII_LINK_FAIL 0x00000008 /* MII Link Failed */
emilmont 10:3bc89ef62ce7 148
emilmont 10:3bc89ef62ce7 149 /* Command Register */
emilmont 10:3bc89ef62ce7 150 #define CR_RX_EN 0x00000001 /* Enable Receive */
emilmont 10:3bc89ef62ce7 151 #define CR_TX_EN 0x00000002 /* Enable Transmit */
emilmont 10:3bc89ef62ce7 152 #define CR_REG_RES 0x00000008 /* Reset Host Registers */
emilmont 10:3bc89ef62ce7 153 #define CR_TX_RES 0x00000010 /* Reset Transmit Datapath */
emilmont 10:3bc89ef62ce7 154 #define CR_RX_RES 0x00000020 /* Reset Receive Datapath */
emilmont 10:3bc89ef62ce7 155 #define CR_PASS_RUNT_FRM 0x00000040 /* Pass Runt Frames */
emilmont 10:3bc89ef62ce7 156 #define CR_PASS_RX_FILT 0x00000080 /* Pass RX Filter */
emilmont 10:3bc89ef62ce7 157 #define CR_TX_FLOW_CTRL 0x00000100 /* TX Flow Control */
emilmont 10:3bc89ef62ce7 158 #define CR_RMII 0x00000200 /* Reduced MII Interface */
emilmont 10:3bc89ef62ce7 159 #define CR_FULL_DUP 0x00000400 /* Full Duplex */
emilmont 10:3bc89ef62ce7 160
emilmont 10:3bc89ef62ce7 161 /* Status Register */
emilmont 10:3bc89ef62ce7 162 #define SR_RX_EN 0x00000001 /* Enable Receive */
emilmont 10:3bc89ef62ce7 163 #define SR_TX_EN 0x00000002 /* Enable Transmit */
emilmont 10:3bc89ef62ce7 164
emilmont 10:3bc89ef62ce7 165 /* Transmit Status Vector 0 Register */
emilmont 10:3bc89ef62ce7 166 #define TSV0_CRC_ERR 0x00000001 /* CRC error */
emilmont 10:3bc89ef62ce7 167 #define TSV0_LEN_CHKERR 0x00000002 /* Length Check Error */
emilmont 10:3bc89ef62ce7 168 #define TSV0_LEN_OUTRNG 0x00000004 /* Length Out of Range */
emilmont 10:3bc89ef62ce7 169 #define TSV0_DONE 0x00000008 /* Tramsmission Completed */
emilmont 10:3bc89ef62ce7 170 #define TSV0_MCAST 0x00000010 /* Multicast Destination */
emilmont 10:3bc89ef62ce7 171 #define TSV0_BCAST 0x00000020 /* Broadcast Destination */
emilmont 10:3bc89ef62ce7 172 #define TSV0_PKT_DEFER 0x00000040 /* Packet Deferred */
emilmont 10:3bc89ef62ce7 173 #define TSV0_EXC_DEFER 0x00000080 /* Excessive Packet Deferral */
emilmont 10:3bc89ef62ce7 174 #define TSV0_EXC_COLL 0x00000100 /* Excessive Collision */
emilmont 10:3bc89ef62ce7 175 #define TSV0_LATE_COLL 0x00000200 /* Late Collision Occured */
emilmont 10:3bc89ef62ce7 176 #define TSV0_GIANT 0x00000400 /* Giant Frame */
emilmont 10:3bc89ef62ce7 177 #define TSV0_UNDERRUN 0x00000800 /* Buffer Underrun */
emilmont 10:3bc89ef62ce7 178 #define TSV0_BYTES 0x0FFFF000 /* Total Bytes Transferred */
emilmont 10:3bc89ef62ce7 179 #define TSV0_CTRL_FRAME 0x10000000 /* Control Frame */
emilmont 10:3bc89ef62ce7 180 #define TSV0_PAUSE 0x20000000 /* Pause Frame */
emilmont 10:3bc89ef62ce7 181 #define TSV0_BACK_PRESS 0x40000000 /* Backpressure Method Applied */
emilmont 10:3bc89ef62ce7 182 #define TSV0_VLAN 0x80000000 /* VLAN Frame */
emilmont 10:3bc89ef62ce7 183
emilmont 10:3bc89ef62ce7 184 /* Transmit Status Vector 1 Register */
emilmont 10:3bc89ef62ce7 185 #define TSV1_BYTE_CNT 0x0000FFFF /* Transmit Byte Count */
emilmont 10:3bc89ef62ce7 186 #define TSV1_COLL_CNT 0x000F0000 /* Transmit Collision Count */
emilmont 10:3bc89ef62ce7 187
emilmont 10:3bc89ef62ce7 188 /* Receive Status Vector Register */
emilmont 10:3bc89ef62ce7 189 #define RSV_BYTE_CNT 0x0000FFFF /* Receive Byte Count */
emilmont 10:3bc89ef62ce7 190 #define RSV_PKT_IGNORED 0x00010000 /* Packet Previously Ignored */
emilmont 10:3bc89ef62ce7 191 #define RSV_RXDV_SEEN 0x00020000 /* RXDV Event Previously Seen */
emilmont 10:3bc89ef62ce7 192 #define RSV_CARR_SEEN 0x00040000 /* Carrier Event Previously Seen */
emilmont 10:3bc89ef62ce7 193 #define RSV_REC_CODEV 0x00080000 /* Receive Code Violation */
emilmont 10:3bc89ef62ce7 194 #define RSV_CRC_ERR 0x00100000 /* CRC Error */
emilmont 10:3bc89ef62ce7 195 #define RSV_LEN_CHKERR 0x00200000 /* Length Check Error */
emilmont 10:3bc89ef62ce7 196 #define RSV_LEN_OUTRNG 0x00400000 /* Length Out of Range */
emilmont 10:3bc89ef62ce7 197 #define RSV_REC_OK 0x00800000 /* Frame Received OK */
emilmont 10:3bc89ef62ce7 198 #define RSV_MCAST 0x01000000 /* Multicast Frame */
emilmont 10:3bc89ef62ce7 199 #define RSV_BCAST 0x02000000 /* Broadcast Frame */
emilmont 10:3bc89ef62ce7 200 #define RSV_DRIB_NIBB 0x04000000 /* Dribble Nibble */
emilmont 10:3bc89ef62ce7 201 #define RSV_CTRL_FRAME 0x08000000 /* Control Frame */
emilmont 10:3bc89ef62ce7 202 #define RSV_PAUSE 0x10000000 /* Pause Frame */
emilmont 10:3bc89ef62ce7 203 #define RSV_UNSUPP_OPC 0x20000000 /* Unsupported Opcode */
emilmont 10:3bc89ef62ce7 204 #define RSV_VLAN 0x40000000 /* VLAN Frame */
emilmont 10:3bc89ef62ce7 205
emilmont 10:3bc89ef62ce7 206 /* Flow Control Counter Register */
emilmont 10:3bc89ef62ce7 207 #define FCC_MIRR_CNT 0x0000FFFF /* Mirror Counter */
emilmont 10:3bc89ef62ce7 208 #define FCC_PAUSE_TIM 0xFFFF0000 /* Pause Timer */
emilmont 10:3bc89ef62ce7 209
emilmont 10:3bc89ef62ce7 210 /* Flow Control Status Register */
emilmont 10:3bc89ef62ce7 211 #define FCS_MIRR_CNT 0x0000FFFF /* Mirror Counter Current */
emilmont 10:3bc89ef62ce7 212
emilmont 10:3bc89ef62ce7 213 /* Receive Filter Control Register */
emilmont 10:3bc89ef62ce7 214 #define RFC_UCAST_EN 0x00000001 /* Accept Unicast Frames Enable */
emilmont 10:3bc89ef62ce7 215 #define RFC_BCAST_EN 0x00000002 /* Accept Broadcast Frames Enable */
emilmont 10:3bc89ef62ce7 216 #define RFC_MCAST_EN 0x00000004 /* Accept Multicast Frames Enable */
emilmont 10:3bc89ef62ce7 217 #define RFC_UCAST_HASH_EN 0x00000008 /* Accept Unicast Hash Filter Frames */
emilmont 10:3bc89ef62ce7 218 #define RFC_MCAST_HASH_EN 0x00000010 /* Accept Multicast Hash Filter Fram.*/
emilmont 10:3bc89ef62ce7 219 #define RFC_PERFECT_EN 0x00000020 /* Accept Perfect Match Enable */
emilmont 10:3bc89ef62ce7 220 #define RFC_MAGP_WOL_EN 0x00001000 /* Magic Packet Filter WoL Enable */
emilmont 10:3bc89ef62ce7 221 #define RFC_PFILT_WOL_EN 0x00002000 /* Perfect Filter WoL Enable */
emilmont 10:3bc89ef62ce7 222
emilmont 10:3bc89ef62ce7 223 /* Receive Filter WoL Status/Clear Registers */
emilmont 10:3bc89ef62ce7 224 #define WOL_UCAST 0x00000001 /* Unicast Frame caused WoL */
emilmont 10:3bc89ef62ce7 225 #define WOL_BCAST 0x00000002 /* Broadcast Frame caused WoL */
emilmont 10:3bc89ef62ce7 226 #define WOL_MCAST 0x00000004 /* Multicast Frame caused WoL */
emilmont 10:3bc89ef62ce7 227 #define WOL_UCAST_HASH 0x00000008 /* Unicast Hash Filter Frame WoL */
emilmont 10:3bc89ef62ce7 228 #define WOL_MCAST_HASH 0x00000010 /* Multicast Hash Filter Frame WoL */
emilmont 10:3bc89ef62ce7 229 #define WOL_PERFECT 0x00000020 /* Perfect Filter WoL */
emilmont 10:3bc89ef62ce7 230 #define WOL_RX_FILTER 0x00000080 /* RX Filter caused WoL */
emilmont 10:3bc89ef62ce7 231 #define WOL_MAG_PACKET 0x00000100 /* Magic Packet Filter caused WoL */
emilmont 10:3bc89ef62ce7 232
emilmont 10:3bc89ef62ce7 233 /* Interrupt Status/Enable/Clear/Set Registers */
emilmont 10:3bc89ef62ce7 234 #define INT_RX_OVERRUN 0x00000001 /* Overrun Error in RX Queue */
emilmont 10:3bc89ef62ce7 235 #define INT_RX_ERR 0x00000002 /* Receive Error */
emilmont 10:3bc89ef62ce7 236 #define INT_RX_FIN 0x00000004 /* RX Finished Process Descriptors */
emilmont 10:3bc89ef62ce7 237 #define INT_RX_DONE 0x00000008 /* Receive Done */
emilmont 10:3bc89ef62ce7 238 #define INT_TX_UNDERRUN 0x00000010 /* Transmit Underrun */
emilmont 10:3bc89ef62ce7 239 #define INT_TX_ERR 0x00000020 /* Transmit Error */
emilmont 10:3bc89ef62ce7 240 #define INT_TX_FIN 0x00000040 /* TX Finished Process Descriptors */
emilmont 10:3bc89ef62ce7 241 #define INT_TX_DONE 0x00000080 /* Transmit Done */
emilmont 10:3bc89ef62ce7 242 #define INT_SOFT_INT 0x00001000 /* Software Triggered Interrupt */
emilmont 10:3bc89ef62ce7 243 #define INT_WAKEUP 0x00002000 /* Wakeup Event Interrupt */
emilmont 10:3bc89ef62ce7 244
emilmont 10:3bc89ef62ce7 245 /* Power Down Register */
emilmont 10:3bc89ef62ce7 246 #define PD_POWER_DOWN 0x80000000 /* Power Down MAC */
emilmont 10:3bc89ef62ce7 247
emilmont 10:3bc89ef62ce7 248 /* RX Descriptor Control Word */
emilmont 10:3bc89ef62ce7 249 #define RCTRL_SIZE 0x000007FF /* Buffer size mask */
emilmont 10:3bc89ef62ce7 250 #define RCTRL_INT 0x80000000 /* Generate RxDone Interrupt */
emilmont 10:3bc89ef62ce7 251
emilmont 10:3bc89ef62ce7 252 /* RX Status Hash CRC Word */
emilmont 10:3bc89ef62ce7 253 #define RHASH_SA 0x000001FF /* Hash CRC for Source Address */
emilmont 10:3bc89ef62ce7 254 #define RHASH_DA 0x001FF000 /* Hash CRC for Destination Address */
emilmont 10:3bc89ef62ce7 255
emilmont 10:3bc89ef62ce7 256 /* RX Status Information Word */
emilmont 10:3bc89ef62ce7 257 #define RINFO_SIZE 0x000007FF /* Data size in bytes */
emilmont 10:3bc89ef62ce7 258 #define RINFO_CTRL_FRAME 0x00040000 /* Control Frame */
emilmont 10:3bc89ef62ce7 259 #define RINFO_VLAN 0x00080000 /* VLAN Frame */
emilmont 10:3bc89ef62ce7 260 #define RINFO_FAIL_FILT 0x00100000 /* RX Filter Failed */
emilmont 10:3bc89ef62ce7 261 #define RINFO_MCAST 0x00200000 /* Multicast Frame */
emilmont 10:3bc89ef62ce7 262 #define RINFO_BCAST 0x00400000 /* Broadcast Frame */
emilmont 10:3bc89ef62ce7 263 #define RINFO_CRC_ERR 0x00800000 /* CRC Error in Frame */
emilmont 10:3bc89ef62ce7 264 #define RINFO_SYM_ERR 0x01000000 /* Symbol Error from PHY */
emilmont 10:3bc89ef62ce7 265 #define RINFO_LEN_ERR 0x02000000 /* Length Error */
emilmont 10:3bc89ef62ce7 266 #define RINFO_RANGE_ERR 0x04000000 /* Range Error (exceeded max. size) */
emilmont 10:3bc89ef62ce7 267 #define RINFO_ALIGN_ERR 0x08000000 /* Alignment Error */
emilmont 10:3bc89ef62ce7 268 #define RINFO_OVERRUN 0x10000000 /* Receive overrun */
emilmont 10:3bc89ef62ce7 269 #define RINFO_NO_DESCR 0x20000000 /* No new Descriptor available */
emilmont 10:3bc89ef62ce7 270 #define RINFO_LAST_FLAG 0x40000000 /* Last Fragment in Frame */
emilmont 10:3bc89ef62ce7 271 #define RINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */
emilmont 10:3bc89ef62ce7 272
emilmont 10:3bc89ef62ce7 273 //#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_CRC_ERR | RINFO_SYM_ERR | RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN)
emilmont 10:3bc89ef62ce7 274 #define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_SYM_ERR | \
emilmont 10:3bc89ef62ce7 275 RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN)
emilmont 10:3bc89ef62ce7 276
emilmont 10:3bc89ef62ce7 277
emilmont 10:3bc89ef62ce7 278 /* TX Descriptor Control Word */
emilmont 10:3bc89ef62ce7 279 #define TCTRL_SIZE 0x000007FF /* Size of data buffer in bytes */
emilmont 10:3bc89ef62ce7 280 #define TCTRL_OVERRIDE 0x04000000 /* Override Default MAC Registers */
emilmont 10:3bc89ef62ce7 281 #define TCTRL_HUGE 0x08000000 /* Enable Huge Frame */
emilmont 10:3bc89ef62ce7 282 #define TCTRL_PAD 0x10000000 /* Pad short Frames to 64 bytes */
emilmont 10:3bc89ef62ce7 283 #define TCTRL_CRC 0x20000000 /* Append a hardware CRC to Frame */
emilmont 10:3bc89ef62ce7 284 #define TCTRL_LAST 0x40000000 /* Last Descriptor for TX Frame */
emilmont 10:3bc89ef62ce7 285 #define TCTRL_INT 0x80000000 /* Generate TxDone Interrupt */
emilmont 10:3bc89ef62ce7 286
emilmont 10:3bc89ef62ce7 287 /* TX Status Information Word */
emilmont 10:3bc89ef62ce7 288 #define TINFO_COL_CNT 0x01E00000 /* Collision Count */
emilmont 10:3bc89ef62ce7 289 #define TINFO_DEFER 0x02000000 /* Packet Deferred (not an error) */
emilmont 10:3bc89ef62ce7 290 #define TINFO_EXCESS_DEF 0x04000000 /* Excessive Deferral */
emilmont 10:3bc89ef62ce7 291 #define TINFO_EXCESS_COL 0x08000000 /* Excessive Collision */
emilmont 10:3bc89ef62ce7 292 #define TINFO_LATE_COL 0x10000000 /* Late Collision Occured */
emilmont 10:3bc89ef62ce7 293 #define TINFO_UNDERRUN 0x20000000 /* Transmit Underrun */
emilmont 10:3bc89ef62ce7 294 #define TINFO_NO_DESCR 0x40000000 /* No new Descriptor available */
emilmont 10:3bc89ef62ce7 295 #define TINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */
emilmont 10:3bc89ef62ce7 296
emilmont 10:3bc89ef62ce7 297 /* ENET Device Revision ID */
emilmont 10:3bc89ef62ce7 298 #define OLD_EMAC_MODULE_ID 0x39022000 /* Rev. ID for first rev '-' */
emilmont 10:3bc89ef62ce7 299
emilmont 10:3bc89ef62ce7 300 /* DP83848C PHY Registers */
emilmont 10:3bc89ef62ce7 301 #define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */
emilmont 10:3bc89ef62ce7 302 #define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */
emilmont 10:3bc89ef62ce7 303 #define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */
emilmont 10:3bc89ef62ce7 304 #define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */
emilmont 10:3bc89ef62ce7 305 #define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */
emilmont 10:3bc89ef62ce7 306 #define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */
emilmont 10:3bc89ef62ce7 307 #define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */
emilmont 10:3bc89ef62ce7 308 #define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */
emilmont 10:3bc89ef62ce7 309
emilmont 10:3bc89ef62ce7 310 /* PHY Extended Registers */
emilmont 10:3bc89ef62ce7 311 #define PHY_REG_STS 0x10 /* Status Register */
emilmont 10:3bc89ef62ce7 312 #define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */
emilmont 10:3bc89ef62ce7 313 #define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */
emilmont 10:3bc89ef62ce7 314 #define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */
emilmont 10:3bc89ef62ce7 315 #define PHY_REG_RECR 0x15 /* Receive Error Counter */
emilmont 10:3bc89ef62ce7 316 #define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */
emilmont 10:3bc89ef62ce7 317 #define PHY_REG_RBR 0x17 /* RMII and Bypass Register */
emilmont 10:3bc89ef62ce7 318 #define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */
emilmont 10:3bc89ef62ce7 319 #define PHY_REG_PHYCR 0x19 /* PHY Control Register */
emilmont 10:3bc89ef62ce7 320 #define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */
emilmont 10:3bc89ef62ce7 321 #define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */
emilmont 10:3bc89ef62ce7 322 #define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */
emilmont 10:3bc89ef62ce7 323
emilmont 10:3bc89ef62ce7 324 #define PHY_REG_SCSR 0x1F /* PHY Special Control/Status Register */
emilmont 10:3bc89ef62ce7 325
emilmont 10:3bc89ef62ce7 326 #define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */
emilmont 10:3bc89ef62ce7 327 #define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */
emilmont 10:3bc89ef62ce7 328 #define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */
emilmont 10:3bc89ef62ce7 329 #define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */
emilmont 10:3bc89ef62ce7 330 #define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */
emilmont 10:3bc89ef62ce7 331
emilmont 10:3bc89ef62ce7 332 #define DP83848C_DEF_ADR 0x0100 /* Default PHY device address */
emilmont 10:3bc89ef62ce7 333 #define DP83848C_ID 0x20005C90 /* PHY Identifier - DP83848C */
emilmont 10:3bc89ef62ce7 334
emilmont 10:3bc89ef62ce7 335 #define LAN8720_ID 0x0007C0F0 /* PHY Identifier - LAN8720 */
emilmont 10:3bc89ef62ce7 336
emilmont 10:3bc89ef62ce7 337 #define PHY_STS_LINK 0x0001 /* PHY Status Link Mask */
emilmont 10:3bc89ef62ce7 338 #define PHY_STS_SPEED 0x0002 /* PHY Status Speed Mask */
emilmont 10:3bc89ef62ce7 339 #define PHY_STS_DUPLEX 0x0004 /* PHY Status Duplex Mask */
emilmont 10:3bc89ef62ce7 340
emilmont 10:3bc89ef62ce7 341 #define PHY_BMCR_RESET 0x8000 /* PHY Reset */
emilmont 10:3bc89ef62ce7 342
emilmont 10:3bc89ef62ce7 343 #define PHY_BMSR_LINK 0x0004 /* PHY BMSR Link valid */
emilmont 10:3bc89ef62ce7 344
emilmont 10:3bc89ef62ce7 345 #define PHY_SCSR_100MBIT 0x0008 /* Speed: 1=100 MBit, 0=10Mbit */
emilmont 10:3bc89ef62ce7 346 #define PHY_SCSR_DUPLEX 0x0010 /* PHY Duplex Mask */
emilmont 10:3bc89ef62ce7 347
emilmont 10:3bc89ef62ce7 348
emilmont 10:3bc89ef62ce7 349 static int phy_read(unsigned int PhyReg);
emilmont 10:3bc89ef62ce7 350 static int phy_write(unsigned int PhyReg, unsigned short Data);
emilmont 10:3bc89ef62ce7 351
emilmont 10:3bc89ef62ce7 352 static void txdscr_init(void);
emilmont 10:3bc89ef62ce7 353 static void rxdscr_init(void);
emilmont 10:3bc89ef62ce7 354
emilmont 10:3bc89ef62ce7 355 #if defined (__ICCARM__)
emilmont 10:3bc89ef62ce7 356 # define AHBSRAM1
emilmont 10:3bc89ef62ce7 357 #elif defined(TOOLCHAIN_GCC_CR)
emilmont 10:3bc89ef62ce7 358 # define AHBSRAM1 __attribute__((section(".data.$RamPeriph32")))
emilmont 10:3bc89ef62ce7 359 #else
emilmont 10:3bc89ef62ce7 360 # define AHBSRAM1 __attribute__((section("AHBSRAM1"),aligned))
emilmont 10:3bc89ef62ce7 361 #endif
emilmont 10:3bc89ef62ce7 362
emilmont 10:3bc89ef62ce7 363 AHBSRAM1 volatile uint8_t rxbuf[NUM_RX_FRAG][ETH_FRAG_SIZE];
emilmont 10:3bc89ef62ce7 364 AHBSRAM1 volatile uint8_t txbuf[NUM_TX_FRAG][ETH_FRAG_SIZE];
emilmont 10:3bc89ef62ce7 365 AHBSRAM1 volatile RX_DESC_TypeDef rxdesc[NUM_RX_FRAG];
emilmont 10:3bc89ef62ce7 366 AHBSRAM1 volatile RX_STAT_TypeDef rxstat[NUM_RX_FRAG];
emilmont 10:3bc89ef62ce7 367 AHBSRAM1 volatile TX_DESC_TypeDef txdesc[NUM_TX_FRAG];
emilmont 10:3bc89ef62ce7 368 AHBSRAM1 volatile TX_STAT_TypeDef txstat[NUM_TX_FRAG];
emilmont 10:3bc89ef62ce7 369
emilmont 10:3bc89ef62ce7 370
emilmont 10:3bc89ef62ce7 371 #if NEW_LOGIC
emilmont 10:3bc89ef62ce7 372 static int rx_consume_offset = -1;
emilmont 10:3bc89ef62ce7 373 static int tx_produce_offset = -1;
emilmont 10:3bc89ef62ce7 374 #else
emilmont 10:3bc89ef62ce7 375 static int send_doff = 0;
emilmont 10:3bc89ef62ce7 376 static int send_idx = -1;
emilmont 10:3bc89ef62ce7 377 static int send_size = 0;
emilmont 10:3bc89ef62ce7 378
emilmont 10:3bc89ef62ce7 379 static int receive_soff = 0;
emilmont 10:3bc89ef62ce7 380 static int receive_idx = -1;
emilmont 10:3bc89ef62ce7 381 #endif
emilmont 10:3bc89ef62ce7 382
emilmont 10:3bc89ef62ce7 383 static uint32_t phy_id = 0;
emilmont 10:3bc89ef62ce7 384
emilmont 10:3bc89ef62ce7 385 static inline int rinc(int idx, int mod) {
emilmont 10:3bc89ef62ce7 386 ++idx;
emilmont 10:3bc89ef62ce7 387 idx %= mod;
emilmont 10:3bc89ef62ce7 388 return idx;
emilmont 10:3bc89ef62ce7 389 }
emilmont 10:3bc89ef62ce7 390
emilmont 10:3bc89ef62ce7 391 //extern unsigned int SystemFrequency;
emilmont 10:3bc89ef62ce7 392 static inline unsigned int clockselect() {
emilmont 10:3bc89ef62ce7 393 if(SystemCoreClock < 10000000) {
emilmont 10:3bc89ef62ce7 394 return 1;
emilmont 10:3bc89ef62ce7 395 } else if(SystemCoreClock < 15000000) {
emilmont 10:3bc89ef62ce7 396 return 2;
emilmont 10:3bc89ef62ce7 397 } else if(SystemCoreClock < 20000000) {
emilmont 10:3bc89ef62ce7 398 return 3;
emilmont 10:3bc89ef62ce7 399 } else if(SystemCoreClock < 25000000) {
emilmont 10:3bc89ef62ce7 400 return 4;
emilmont 10:3bc89ef62ce7 401 } else if(SystemCoreClock < 35000000) {
emilmont 10:3bc89ef62ce7 402 return 5;
emilmont 10:3bc89ef62ce7 403 } else if(SystemCoreClock < 50000000) {
emilmont 10:3bc89ef62ce7 404 return 6;
emilmont 10:3bc89ef62ce7 405 } else if(SystemCoreClock < 70000000) {
emilmont 10:3bc89ef62ce7 406 return 7;
emilmont 10:3bc89ef62ce7 407 } else if(SystemCoreClock < 80000000) {
emilmont 10:3bc89ef62ce7 408 return 8;
emilmont 10:3bc89ef62ce7 409 } else if(SystemCoreClock < 90000000) {
emilmont 10:3bc89ef62ce7 410 return 9;
emilmont 10:3bc89ef62ce7 411 } else if(SystemCoreClock < 100000000) {
emilmont 10:3bc89ef62ce7 412 return 10;
emilmont 10:3bc89ef62ce7 413 } else if(SystemCoreClock < 120000000) {
emilmont 10:3bc89ef62ce7 414 return 11;
emilmont 10:3bc89ef62ce7 415 } else if(SystemCoreClock < 130000000) {
emilmont 10:3bc89ef62ce7 416 return 12;
emilmont 10:3bc89ef62ce7 417 } else if(SystemCoreClock < 140000000) {
emilmont 10:3bc89ef62ce7 418 return 13;
emilmont 10:3bc89ef62ce7 419 } else if(SystemCoreClock < 150000000) {
emilmont 10:3bc89ef62ce7 420 return 15;
emilmont 10:3bc89ef62ce7 421 } else if(SystemCoreClock < 160000000) {
emilmont 10:3bc89ef62ce7 422 return 16;
emilmont 10:3bc89ef62ce7 423 } else {
emilmont 10:3bc89ef62ce7 424 return 0;
emilmont 10:3bc89ef62ce7 425 }
emilmont 10:3bc89ef62ce7 426 }
emilmont 10:3bc89ef62ce7 427
emilmont 10:3bc89ef62ce7 428 #ifndef min
emilmont 10:3bc89ef62ce7 429 #define min(x, y) (((x)<(y))?(x):(y))
emilmont 10:3bc89ef62ce7 430 #endif
emilmont 10:3bc89ef62ce7 431
emilmont 10:3bc89ef62ce7 432 /*----------------------------------------------------------------------------
emilmont 10:3bc89ef62ce7 433 Ethernet Device initialize
emilmont 10:3bc89ef62ce7 434 *----------------------------------------------------------------------------*/
emilmont 10:3bc89ef62ce7 435 int ethernet_init() {
emilmont 10:3bc89ef62ce7 436 int regv, tout;
emilmont 10:3bc89ef62ce7 437 char mac[ETHERNET_ADDR_SIZE];
emilmont 10:3bc89ef62ce7 438 unsigned int clock = clockselect();
mbed_official 212:34d62c0b2af6 439
emilmont 10:3bc89ef62ce7 440 LPC_SC->PCONP |= 0x40000000; /* Power Up the EMAC controller. */
mbed_official 212:34d62c0b2af6 441
emilmont 10:3bc89ef62ce7 442 LPC_PINCON->PINSEL2 = 0x50150105; /* Enable P1 Ethernet Pins. */
emilmont 10:3bc89ef62ce7 443 LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005;
emilmont 10:3bc89ef62ce7 444
emilmont 10:3bc89ef62ce7 445 /* Reset all EMAC internal modules. */
emilmont 10:3bc89ef62ce7 446 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX |
emilmont 10:3bc89ef62ce7 447 MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
emilmont 10:3bc89ef62ce7 448 LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
emilmont 10:3bc89ef62ce7 449
emilmont 10:3bc89ef62ce7 450 for(tout = 100; tout; tout--) __NOP(); /* A short delay after reset. */
emilmont 10:3bc89ef62ce7 451
emilmont 10:3bc89ef62ce7 452 LPC_EMAC->MAC1 = MAC1_PASS_ALL; /* Initialize MAC control registers. */
emilmont 10:3bc89ef62ce7 453 LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
emilmont 10:3bc89ef62ce7 454 LPC_EMAC->MAXF = ETH_MAX_FLEN;
emilmont 10:3bc89ef62ce7 455 LPC_EMAC->CLRT = CLRT_DEF;
emilmont 10:3bc89ef62ce7 456 LPC_EMAC->IPGR = IPGR_DEF;
emilmont 10:3bc89ef62ce7 457
emilmont 10:3bc89ef62ce7 458 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM; /* Enable Reduced MII interface. */
emilmont 10:3bc89ef62ce7 459
emilmont 10:3bc89ef62ce7 460 LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; /* Set clock */
emilmont 10:3bc89ef62ce7 461 LPC_EMAC->MCFG |= MCFG_RES_MII; /* and reset */
emilmont 10:3bc89ef62ce7 462
emilmont 10:3bc89ef62ce7 463 for(tout = 100; tout; tout--) __NOP(); /* A short delay */
emilmont 10:3bc89ef62ce7 464
emilmont 10:3bc89ef62ce7 465 LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;
emilmont 10:3bc89ef62ce7 466 LPC_EMAC->MCMD = 0;
emilmont 10:3bc89ef62ce7 467
emilmont 10:3bc89ef62ce7 468 LPC_EMAC->SUPP = SUPP_RES_RMII; /* Reset Reduced MII Logic. */
emilmont 10:3bc89ef62ce7 469
emilmont 10:3bc89ef62ce7 470 for (tout = 100; tout; tout--) __NOP(); /* A short delay */
emilmont 10:3bc89ef62ce7 471
emilmont 10:3bc89ef62ce7 472 LPC_EMAC->SUPP = 0;
emilmont 10:3bc89ef62ce7 473
emilmont 10:3bc89ef62ce7 474 phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */
emilmont 10:3bc89ef62ce7 475 for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */
emilmont 10:3bc89ef62ce7 476 regv = phy_read(PHY_REG_BMCR);
emilmont 10:3bc89ef62ce7 477 if(regv < 0 || tout == 0) {
emilmont 10:3bc89ef62ce7 478 return -1; /* Error */
emilmont 10:3bc89ef62ce7 479 }
emilmont 10:3bc89ef62ce7 480 if(!(regv & PHY_BMCR_RESET)) {
emilmont 10:3bc89ef62ce7 481 break; /* Reset complete. */
emilmont 10:3bc89ef62ce7 482 }
emilmont 10:3bc89ef62ce7 483 }
emilmont 10:3bc89ef62ce7 484
emilmont 10:3bc89ef62ce7 485 phy_id = (phy_read(PHY_REG_IDR1) << 16);
emilmont 10:3bc89ef62ce7 486 phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);
emilmont 10:3bc89ef62ce7 487
emilmont 10:3bc89ef62ce7 488 if (phy_id != DP83848C_ID && phy_id != LAN8720_ID) {
emilmont 10:3bc89ef62ce7 489 error("Unknown Ethernet PHY (%x)", (unsigned int)phy_id);
emilmont 10:3bc89ef62ce7 490 }
emilmont 10:3bc89ef62ce7 491
emilmont 10:3bc89ef62ce7 492 ethernet_set_link(-1, 0);
emilmont 10:3bc89ef62ce7 493
emilmont 10:3bc89ef62ce7 494 /* Set the Ethernet MAC Address registers */
emilmont 10:3bc89ef62ce7 495 ethernet_address(mac);
emilmont 10:3bc89ef62ce7 496 LPC_EMAC->SA0 = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4];
emilmont 10:3bc89ef62ce7 497 LPC_EMAC->SA1 = ((uint32_t)mac[3] << 8) | (uint32_t)mac[2];
emilmont 10:3bc89ef62ce7 498 LPC_EMAC->SA2 = ((uint32_t)mac[1] << 8) | (uint32_t)mac[0];
emilmont 10:3bc89ef62ce7 499
emilmont 10:3bc89ef62ce7 500 txdscr_init(); /* initialize DMA TX Descriptor */
emilmont 10:3bc89ef62ce7 501 rxdscr_init(); /* initialize DMA RX Descriptor */
emilmont 10:3bc89ef62ce7 502
emilmont 10:3bc89ef62ce7 503 LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
emilmont 10:3bc89ef62ce7 504 /* Receive Broadcast, Perfect Match Packets */
emilmont 10:3bc89ef62ce7 505
emilmont 10:3bc89ef62ce7 506 LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE; /* Enable EMAC interrupts. */
emilmont 10:3bc89ef62ce7 507 LPC_EMAC->IntClear = 0xFFFF; /* Reset all interrupts */
emilmont 10:3bc89ef62ce7 508
emilmont 10:3bc89ef62ce7 509
emilmont 10:3bc89ef62ce7 510 LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); /* Enable receive and transmit mode of MAC Ethernet core */
emilmont 10:3bc89ef62ce7 511 LPC_EMAC->MAC1 |= MAC1_REC_EN;
emilmont 10:3bc89ef62ce7 512
emilmont 10:3bc89ef62ce7 513 #if NEW_LOGIC
emilmont 10:3bc89ef62ce7 514 rx_consume_offset = -1;
emilmont 10:3bc89ef62ce7 515 tx_produce_offset = -1;
emilmont 10:3bc89ef62ce7 516 #else
emilmont 10:3bc89ef62ce7 517 send_doff = 0;
emilmont 10:3bc89ef62ce7 518 send_idx = -1;
emilmont 10:3bc89ef62ce7 519 send_size = 0;
emilmont 10:3bc89ef62ce7 520
emilmont 10:3bc89ef62ce7 521 receive_soff = 0;
emilmont 10:3bc89ef62ce7 522 receive_idx = -1;
emilmont 10:3bc89ef62ce7 523 #endif
emilmont 10:3bc89ef62ce7 524
emilmont 10:3bc89ef62ce7 525 return 0;
emilmont 10:3bc89ef62ce7 526 }
emilmont 10:3bc89ef62ce7 527
emilmont 10:3bc89ef62ce7 528 /*----------------------------------------------------------------------------
emilmont 10:3bc89ef62ce7 529 Ethernet Device Uninitialize
emilmont 10:3bc89ef62ce7 530 *----------------------------------------------------------------------------*/
emilmont 10:3bc89ef62ce7 531 void ethernet_free() {
emilmont 10:3bc89ef62ce7 532 LPC_EMAC->IntEnable &= ~(INT_RX_DONE | INT_TX_DONE);
emilmont 10:3bc89ef62ce7 533 LPC_EMAC->IntClear = 0xFFFF;
mbed_official 212:34d62c0b2af6 534
emilmont 10:3bc89ef62ce7 535 LPC_SC->PCONP &= ~0x40000000; /* Power down the EMAC controller. */
mbed_official 212:34d62c0b2af6 536
emilmont 10:3bc89ef62ce7 537 LPC_PINCON->PINSEL2 &= ~0x50150105; /* Disable P1 ethernet pins. */
emilmont 10:3bc89ef62ce7 538 LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000000;
emilmont 10:3bc89ef62ce7 539 }
emilmont 10:3bc89ef62ce7 540
emilmont 10:3bc89ef62ce7 541 // if(TxProduceIndex == TxConsumeIndex) buffer array is empty
emilmont 10:3bc89ef62ce7 542 // if(TxProduceIndex == TxConsumeIndex - 1) buffer is full, should not fill
emilmont 10:3bc89ef62ce7 543 // TxProduceIndex - The buffer that will/is being fileld by driver, s/w increment
emilmont 10:3bc89ef62ce7 544 // TxConsumeIndex - The buffer that will/is beign sent by hardware
emilmont 10:3bc89ef62ce7 545
emilmont 10:3bc89ef62ce7 546 int ethernet_write(const char *data, int slen) {
emilmont 10:3bc89ef62ce7 547
emilmont 10:3bc89ef62ce7 548 #if NEW_LOGIC
emilmont 10:3bc89ef62ce7 549
emilmont 10:3bc89ef62ce7 550 if(tx_produce_offset < 0) { // mark as active if not already
emilmont 10:3bc89ef62ce7 551 tx_produce_offset = 0;
emilmont 10:3bc89ef62ce7 552 }
emilmont 10:3bc89ef62ce7 553
emilmont 10:3bc89ef62ce7 554 int index = LPC_EMAC->TxProduceIndex;
emilmont 10:3bc89ef62ce7 555
emilmont 10:3bc89ef62ce7 556 int remaining = ETH_MAX_FLEN - tx_produce_offset - 4; // bytes written plus checksum
emilmont 10:3bc89ef62ce7 557 int requested = slen;
emilmont 10:3bc89ef62ce7 558 int ncopy = min(remaining, requested);
emilmont 10:3bc89ef62ce7 559
emilmont 10:3bc89ef62ce7 560 void *pdst = (void *)(txdesc[index].Packet + tx_produce_offset);
emilmont 10:3bc89ef62ce7 561 void *psrc = (void *)(data);
emilmont 10:3bc89ef62ce7 562
emilmont 10:3bc89ef62ce7 563 if(ncopy > 0 ){
emilmont 10:3bc89ef62ce7 564 if(data != NULL) {
emilmont 10:3bc89ef62ce7 565 memcpy(pdst, psrc, ncopy);
emilmont 10:3bc89ef62ce7 566 } else {
emilmont 10:3bc89ef62ce7 567 memset(pdst, 0, ncopy);
emilmont 10:3bc89ef62ce7 568 }
emilmont 10:3bc89ef62ce7 569 }
emilmont 10:3bc89ef62ce7 570
emilmont 10:3bc89ef62ce7 571 tx_produce_offset += ncopy;
emilmont 10:3bc89ef62ce7 572
emilmont 10:3bc89ef62ce7 573 return ncopy;
emilmont 10:3bc89ef62ce7 574
emilmont 10:3bc89ef62ce7 575 #else
emilmont 10:3bc89ef62ce7 576 void *pdst, *psrc;
emilmont 10:3bc89ef62ce7 577 const int dlen = ETH_FRAG_SIZE;
emilmont 10:3bc89ef62ce7 578 int copy = 0;
emilmont 10:3bc89ef62ce7 579 int soff = 0;
emilmont 10:3bc89ef62ce7 580
emilmont 10:3bc89ef62ce7 581 if(send_idx == -1) {
emilmont 10:3bc89ef62ce7 582 send_idx = LPC_EMAC->TxProduceIndex;
emilmont 10:3bc89ef62ce7 583 }
emilmont 10:3bc89ef62ce7 584
emilmont 10:3bc89ef62ce7 585 if(slen + send_doff > ethernet_MTU_SIZE) {
emilmont 10:3bc89ef62ce7 586 return -1;
emilmont 10:3bc89ef62ce7 587 }
emilmont 10:3bc89ef62ce7 588
emilmont 10:3bc89ef62ce7 589 do {
emilmont 10:3bc89ef62ce7 590 copy = min(slen - soff, dlen - send_doff);
emilmont 10:3bc89ef62ce7 591 pdst = (void *)(txdesc[send_idx].Packet + send_doff);
emilmont 10:3bc89ef62ce7 592 psrc = (void *)(data + soff);
emilmont 10:3bc89ef62ce7 593 if(send_doff + copy > ETH_FRAG_SIZE) {
emilmont 10:3bc89ef62ce7 594 txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT);
emilmont 10:3bc89ef62ce7 595 send_idx = rinc(send_idx, NUM_TX_FRAG);
emilmont 10:3bc89ef62ce7 596 send_doff = 0;
emilmont 10:3bc89ef62ce7 597 }
emilmont 10:3bc89ef62ce7 598
emilmont 10:3bc89ef62ce7 599 if(data != NULL) {
emilmont 10:3bc89ef62ce7 600 memcpy(pdst, psrc, copy);
emilmont 10:3bc89ef62ce7 601 } else {
emilmont 10:3bc89ef62ce7 602 memset(pdst, 0, copy);
emilmont 10:3bc89ef62ce7 603 }
emilmont 10:3bc89ef62ce7 604
emilmont 10:3bc89ef62ce7 605 soff += copy;
emilmont 10:3bc89ef62ce7 606 send_doff += copy;
emilmont 10:3bc89ef62ce7 607 send_size += copy;
emilmont 10:3bc89ef62ce7 608 } while(soff != slen);
emilmont 10:3bc89ef62ce7 609
emilmont 10:3bc89ef62ce7 610 return soff;
emilmont 10:3bc89ef62ce7 611 #endif
emilmont 10:3bc89ef62ce7 612 }
emilmont 10:3bc89ef62ce7 613
emilmont 10:3bc89ef62ce7 614 int ethernet_send() {
emilmont 10:3bc89ef62ce7 615
emilmont 10:3bc89ef62ce7 616 #if NEW_LOGIC
emilmont 10:3bc89ef62ce7 617 if(tx_produce_offset < 0) { // no buffer active
emilmont 10:3bc89ef62ce7 618 return -1;
emilmont 10:3bc89ef62ce7 619 }
emilmont 10:3bc89ef62ce7 620
emilmont 10:3bc89ef62ce7 621 // ensure there is a link
emilmont 10:3bc89ef62ce7 622 if(!ethernet_link()) {
emilmont 10:3bc89ef62ce7 623 return -2;
emilmont 10:3bc89ef62ce7 624 }
emilmont 10:3bc89ef62ce7 625
emilmont 10:3bc89ef62ce7 626 // we have been writing in to a buffer, so finalise it
emilmont 10:3bc89ef62ce7 627 int size = tx_produce_offset;
emilmont 10:3bc89ef62ce7 628 int index = LPC_EMAC->TxProduceIndex;
emilmont 10:3bc89ef62ce7 629 txdesc[index].Ctrl = (tx_produce_offset-1) | (TCTRL_INT | TCTRL_LAST);
emilmont 10:3bc89ef62ce7 630
emilmont 10:3bc89ef62ce7 631 // Increment ProduceIndex to allow it to be sent
emilmont 10:3bc89ef62ce7 632 // We can only do this if the next slot is free
emilmont 10:3bc89ef62ce7 633 int next = rinc(index, NUM_TX_FRAG);
emilmont 10:3bc89ef62ce7 634 while(next == LPC_EMAC->TxConsumeIndex) {
emilmont 10:3bc89ef62ce7 635 for(int i=0; i<1000; i++) { __NOP(); }
emilmont 10:3bc89ef62ce7 636 }
emilmont 10:3bc89ef62ce7 637
emilmont 10:3bc89ef62ce7 638 LPC_EMAC->TxProduceIndex = next;
emilmont 10:3bc89ef62ce7 639 tx_produce_offset = -1;
emilmont 10:3bc89ef62ce7 640 return size;
emilmont 10:3bc89ef62ce7 641
emilmont 10:3bc89ef62ce7 642 #else
emilmont 10:3bc89ef62ce7 643 int s = send_size;
emilmont 10:3bc89ef62ce7 644 txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT | TCTRL_LAST);
emilmont 10:3bc89ef62ce7 645 send_idx = rinc(send_idx, NUM_TX_FRAG);
emilmont 10:3bc89ef62ce7 646 LPC_EMAC->TxProduceIndex = send_idx;
emilmont 10:3bc89ef62ce7 647 send_doff = 0;
emilmont 10:3bc89ef62ce7 648 send_idx = -1;
emilmont 10:3bc89ef62ce7 649 send_size = 0;
emilmont 10:3bc89ef62ce7 650 return s;
emilmont 10:3bc89ef62ce7 651 #endif
emilmont 10:3bc89ef62ce7 652 }
emilmont 10:3bc89ef62ce7 653
emilmont 10:3bc89ef62ce7 654 // RxConsmeIndex - The index of buffer the driver will/is reading from. Driver should inc once read
emilmont 10:3bc89ef62ce7 655 // RxProduceIndex - The index of buffer that will/is being filled by MAC. H/w will inc once rxd
emilmont 10:3bc89ef62ce7 656 //
emilmont 10:3bc89ef62ce7 657 // if(RxConsumeIndex == RxProduceIndex) buffer array is empty
emilmont 10:3bc89ef62ce7 658 // if(RxConsumeIndex == RxProduceIndex + 1) buffer array is full
emilmont 10:3bc89ef62ce7 659
emilmont 10:3bc89ef62ce7 660 // Recevies an arrived ethernet packet.
emilmont 10:3bc89ef62ce7 661 // Receiving an ethernet packet will drop the last received ethernet packet
emilmont 10:3bc89ef62ce7 662 // and make a new ethernet packet ready to read.
emilmont 10:3bc89ef62ce7 663 // Returns size of packet, else 0 if nothing to receive
emilmont 10:3bc89ef62ce7 664
emilmont 10:3bc89ef62ce7 665 // We read from RxConsumeIndex from position rx_consume_offset
emilmont 10:3bc89ef62ce7 666 // if rx_consume_offset < 0, then we have not recieved the RxConsumeIndex packet for reading
emilmont 10:3bc89ef62ce7 667 // rx_consume_offset = -1 // no frame
emilmont 10:3bc89ef62ce7 668 // rx_consume_offset = 0 // start of frame
emilmont 10:3bc89ef62ce7 669 // Assumption: A fragment should alway be a whole frame
emilmont 10:3bc89ef62ce7 670
emilmont 10:3bc89ef62ce7 671 int ethernet_receive() {
emilmont 10:3bc89ef62ce7 672 #if NEW_LOGIC
emilmont 10:3bc89ef62ce7 673
emilmont 10:3bc89ef62ce7 674 // if we are currently reading a valid RxConsume buffer, increment to the next one
emilmont 10:3bc89ef62ce7 675 if(rx_consume_offset >= 0) {
emilmont 10:3bc89ef62ce7 676 LPC_EMAC->RxConsumeIndex = rinc(LPC_EMAC->RxConsumeIndex, NUM_RX_FRAG);
emilmont 10:3bc89ef62ce7 677 }
emilmont 10:3bc89ef62ce7 678
emilmont 10:3bc89ef62ce7 679 // if the buffer is empty, mark it as no valid buffer
emilmont 10:3bc89ef62ce7 680 if(LPC_EMAC->RxConsumeIndex == LPC_EMAC->RxProduceIndex) {
emilmont 10:3bc89ef62ce7 681 rx_consume_offset = -1;
emilmont 10:3bc89ef62ce7 682 return 0;
emilmont 10:3bc89ef62ce7 683 }
emilmont 10:3bc89ef62ce7 684
emilmont 10:3bc89ef62ce7 685 uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info;
emilmont 10:3bc89ef62ce7 686 rx_consume_offset = 0;
emilmont 10:3bc89ef62ce7 687
emilmont 10:3bc89ef62ce7 688 // check if it is not marked as last or for errors
emilmont 10:3bc89ef62ce7 689 if(!(info & RINFO_LAST_FLAG) || (info & RINFO_ERR_MASK)) {
emilmont 10:3bc89ef62ce7 690 return -1;
emilmont 10:3bc89ef62ce7 691 }
emilmont 10:3bc89ef62ce7 692
emilmont 10:3bc89ef62ce7 693 int size = (info & RINFO_SIZE) + 1;
emilmont 10:3bc89ef62ce7 694 return size - 4; // don't include checksum bytes
emilmont 10:3bc89ef62ce7 695
emilmont 10:3bc89ef62ce7 696 #else
emilmont 10:3bc89ef62ce7 697 if(receive_idx == -1) {
emilmont 10:3bc89ef62ce7 698 receive_idx = LPC_EMAC->RxConsumeIndex;
emilmont 10:3bc89ef62ce7 699 } else {
bogdanm 19:398f4c622e1b 700 while(!(rxstat[receive_idx].Info & RINFO_LAST_FLAG) && ((uint32_t)receive_idx != LPC_EMAC->RxProduceIndex)) {
emilmont 10:3bc89ef62ce7 701 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
emilmont 10:3bc89ef62ce7 702 }
emilmont 10:3bc89ef62ce7 703 unsigned int info = rxstat[receive_idx].Info;
emilmont 10:3bc89ef62ce7 704 int slen = (info & RINFO_SIZE) + 1;
emilmont 10:3bc89ef62ce7 705
emilmont 10:3bc89ef62ce7 706 if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) {
emilmont 10:3bc89ef62ce7 707 /* Invalid frame, ignore it and free buffer. */
emilmont 10:3bc89ef62ce7 708 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
emilmont 10:3bc89ef62ce7 709 }
emilmont 10:3bc89ef62ce7 710 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
emilmont 10:3bc89ef62ce7 711 receive_soff = 0;
emilmont 10:3bc89ef62ce7 712
emilmont 10:3bc89ef62ce7 713 LPC_EMAC->RxConsumeIndex = receive_idx;
emilmont 10:3bc89ef62ce7 714 }
emilmont 10:3bc89ef62ce7 715
bogdanm 19:398f4c622e1b 716 if((uint32_t)receive_idx == LPC_EMAC->RxProduceIndex) {
emilmont 10:3bc89ef62ce7 717 receive_idx = -1;
emilmont 10:3bc89ef62ce7 718 return 0;
emilmont 10:3bc89ef62ce7 719 }
emilmont 10:3bc89ef62ce7 720
emilmont 10:3bc89ef62ce7 721 return (rxstat[receive_idx].Info & RINFO_SIZE) - 3;
emilmont 10:3bc89ef62ce7 722 #endif
emilmont 10:3bc89ef62ce7 723 }
emilmont 10:3bc89ef62ce7 724
emilmont 10:3bc89ef62ce7 725 // Read from an recevied ethernet packet.
emilmont 10:3bc89ef62ce7 726 // After receive returnd a number bigger than 0 it is
emilmont 10:3bc89ef62ce7 727 // possible to read bytes from this packet.
emilmont 10:3bc89ef62ce7 728 // Read will write up to size bytes into data.
emilmont 10:3bc89ef62ce7 729 // It is possible to use read multible times.
emilmont 10:3bc89ef62ce7 730 // Each time read will start reading after the last read byte before.
emilmont 10:3bc89ef62ce7 731
emilmont 10:3bc89ef62ce7 732 int ethernet_read(char *data, int dlen) {
emilmont 10:3bc89ef62ce7 733 #if NEW_LOGIC
emilmont 10:3bc89ef62ce7 734 // Check we have a valid buffer to read
emilmont 10:3bc89ef62ce7 735 if(rx_consume_offset < 0) {
emilmont 10:3bc89ef62ce7 736 return 0;
emilmont 10:3bc89ef62ce7 737 }
emilmont 10:3bc89ef62ce7 738
emilmont 10:3bc89ef62ce7 739 // Assume 1 fragment block
emilmont 10:3bc89ef62ce7 740 uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info;
emilmont 10:3bc89ef62ce7 741 int size = (info & RINFO_SIZE) + 1 - 4; // exclude checksum
emilmont 10:3bc89ef62ce7 742
emilmont 10:3bc89ef62ce7 743 int remaining = size - rx_consume_offset;
emilmont 10:3bc89ef62ce7 744 int requested = dlen;
emilmont 10:3bc89ef62ce7 745 int ncopy = min(remaining, requested);
emilmont 10:3bc89ef62ce7 746
emilmont 10:3bc89ef62ce7 747 void *psrc = (void *)(rxdesc[LPC_EMAC->RxConsumeIndex].Packet + rx_consume_offset);
emilmont 10:3bc89ef62ce7 748 void *pdst = (void *)(data);
emilmont 10:3bc89ef62ce7 749
emilmont 10:3bc89ef62ce7 750 if(data != NULL && ncopy > 0) {
emilmont 10:3bc89ef62ce7 751 memcpy(pdst, psrc, ncopy);
emilmont 10:3bc89ef62ce7 752 }
emilmont 10:3bc89ef62ce7 753
emilmont 10:3bc89ef62ce7 754 rx_consume_offset += ncopy;
emilmont 10:3bc89ef62ce7 755
emilmont 10:3bc89ef62ce7 756 return ncopy;
emilmont 10:3bc89ef62ce7 757 #else
emilmont 10:3bc89ef62ce7 758 int slen;
emilmont 10:3bc89ef62ce7 759 int copy = 0;
emilmont 10:3bc89ef62ce7 760 unsigned int more;
emilmont 10:3bc89ef62ce7 761 unsigned int info;
emilmont 10:3bc89ef62ce7 762 void *pdst, *psrc;
emilmont 10:3bc89ef62ce7 763 int doff = 0;
emilmont 10:3bc89ef62ce7 764
bogdanm 19:398f4c622e1b 765 if((uint32_t)receive_idx == LPC_EMAC->RxProduceIndex || receive_idx == -1) {
emilmont 10:3bc89ef62ce7 766 return 0;
emilmont 10:3bc89ef62ce7 767 }
emilmont 10:3bc89ef62ce7 768
emilmont 10:3bc89ef62ce7 769 do {
emilmont 10:3bc89ef62ce7 770 info = rxstat[receive_idx].Info;
emilmont 10:3bc89ef62ce7 771 more = !(info & RINFO_LAST_FLAG);
emilmont 10:3bc89ef62ce7 772 slen = (info & RINFO_SIZE) + 1;
emilmont 10:3bc89ef62ce7 773
emilmont 10:3bc89ef62ce7 774 if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) {
emilmont 10:3bc89ef62ce7 775 /* Invalid frame, ignore it and free buffer. */
emilmont 10:3bc89ef62ce7 776 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
emilmont 10:3bc89ef62ce7 777 } else {
emilmont 10:3bc89ef62ce7 778
emilmont 10:3bc89ef62ce7 779 copy = min(slen - receive_soff, dlen - doff);
emilmont 10:3bc89ef62ce7 780 psrc = (void *)(rxdesc[receive_idx].Packet + receive_soff);
emilmont 10:3bc89ef62ce7 781 pdst = (void *)(data + doff);
emilmont 10:3bc89ef62ce7 782
emilmont 10:3bc89ef62ce7 783 if(data != NULL) {
emilmont 10:3bc89ef62ce7 784 /* check if Buffer available */
emilmont 10:3bc89ef62ce7 785 memcpy(pdst, psrc, copy);
emilmont 10:3bc89ef62ce7 786 }
emilmont 10:3bc89ef62ce7 787
emilmont 10:3bc89ef62ce7 788 receive_soff += copy;
emilmont 10:3bc89ef62ce7 789 doff += copy;
emilmont 10:3bc89ef62ce7 790
emilmont 10:3bc89ef62ce7 791 if((more && (receive_soff == slen))) {
emilmont 10:3bc89ef62ce7 792 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
emilmont 10:3bc89ef62ce7 793 receive_soff = 0;
emilmont 10:3bc89ef62ce7 794 }
emilmont 10:3bc89ef62ce7 795 }
emilmont 10:3bc89ef62ce7 796 } while(more && !(doff == dlen) && !receive_soff);
emilmont 10:3bc89ef62ce7 797
emilmont 10:3bc89ef62ce7 798 return doff;
emilmont 10:3bc89ef62ce7 799 #endif
emilmont 10:3bc89ef62ce7 800 }
emilmont 10:3bc89ef62ce7 801
emilmont 10:3bc89ef62ce7 802 int ethernet_link(void) {
emilmont 10:3bc89ef62ce7 803
emilmont 10:3bc89ef62ce7 804 if (phy_id == DP83848C_ID) {
emilmont 10:3bc89ef62ce7 805 return (phy_read(PHY_REG_STS) & PHY_STS_LINK);
emilmont 10:3bc89ef62ce7 806 }
emilmont 10:3bc89ef62ce7 807 else { // LAN8720_ID
emilmont 10:3bc89ef62ce7 808 return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);
emilmont 10:3bc89ef62ce7 809 }
emilmont 10:3bc89ef62ce7 810 }
emilmont 10:3bc89ef62ce7 811
emilmont 10:3bc89ef62ce7 812 static int phy_write(unsigned int PhyReg, unsigned short Data) {
emilmont 10:3bc89ef62ce7 813 unsigned int timeOut;
emilmont 10:3bc89ef62ce7 814
emilmont 10:3bc89ef62ce7 815 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
emilmont 10:3bc89ef62ce7 816 LPC_EMAC->MWTD = Data;
emilmont 10:3bc89ef62ce7 817
emilmont 10:3bc89ef62ce7 818 for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) { /* Wait until operation completed */
emilmont 10:3bc89ef62ce7 819 if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
emilmont 10:3bc89ef62ce7 820 return 0;
emilmont 10:3bc89ef62ce7 821 }
emilmont 10:3bc89ef62ce7 822 }
emilmont 10:3bc89ef62ce7 823
emilmont 10:3bc89ef62ce7 824 return -1;
emilmont 10:3bc89ef62ce7 825 }
emilmont 10:3bc89ef62ce7 826
emilmont 10:3bc89ef62ce7 827
emilmont 10:3bc89ef62ce7 828 static int phy_read(unsigned int PhyReg) {
emilmont 10:3bc89ef62ce7 829 unsigned int timeOut;
emilmont 10:3bc89ef62ce7 830
emilmont 10:3bc89ef62ce7 831 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
emilmont 10:3bc89ef62ce7 832 LPC_EMAC->MCMD = MCMD_READ;
emilmont 10:3bc89ef62ce7 833
emilmont 10:3bc89ef62ce7 834 for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */
emilmont 10:3bc89ef62ce7 835 if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
emilmont 10:3bc89ef62ce7 836 LPC_EMAC->MCMD = 0;
emilmont 10:3bc89ef62ce7 837 return LPC_EMAC->MRDD; /* Return a 16-bit value. */
emilmont 10:3bc89ef62ce7 838 }
emilmont 10:3bc89ef62ce7 839 }
emilmont 10:3bc89ef62ce7 840
emilmont 10:3bc89ef62ce7 841 return -1;
emilmont 10:3bc89ef62ce7 842 }
emilmont 10:3bc89ef62ce7 843
emilmont 10:3bc89ef62ce7 844
emilmont 10:3bc89ef62ce7 845 static void txdscr_init() {
emilmont 10:3bc89ef62ce7 846 int i;
emilmont 10:3bc89ef62ce7 847
emilmont 10:3bc89ef62ce7 848 for(i = 0; i < NUM_TX_FRAG; i++) {
emilmont 10:3bc89ef62ce7 849 txdesc[i].Packet = (uint32_t)&txbuf[i];
emilmont 10:3bc89ef62ce7 850 txdesc[i].Ctrl = 0;
emilmont 10:3bc89ef62ce7 851 txstat[i].Info = 0;
emilmont 10:3bc89ef62ce7 852 }
emilmont 10:3bc89ef62ce7 853
emilmont 10:3bc89ef62ce7 854 LPC_EMAC->TxDescriptor = (uint32_t)txdesc; /* Set EMAC Transmit Descriptor Registers. */
emilmont 10:3bc89ef62ce7 855 LPC_EMAC->TxStatus = (uint32_t)txstat;
emilmont 10:3bc89ef62ce7 856 LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
emilmont 10:3bc89ef62ce7 857
emilmont 10:3bc89ef62ce7 858 LPC_EMAC->TxProduceIndex = 0; /* Tx Descriptors Point to 0 */
emilmont 10:3bc89ef62ce7 859 }
emilmont 10:3bc89ef62ce7 860
emilmont 10:3bc89ef62ce7 861
emilmont 10:3bc89ef62ce7 862 static void rxdscr_init() {
emilmont 10:3bc89ef62ce7 863 int i;
emilmont 10:3bc89ef62ce7 864
emilmont 10:3bc89ef62ce7 865 for(i = 0; i < NUM_RX_FRAG; i++) {
emilmont 10:3bc89ef62ce7 866 rxdesc[i].Packet = (uint32_t)&rxbuf[i];
emilmont 10:3bc89ef62ce7 867 rxdesc[i].Ctrl = RCTRL_INT | (ETH_FRAG_SIZE-1);
emilmont 10:3bc89ef62ce7 868 rxstat[i].Info = 0;
emilmont 10:3bc89ef62ce7 869 rxstat[i].HashCRC = 0;
emilmont 10:3bc89ef62ce7 870 }
emilmont 10:3bc89ef62ce7 871
emilmont 10:3bc89ef62ce7 872 LPC_EMAC->RxDescriptor = (uint32_t)rxdesc; /* Set EMAC Receive Descriptor Registers. */
emilmont 10:3bc89ef62ce7 873 LPC_EMAC->RxStatus = (uint32_t)rxstat;
emilmont 10:3bc89ef62ce7 874 LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1;
emilmont 10:3bc89ef62ce7 875
emilmont 10:3bc89ef62ce7 876 LPC_EMAC->RxConsumeIndex = 0; /* Rx Descriptors Point to 0 */
emilmont 10:3bc89ef62ce7 877 }
emilmont 10:3bc89ef62ce7 878
emilmont 10:3bc89ef62ce7 879 void ethernet_address(char *mac) {
emilmont 10:3bc89ef62ce7 880 mbed_mac_address(mac);
emilmont 10:3bc89ef62ce7 881 }
emilmont 10:3bc89ef62ce7 882
emilmont 10:3bc89ef62ce7 883 void ethernet_set_link(int speed, int duplex) {
emilmont 10:3bc89ef62ce7 884 unsigned short phy_data;
emilmont 10:3bc89ef62ce7 885 int tout;
emilmont 10:3bc89ef62ce7 886
emilmont 10:3bc89ef62ce7 887 if((speed < 0) || (speed > 1)) {
emilmont 10:3bc89ef62ce7 888
emilmont 10:3bc89ef62ce7 889 phy_data = PHY_AUTO_NEG;
emilmont 10:3bc89ef62ce7 890
emilmont 10:3bc89ef62ce7 891 } else {
emilmont 10:3bc89ef62ce7 892
emilmont 10:3bc89ef62ce7 893 phy_data = (((unsigned short) speed << 13) |
emilmont 10:3bc89ef62ce7 894 ((unsigned short) duplex << 8));
emilmont 10:3bc89ef62ce7 895 }
emilmont 10:3bc89ef62ce7 896
emilmont 10:3bc89ef62ce7 897 phy_write(PHY_REG_BMCR, phy_data);
emilmont 10:3bc89ef62ce7 898
emilmont 10:3bc89ef62ce7 899 for(tout = 100; tout; tout--) { __NOP(); } /* A short delay */
emilmont 10:3bc89ef62ce7 900
emilmont 10:3bc89ef62ce7 901 switch(phy_id) {
emilmont 10:3bc89ef62ce7 902 case DP83848C_ID:
emilmont 10:3bc89ef62ce7 903
emilmont 10:3bc89ef62ce7 904 phy_data = phy_read(PHY_REG_STS);
emilmont 10:3bc89ef62ce7 905
emilmont 10:3bc89ef62ce7 906 if(phy_data & PHY_STS_DUPLEX) {
emilmont 10:3bc89ef62ce7 907 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
emilmont 10:3bc89ef62ce7 908 LPC_EMAC->Command |= CR_FULL_DUP;
emilmont 10:3bc89ef62ce7 909 LPC_EMAC->IPGT = IPGT_FULL_DUP;
emilmont 10:3bc89ef62ce7 910 } else {
emilmont 10:3bc89ef62ce7 911 LPC_EMAC->MAC2 &= ~MAC2_FULL_DUP;
emilmont 10:3bc89ef62ce7 912 LPC_EMAC->Command &= ~CR_FULL_DUP;
emilmont 10:3bc89ef62ce7 913 LPC_EMAC->IPGT = IPGT_HALF_DUP;
emilmont 10:3bc89ef62ce7 914 }
emilmont 10:3bc89ef62ce7 915
emilmont 10:3bc89ef62ce7 916 if(phy_data & PHY_STS_SPEED) {
emilmont 10:3bc89ef62ce7 917 LPC_EMAC->SUPP &= ~SUPP_SPEED;
emilmont 10:3bc89ef62ce7 918 } else {
emilmont 10:3bc89ef62ce7 919 LPC_EMAC->SUPP |= SUPP_SPEED;
emilmont 10:3bc89ef62ce7 920 }
emilmont 10:3bc89ef62ce7 921
emilmont 10:3bc89ef62ce7 922
emilmont 10:3bc89ef62ce7 923 break;
emilmont 10:3bc89ef62ce7 924 case LAN8720_ID:
emilmont 10:3bc89ef62ce7 925
emilmont 10:3bc89ef62ce7 926 phy_data = phy_read(PHY_REG_SCSR);
emilmont 10:3bc89ef62ce7 927
emilmont 10:3bc89ef62ce7 928 if (phy_data & PHY_SCSR_DUPLEX) {
emilmont 10:3bc89ef62ce7 929 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
emilmont 10:3bc89ef62ce7 930 LPC_EMAC->Command |= CR_FULL_DUP;
emilmont 10:3bc89ef62ce7 931 LPC_EMAC->IPGT = IPGT_FULL_DUP;
emilmont 10:3bc89ef62ce7 932 } else {
emilmont 10:3bc89ef62ce7 933 LPC_EMAC->Command &= ~CR_FULL_DUP;
emilmont 10:3bc89ef62ce7 934 LPC_EMAC->IPGT = IPGT_HALF_DUP;
emilmont 10:3bc89ef62ce7 935 }
emilmont 10:3bc89ef62ce7 936
emilmont 10:3bc89ef62ce7 937 if(phy_data & PHY_SCSR_100MBIT) {
emilmont 10:3bc89ef62ce7 938 LPC_EMAC->SUPP |= SUPP_SPEED;
emilmont 10:3bc89ef62ce7 939 } else {
emilmont 10:3bc89ef62ce7 940 LPC_EMAC->SUPP &= ~SUPP_SPEED;
emilmont 10:3bc89ef62ce7 941 }
emilmont 10:3bc89ef62ce7 942
emilmont 10:3bc89ef62ce7 943
emilmont 10:3bc89ef62ce7 944 break;
emilmont 10:3bc89ef62ce7 945 }
emilmont 10:3bc89ef62ce7 946
emilmont 10:3bc89ef62ce7 947
emilmont 10:3bc89ef62ce7 948 }