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