]> rtime.felk.cvut.cz Git - pes-rpp/rpp-test-sw.git/blob - rpp-test-sw/commands/cmd_emac.c
Change license to MIT
[pes-rpp/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  * Permission is hereby granted, free of charge, to any person
10  * obtaining a copy of this software and associated documentation
11  * files (the "Software"), to deal in the Software without
12  * restriction, including without limitation the rights to use,
13  * copy, modify, merge, publish, distribute, sublicense, and/or sell
14  * copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following
16  * conditions:
17  *
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  *
30  * File : cmd_emac.c
31  *
32  * Abstract:
33  *              Test command for Ethernet PHY
34  *
35  */
36 #include "cmd_emac.h"
37
38 #ifndef DOCGEN
39
40 #include "rpp/rpp.h"
41 #include "sys/sys.h"
42 #include "sys/phy_dp83848h.h"
43 #include "types.h"
44
45 /* ************************************************* */
46 /*   Emac frame buffer related stuff                 */
47 /* ************************************************* */
48 typedef struct _EMAC_Desc {
49         struct _EMAC_Desc *pNext;   /* Pointer to next descriptor in chain */
50         uint8_t *pBuffer;           /* Pointer to data buffer */
51         uint32_t BufOffLen;         /* Buffer Offset(MSW) and Length(LSW) */
52         uint32_t PktFlgLen;         /* Packet Flags(MSW) and Length(LSW) */
53 } EMAC_Desc;
54
55 /* Packet Flags */
56 #define EMAC_DSC_FLAG_SOP           0x80000000u
57 #define EMAC_DSC_FLAG_EOP           0x40000000u
58 #define EMAC_DSC_FLAG_OWNER         0x20000000u
59 #define EMAC_DSC_FLAG_EOQ           0x10000000u
60 #define EMAC_DSC_FLAG_TDOWNCMPLT    0x08000000u
61 #define EMAC_DSC_FLAG_PASSCRC       0x04000000u
62
63 /* ************************************************* */
64 /*   Ethernet frame                                  */
65 /* ************************************************* */
66 typedef struct {
67         uint8_t destination[6];
68         uint8_t source[6];
69         uint16_t len;
70         uint8_t data[50];
71         uint32_t fcs;
72 } eth_frame_t;
73
74 /* ************************************************* */
75
76
77
78 unsigned int emacCtrlBase   = EMAC_CTRL_BASE;
79 unsigned int emacBase       = EMAC_BASE;
80 unsigned int emacCtrlRamBase    = EMAC_CTRL_RAM_BASE;
81 unsigned int mdioBase       = MDIO_BASE;
82
83 int rx_irq_cnt; /* Interrupt counters */
84 int tx_irq_cnt;
85
86 unsigned int phyalive;
87 unsigned int phylink;
88
89 unsigned int intvect;
90 unsigned int intvectraw;
91
92 /* 
93  * Emac address is used only in this debugging tool. During emac_test is't called rpp_init().
94  * MAC address defined in eth.h have no efect in this test file.
95  */
96  
97 uint8_t emacAddress[6]  = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
98 uint32_t emacPhyAddress = 0x1;  /* Address of PHY on "MDIO bus"
99                                    (depends on PHY configuration) */
100 int channel = 0;    /* Emac has 8 RX and TX channels; we use only one */
101
102 EMAC_Desc fr1 __attribute__((aligned(4)));  /* Frame descriptor of Ethernet frame to be sent */
103
104 /* Frame descriptor used for receiving frames --
105    it might be placed in normal RAM or in CPPI ram of EMAC */
106 //EMAC_Desc rx_desc __attribute__((aligned(4)));
107 volatile EMAC_Desc *rx_desc = ((EMAC_Desc *)EMAC_CTRL_RAM_BASE);
108
109
110 #define BUFF_SIZE   2048
111 uint8_t rx_buff[BUFF_SIZE]; /* Buffer for data reception */
112
113 eth_frame_t efr1;   /* Buffer for TX -- Before sending some data we have to
114                        prepare it in "Ethernet frame" format */
115
116
117 void dummy_wait()
118 {
119         volatile int i;
120
121         for (i = 0; i < 65555; i++)
122                 ;
123 }
124
125 int emac_test(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
126 {
127         int chan;
128         unsigned char input = 0;
129         volatile unsigned int delay = 0xfff;
130         unsigned short data;
131         int j;
132
133 #ifdef TARGET_TMS570_RPP
134         /* Deactivate reset pin of PHY */
135         dmmREG->PC4 = (1 << DMM_CLK); /* Set to H */
136         dummy_wait();
137         dmmREG->PC5 = (1 << DMM_CLK); /* Set to L */
138         dummy_wait();
139         dmmREG->PC4 = (1 << DMM_CLK); /* Set to H */
140         dummy_wait();
141 #endif
142
143         /* Prepare RX Packet buffer descriptor */
144         rx_desc->pBuffer = rx_buff;
145         rx_desc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
146         rx_desc->pNext = NULL;
147         rx_desc->BufOffLen = BUFF_SIZE;
148
149
150         /* Fill some testing Ethernet frame with relevant data */
151         efr1.destination[0] = 0x00;
152         efr1.destination[1] = 0x21;
153         efr1.destination[2] = 0x70;
154         efr1.destination[3] = 0xb5;
155         efr1.destination[4] = 0x4b;
156         efr1.destination[5] = 0xea;
157         efr1.source[0]      = 0xff;
158         efr1.source[1]      = 0xff;
159         efr1.source[2]      = 0xff;
160         efr1.source[3]      = 0xff;
161         efr1.source[4]      = 0xff;
162         efr1.source[5]      = 0xff;
163
164         efr1.len = 46;
165         efr1.data[0] = 0xaa;
166
167         _enable_IRQ();
168         _enable_FIQ();
169
170
171         EMACInit(emacCtrlBase, emacBase);
172         MDIOInit(mdioBase, 0x0, 0x0);
173         dummy_wait();   // FIXME
174
175         EMACMACSrcAddrSet(emacBase, emacAddress);
176         /*  Be sure to program all eight MAC address registers -
177          *  whether the receive channel is to be enabled or not.
178          */
179         for (chan = 0; chan < 8; chan++)
180                 EMACMACAddrSet(emacBase, chan, emacAddress, EMAC_MACADDR_NO_MATCH_NO_FILTER);
181
182         phyalive = MDIOPhyAliveStatusGet(mdioBase);
183         if (!phyalive) {
184                 rpp_sci_printf("PHY not alive\r\n");
185                 return -1;
186         }
187
188         phylink = MDIOPhyLinkStatusGet(mdioBase);
189         if (!phylink)
190                 rpp_sci_printf("PHY link down\r\n");
191         else
192                 rpp_sci_printf("PHY link up\r\n");
193
194         rpp_sci_printf("Configuring PHY and EMAC...\r\n");
195         PHY_auto_negotiate(mdioBase, emacPhyAddress, PHY_100BASETXDUPL_m | PHY_100BASETX_m | PHY_10BASETDUPL_m | PHY_10BASET_m);
196
197         /* Set the EMAC with the negotiation results if it is successful */
198         PHY_partner_ability_get(mdioBase, emacPhyAddress, &data);
199         if (data & PHY_100BASETXDUPL_m) {
200                 EMACDuplexSet(emacBase, EMAC_DUPLEX_FULL);
201                 dummy_wait();
202         }
203         else if (data & PHY_100BASETX_m) {
204                 EMACDuplexSet(emacBase, EMAC_DUPLEX_HALF);
205                 dummy_wait();
206         }
207         else
208                 while (1)
209                         ;
210
211         for (chan = 0; chan < 8; chan++) {
212                 EMACTxHdrDescPtrWrite(emacBase, 0, chan);
213                 EMACRxHdrDescPtrWrite(emacBase, 0, chan);
214         }
215
216         //EMACCoreIntAck(emacBase, EMAC_INT_CORE0_RX);
217         //EMACCoreIntAck(emacBase, EMAC_INT_CORE0_TX);
218
219         EMACRxBroadCastEnable(emacBase, channel);
220         EMACRxPromiscEnable(emacBase, channel);
221
222         EMACTxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
223         EMACRxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
224
225         EMACRxHdrDescPtrWrite(emacBase, (unsigned int)rx_desc, channel);
226
227         //EMACRxUnicastSet(emacBase, 0);
228         EMACTxEnable(emacBase);
229         EMACRxEnable(emacBase);
230
231         EMACMIIEnable(emacBase);
232
233         phylink = MDIOPhyLinkStatusGet(mdioBase);
234         if (!phylink)
235                 rpp_sci_printf("PHY link down\r\n");
236         else
237                 rpp_sci_printf("PHY link up\r\n");
238
239
240         /* TX */
241         for (j = 0; j < 8; j++) {
242                 fr1.pNext = NULL;
243                 fr1.pBuffer = (uint8_t *)&efr1;
244                 fr1.BufOffLen = 65;
245                 fr1.PktFlgLen = (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_EOP | EMAC_DSC_FLAG_OWNER | 65);
246
247                 EMACTxHdrDescPtrWrite(emacBase, (unsigned int)&fr1, channel);
248                 rpp_sci_printf("Packet sent\r\n");
249                 while (fr1.PktFlgLen == EMAC_DSC_FLAG_OWNER)
250                         if (rpp_sci_read_nb(1, &input) == SUCCESS)
251                                 return -1;
252                 dummy_wait();
253                 intvect = EMACIntVectorGet(emacBase);
254                 intvectraw = EMACIntVectorRawGet(emacBase);
255         }
256
257         /* Dummy RX */
258         {
259                 char rx_fr[10];
260                 int i;
261
262                 rpp_sci_printf("Trying to receive some data\r\n");
263                 EMACRxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
264
265                 for (j = 0; j < 8; j++) {
266                         while (!(rx_desc->PktFlgLen & EMAC_DSC_FLAG_SOP))
267                                 if (rpp_sci_read_nb(1, &input) == SUCCESS)
268                                         return -1;
269
270                         ;
271
272                         rpp_sci_printf("Received packet:\r\n");
273                         rpp_sci_printf("Length: %d\r\n", rx_desc->PktFlgLen & 0xffff);
274
275                         for (i = 0; i < (rx_desc->PktFlgLen & 0xffff); i++) {
276                                 i2str(rx_fr, rx_desc->pBuffer[i], 0, 16);
277                                 rpp_sci_printf("%x ", rx_desc->pBuffer[i]);
278                                 if (((i+1) % 8) == 0)
279                                         rpp_sci_printf("\r\n");
280                         }
281
282                         /* Reinitialize RX buffer */
283                         rx_desc->pBuffer = rx_buff;
284                         rx_desc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
285                         rx_desc->pNext = NULL;
286                         rx_desc->BufOffLen = BUFF_SIZE;
287                         EMACRxHdrDescPtrWrite(emacBase, (unsigned int)rx_desc, channel);
288                         rpp_sci_printf("\r\n-------------------------------------------\r\n");
289                 }
290
291                 EMACRxIntPulseDisable(emacBase, emacCtrlBase, 0, channel);
292         }
293
294
295
296         return 0;
297 }
298
299 #endif  /* DOCGEN */
300
301 cmd_des_t const cmd_des_test_ethernet = {
302         0, 0,
303         "ethernet", "Temporary command to test Ethernet communication",
304         "### Command syntax ###\n"
305         "\n"
306         "    ethernet\n"
307         "\n"
308         "### Description ###\n"
309         "\n"
310         "Command tries to send a few ethernet frames. No real connection or\n"
311         "meaningful packets are sent. This only tests, if Ethernet is just\n"
312         "working.\n",
313         CMD_HANDLER(emac_test), (void *)&cmd_list_emac
314 };
315
316 cmd_des_t const *cmd_list_emac[] = {
317         &cmd_des_test_ethernet,
318         NULL
319 };