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