]> rtime.felk.cvut.cz Git - rpp-test-sw.git/blob - rpp-test-sw/commands/cmd_emac.c
Convert doc from MediaWiki syntax to Markdown
[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         } else if (data & PHY_100BASETX_m) {
188                 EMACDuplexSet(emacBase, EMAC_DUPLEX_HALF);
189                 dummy_wait();
190         } else {
191                 while(1)
192                         ;
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                         }
237                 }
238                 dummy_wait();
239                 intvect = EMACIntVectorGet(emacBase);
240                 intvectraw = EMACIntVectorRawGet(emacBase);
241         }
242
243         /* Dummy RX */
244         {
245                 char rx_fr[10];
246                 int i;
247
248                 rpp_sci_printf("Trying to receive some data\r\n");
249                 EMACRxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
250
251                 for (j = 0; j < 8; j++) {
252                         while (!(rx_desc->PktFlgLen & EMAC_DSC_FLAG_SOP))
253                                 if(rpp_sci_read_nb(1, &input) == SUCCESS){
254                                         return -1;
255                                 }
256                                 ;
257
258                         rpp_sci_printf("Received packet:\r\n");
259                         rpp_sci_printf("Length: %d\r\n", rx_desc->PktFlgLen & 0xffff);
260
261                         for (i = 0; i < (rx_desc->PktFlgLen & 0xffff); i++) {
262                                 i2str(rx_fr, rx_desc->pBuffer[i], 0, 16);
263                                 rpp_sci_printf("%x ", rx_desc->pBuffer[i]);
264                                 if (((i+1) % 8) == 0)
265                                         rpp_sci_printf("\r\n");
266                         }
267
268                         /* Reinitialize RX buffer */
269                         rx_desc->pBuffer = rx_buff;
270                         rx_desc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
271                         rx_desc->pNext = NULL;
272                         rx_desc->BufOffLen = BUFF_SIZE;
273                         EMACRxHdrDescPtrWrite(emacBase, (unsigned int)rx_desc, channel);
274                         rpp_sci_printf("\r\n-------------------------------------------\r\n");
275                 }
276
277                 EMACRxIntPulseDisable(emacBase, emacCtrlBase, 0, channel);
278         }
279
280
281
282         return 0;
283 }
284
285 #endif  /* DOCGEN */
286
287 cmd_des_t const cmd_des_test_ethernet={
288     0, 0,
289     "ethernet", "Temporary command to test Ethernet communication",
290     "### Command syntax ###\n"
291     "\n"
292     "    ethernet\n"
293     "\n"
294     "### Description ###\n"
295     "\n"
296     "Command tries to send a few ethernet frames. No real connection or\n"
297     "meaningful packets are sent. This only tests, if Ethernet is just\n"
298     "working.\n",
299     CMD_HANDLER(emac_test), (void *)&cmd_list_emac
300 };
301
302 cmd_des_t const *cmd_list_emac[]={
303   &cmd_des_test_ethernet,
304   NULL
305 };