]> rtime.felk.cvut.cz Git - rpp-test-sw.git/blob - rpp-test-sw/commands/cmd_emac.c
Merge branch 'master' of rtime.felk.cvut.cz:rpp-test-sw
[rpp-test-sw.git] / rpp-test-sw / commands / cmd_emac.c
1 /*
2  * Copyright (C) 2012-2013 Czech Technical University in Prague
3  *
4  * Created on: 28.2.2013
5  *
6  * Authors:
7  *     - Rostislav LisovĂ˝
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  * File : cmd_emac.c
23  *
24  * Abstract:
25  *              Test command for Ethernet PHY
26  *
27  */
28 #include "cmd_emac.h"
29
30 #ifndef DOCGEN
31
32 #include "rpp/rpp.h"
33 #include "sys/sys.h"
34 #include "sys/phy_dp83848h.h"
35 #include "types.h"
36
37 /* ************************************************* */
38 /*   Emac frame buffer related stuff                 */
39 /* ************************************************* */
40 typedef struct _EMAC_Desc {
41         struct _EMAC_Desc *pNext;   /* Pointer to next descriptor in chain */
42         uint8_t *pBuffer;           /* Pointer to data buffer */
43         uint32_t BufOffLen;         /* Buffer Offset(MSW) and Length(LSW) */
44         uint32_t PktFlgLen;         /* Packet Flags(MSW) and Length(LSW) */
45 } EMAC_Desc;
46
47 /* Packet Flags */
48 #define EMAC_DSC_FLAG_SOP           0x80000000u
49 #define EMAC_DSC_FLAG_EOP           0x40000000u
50 #define EMAC_DSC_FLAG_OWNER         0x20000000u
51 #define EMAC_DSC_FLAG_EOQ           0x10000000u
52 #define EMAC_DSC_FLAG_TDOWNCMPLT    0x08000000u
53 #define EMAC_DSC_FLAG_PASSCRC       0x04000000u
54
55 /* ************************************************* */
56 /*   Ethernet frame                                  */
57 /* ************************************************* */
58 typedef struct {
59         uint8_t destination[6];
60         uint8_t source[6];
61         uint16_t len;
62         uint8_t data[50];
63         uint32_t fcs;
64 } eth_frame_t;
65
66 /* ************************************************* */
67
68
69
70 unsigned int emacCtrlBase   = EMAC_CTRL_BASE;
71 unsigned int emacBase       = EMAC_BASE;
72 unsigned int emacCtrlRamBase    = EMAC_CTRL_RAM_BASE;
73 unsigned int mdioBase       = MDIO_BASE;
74
75 int rx_irq_cnt; /* Interrupt counters */
76 int tx_irq_cnt;
77
78 unsigned int phyalive;
79 unsigned int phylink;
80
81 unsigned int intvect;
82 unsigned int intvectraw;
83
84 uint8_t emacAddress[6]  = {0x12, 0x34, 0x56, 0x78, 0x90, 0xab};
85 uint32_t emacPhyAddress = 0x1;  /* Address of PHY on "MDIO bus"
86                                    (depends on PHY configuration) */
87 int channel = 0;    /* Emac has 8 RX and TX channels; we use only one */
88
89 EMAC_Desc fr1 __attribute__((aligned(4)));  /* Frame descriptor of Ethernet frame to be sent */
90
91 /* Frame descriptor used for receiving frames --
92    it might be placed in normal RAM or in CPPI ram of EMAC */
93 //EMAC_Desc rx_desc __attribute__((aligned(4)));
94 volatile EMAC_Desc *rx_desc = ((EMAC_Desc *)EMAC_CTRL_RAM_BASE);
95
96
97 #define BUFF_SIZE   2048
98 uint8_t rx_buff[BUFF_SIZE]; /* Buffer for data reception */
99
100 eth_frame_t efr1;   /* Buffer for TX -- Before sending some data we have to
101                        prepare it in "Ethernet frame" format */
102
103
104 void dummy_wait()
105 {
106         volatile int i;
107
108         for (i = 0; i < 65555; i++)
109                 ;
110 }
111
112 int emac_test(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
113 {
114         int chan;
115         unsigned char input = 0;
116         volatile unsigned int delay = 0xfff;
117         unsigned short data;
118         int j;
119
120         /* Deactivate reset pin of PHY */
121         dmmREG->PC4 = (1 << DMM_CLK); /* Set to H */
122         dummy_wait();
123         dmmREG->PC5 = (1 << DMM_CLK); /* Set to L */
124         dummy_wait();
125         dmmREG->PC4 = (1 << DMM_CLK); /* Set to H */
126         dummy_wait();
127
128         /* Prepare RX Packet buffer descriptor */
129         rx_desc->pBuffer = rx_buff;
130         rx_desc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
131         rx_desc->pNext = NULL;
132         rx_desc->BufOffLen = BUFF_SIZE;
133
134
135         /* Fill some testing Ethernet frame with relevant data */
136         efr1.destination[0] = 0x00;
137         efr1.destination[1] = 0x21;
138         efr1.destination[2] = 0x70;
139         efr1.destination[3] = 0xb5;
140         efr1.destination[4] = 0x4b;
141         efr1.destination[5] = 0xea;
142         efr1.source[0]      = 0xff;
143         efr1.source[1]      = 0xff;
144         efr1.source[2]      = 0xff;
145         efr1.source[3]      = 0xff;
146         efr1.source[4]      = 0xff;
147         efr1.source[5]      = 0xff;
148
149         efr1.len = 46;
150         efr1.data[0] = 0xaa;
151
152         _enable_IRQ();
153         _enable_FIQ();
154
155
156         EMACInit(emacCtrlBase, emacBase);
157         MDIOInit(mdioBase, 0x0, 0x0);
158         dummy_wait();   // FIXME
159
160         EMACMACSrcAddrSet(emacBase, emacAddress);
161         /*  Be sure to program all eight MAC address registers -
162          *  whether the receive channel is to be enabled or not.
163          */
164         for (chan = 0; chan < 8; chan++)
165                 EMACMACAddrSet(emacBase, chan, emacAddress, EMAC_MACADDR_NO_MATCH_NO_FILTER);
166
167         phyalive = MDIOPhyAliveStatusGet(mdioBase);
168         if (!phyalive) {
169                 rpp_sci_printf("PHY not alive\r\n");
170                 return -1;
171         }
172
173         phylink = MDIOPhyLinkStatusGet(mdioBase);
174         if (!phylink)
175                 rpp_sci_printf("PHY link down\r\n");
176         else
177                 rpp_sci_printf("PHY link up\r\n");
178
179         rpp_sci_printf("Configuring PHY and EMAC...\r\n");
180         PHY_auto_negotiate(mdioBase, emacPhyAddress, PHY_100BASETXDUPL_m | PHY_100BASETX_m | PHY_10BASETDUPL_m | PHY_10BASET_m);
181
182         /* Set the EMAC with the negotiation results if it is successful */
183         PHY_partner_ability_get(mdioBase, emacPhyAddress, &data);
184         if (data & PHY_100BASETXDUPL_m) {
185                 EMACDuplexSet(emacBase, EMAC_DUPLEX_FULL);
186                 dummy_wait();
187         }
188         else if (data & PHY_100BASETX_m) {
189                 EMACDuplexSet(emacBase, EMAC_DUPLEX_HALF);
190                 dummy_wait();
191         }
192         else
193                 while (1)
194                         ;
195
196         for (chan = 0; chan < 8; chan++) {
197                 EMACTxHdrDescPtrWrite(emacBase, 0, chan);
198                 EMACRxHdrDescPtrWrite(emacBase, 0, chan);
199         }
200
201         //EMACCoreIntAck(emacBase, EMAC_INT_CORE0_RX);
202         //EMACCoreIntAck(emacBase, EMAC_INT_CORE0_TX);
203
204         EMACRxBroadCastEnable(emacBase, channel);
205         EMACRxPromiscEnable(emacBase, channel);
206
207         EMACTxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
208         EMACRxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
209
210         EMACRxHdrDescPtrWrite(emacBase, (unsigned int)rx_desc, channel);
211
212         //EMACRxUnicastSet(emacBase, 0);
213         EMACTxEnable(emacBase);
214         EMACRxEnable(emacBase);
215
216         EMACMIIEnable(emacBase);
217
218         phylink = MDIOPhyLinkStatusGet(mdioBase);
219         if (!phylink)
220                 rpp_sci_printf("PHY link down\r\n");
221         else
222                 rpp_sci_printf("PHY link up\r\n");
223
224
225         /* TX */
226         for (j = 0; j < 8; j++) {
227                 fr1.pNext = NULL;
228                 fr1.pBuffer = (uint8_t *)&efr1;
229                 fr1.BufOffLen = 65;
230                 fr1.PktFlgLen = (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_EOP | EMAC_DSC_FLAG_OWNER | 65);
231
232                 EMACTxHdrDescPtrWrite(emacBase, (unsigned int)&fr1, channel);
233                 rpp_sci_printf("Packet sent\r\n");
234                 while (fr1.PktFlgLen == EMAC_DSC_FLAG_OWNER)
235                         if (rpp_sci_read_nb(1, &input) == SUCCESS)
236                                 return -1;
237                 dummy_wait();
238                 intvect = EMACIntVectorGet(emacBase);
239                 intvectraw = EMACIntVectorRawGet(emacBase);
240         }
241
242         /* Dummy RX */
243         {
244                 char rx_fr[10];
245                 int i;
246
247                 rpp_sci_printf("Trying to receive some data\r\n");
248                 EMACRxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
249
250                 for (j = 0; j < 8; j++) {
251                         while (!(rx_desc->PktFlgLen & EMAC_DSC_FLAG_SOP))
252                                 if (rpp_sci_read_nb(1, &input) == SUCCESS)
253                                         return -1;
254
255                         ;
256
257                         rpp_sci_printf("Received packet:\r\n");
258                         rpp_sci_printf("Length: %d\r\n", rx_desc->PktFlgLen & 0xffff);
259
260                         for (i = 0; i < (rx_desc->PktFlgLen & 0xffff); i++) {
261                                 i2str(rx_fr, rx_desc->pBuffer[i], 0, 16);
262                                 rpp_sci_printf("%x ", rx_desc->pBuffer[i]);
263                                 if (((i+1) % 8) == 0)
264                                         rpp_sci_printf("\r\n");
265                         }
266
267                         /* Reinitialize RX buffer */
268                         rx_desc->pBuffer = rx_buff;
269                         rx_desc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
270                         rx_desc->pNext = NULL;
271                         rx_desc->BufOffLen = BUFF_SIZE;
272                         EMACRxHdrDescPtrWrite(emacBase, (unsigned int)rx_desc, channel);
273                         rpp_sci_printf("\r\n-------------------------------------------\r\n");
274                 }
275
276                 EMACRxIntPulseDisable(emacBase, emacCtrlBase, 0, channel);
277         }
278
279
280
281         return 0;
282 }
283
284 #endif  /* DOCGEN */
285
286 cmd_des_t const cmd_des_test_ethernet = {
287         0, 0,
288         "ethernet", "Temporary command to test Ethernet communication",
289         "### Command syntax ###\n"
290         "\n"
291         "    ethernet\n"
292         "\n"
293         "### Description ###\n"
294         "\n"
295         "Command tries to send a few ethernet frames. No real connection or\n"
296         "meaningful packets are sent. This only tests, if Ethernet is just\n"
297         "working.\n",
298         CMD_HANDLER(emac_test), (void *)&cmd_list_emac
299 };
300
301 cmd_des_t const *cmd_list_emac[] = {
302         &cmd_des_test_ethernet,
303         NULL
304 };