added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

Who changed what in which revision?

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