UART: Start adding UART code
[keystone-rtos/ibl.git] / src / ethboot / ethboot.c
1 /*
2  *
3  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 
4  * 
5  * 
6  *  Redistribution and use in source and binary forms, with or without 
7  *  modification, are permitted provided that the following conditions 
8  *  are met:
9  *
10  *    Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  *    Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the 
15  *    documentation and/or other materials provided with the   
16  *    distribution.
17  *
18  *    Neither the name of Texas Instruments Incorporated nor the names of
19  *    its contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
26  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
27  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
28  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
31  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
32  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34 */
38 /*********************************************************************************
39  * FILE PURPOSE: The Ethernet boot wrapper
40  *********************************************************************************
41  * FILE NAME: ethboot.c
42  *
43  * DESCRIPTION: This file provides the ethernet boot wrapper used by IBL modules
44  *
45  * @file ethboot.c
46  *
47  * @brief
48  *   The ethernet boot wrapper
49  *
50  ***********************************************************************************/
51 #include "types.h"
52 #include "ibl.h"
53 #include "iblloc.h"
54 #include "ethboot.h"
55 #include "net.h"
56 #include "cpmacdrv.h"
57 #include "sgmii.h"
58 #include "device.h"
59 #include "mdioapi.h"
60 #include <string.h>
61 #include "net_osal.h"
62 #include "cpsw_api.h"
63 #include "qm_api.h"
64 #include "cpdma_api.h"
66 /**
67  *  @brief Remove the possible re-definition of iblEthBoot. iblcfg.h defines this to be a void
68  *         statement if there is no ethernet boot support. It must be re-enabled for the compile
69  */
70 #ifdef iblEthBoot
71  #undef iblEthBoot
72 #endif
74 /* Convert an IP address from unsigned char to IPN (uint32) */
75 #define FORM_IPN(x)     (  (x[0] << 24) | \
76                            (x[1] << 16) | \
77                            (x[2] <<  8) | \
78                            (x[3] <<  0) )
80 #define UNFORM_IPN(x,y)  (x)[0] = (y) >> 24;  \
81                          (x)[1] = (y) >> 16;  \
82                          (x)[2] = (y) >>  8;  \
83                          (x)[3] = (y) >>  0
85 #define MIN(a,b)         ((a) < (b)) ? (a) : (b)
87 static bool have_params;
89 /* Receive a call back when the boot file name is known */
90 void ibl_rec_params (void *params)
91 {
92     NET_DRV_DEVICE *netdev = (NET_DRV_DEVICE *)params;
94     have_params = TRUE;
96     /* Copy the information to the status fields */
97     UNFORM_IPN(iblStatus.ethParams.ipAddr, netdev->ip_address);
98     UNFORM_IPN(iblStatus.ethParams.serverIp, netdev->server_ip);
100     netMemcpy (iblStatus.ethParams.hwAddress, netdev->mac_address, sizeof(iblStatus.ethParams.hwAddress));
101     strncpy (iblStatus.ethParams.fileName, netdev->file_name, sizeof(iblStatus.ethParams.fileName));
106 void iblEthBoot (Int32 eIdx)
108     NET_DRV_DEVICE nDevice;
109     Uint32  nl;
110     Uint32  entry;
111     Int32   n;
112     Int32   dataSize;
113     Int32   format;
114     void    (*exit)();
115     uint8   buf[16];
116     char    *ext;
117     unsigned int i,j;
119     /* Power up the device. No action is taken if the device is already powered up */
120     if (devicePowerPeriph (TARGET_PWR_ETH(ibl.bootModes[eIdx].port)) < 0)
121         return;
123     /* Do any mdio configuration */
124     if (ibl.mdioConfig.nMdioOps > 0)
125         hwMdio (ibl.mdioConfig.nMdioOps, ibl.mdioConfig.mdio, 
126                 ibl.mdioConfig.mdioClkDiv, ibl.mdioConfig.interDelay);
128     for (j = 0; j < 0x100; j++)
129         for (i = 0; i < 0x1000000; i++);
131     /* SGMII configuration. If sgmii is not present this statement is defined
132      * to void in target.h */
133     for (n = 0; n < ibl_N_ETH_PORTS; n++)  {
134         if (ibl.sgmiiConfig[n].configure == TRUE)
135             hwSgmiiConfig (n, &ibl.sgmiiConfig[n]);
136     }
139 #ifdef DEVICE_CPSW
140     /* On chip switch configuration */
141     hwCpswConfig (targetGetSwitchCtl(), targetGetSwitchMaxPktSize());
142 #endif
145 #ifdef DEVICE_QM
146     /* Queue manager configuration */
147     hwQmSetup ((qmConfig_t *)(targetGetQmConfig()));
148     targetInitQs ();
149 #endif
150     
152 #ifdef DEVICE_CPDMA
153     /* Cpdma configuration. */
154     hwCpdmaRxConfig ((cpdmaRxCfg_t *)targetGetCpdmaRxConfig());
155     hwCpdmaTxConfig ((cpdmaTxCfg_t *)targetGetCpdmaTxConfig());
156 #endif
159 #ifdef DEVICE_PA
160     /* Packet accelerator configuration. If PA is not present this statement is defined
161      * to void in target.h */
162     targetPaConfig(ibl.bootModes[eIdx].u.ethBoot.ethInfo.hwAddress);
163 #endif
166 #ifdef DEVICE_SS
167     /* Streaming switch configuration. If not present this statement is defined to void
168      * in target.h.  If present this is usually defined to a series of register writes */
169     hwConfigStreamingSwitch();
170 #endif
172     nDevice.port_num = ibl.bootModes[eIdx].port;
174     /* Simple transation to initialize the driver */
175     netMemcpy (nDevice.mac_address, ibl.bootModes[eIdx].u.ethBoot.ethInfo.hwAddress, sizeof(nDevice.mac_address));
177     nl = FORM_IPN(ibl.bootModes[eIdx].u.ethBoot.ethInfo.ipAddr);
178     if (ibl.bootModes[eIdx].u.ethBoot.doBootp == TRUE)
179         nDevice.ip_address = 0;
180     else
181         nDevice.ip_address = htonl(nl);
183     nl = FORM_IPN(ibl.bootModes[eIdx].u.ethBoot.ethInfo.netmask);
184     nDevice.net_mask  = htonl(nl);
186     nl = FORM_IPN(ibl.bootModes[eIdx].u.ethBoot.ethInfo.serverIp);
187     nDevice.server_ip           = htonl(nl);
188     nDevice.use_bootp_server_ip = ibl.bootModes[eIdx].u.ethBoot.useBootpServerIp;
190     /* Note - the file name structure in nDevice is only 64 bytes, but 128 in ethInfo */
191     netMemcpy (nDevice.file_name, ibl.bootModes[eIdx].u.ethBoot.ethInfo.fileName, sizeof(nDevice.file_name));
192     nDevice.use_bootp_file_name = ibl.bootModes[eIdx].u.ethBoot.useBootpFileName;
195     nDevice.start    = cpmac_drv_start;
196     nDevice.stop     = cpmac_drv_stop;
197     nDevice.send     = cpmac_drv_send;
198     nDevice.receive  = cpmac_drv_receive;
201     /* have_params will be set to true in the tftp call back. It must be
202      * set to false before opening the module, since the call back will
203      * be from the open call if bootp is not used */
204     have_params = FALSE;
206     /* Open the network device */
207     if ((*net_boot_module.open) ((void *)&nDevice, ibl_rec_params) != 0)
208         return;
210     /* Wait for the callback with the requested filename */
211     while (have_params == FALSE)  {
213        if ((*net_boot_module.peek) ((uint8 *)&nl, sizeof(nl)) < 0)  {
215             (*net_boot_module.close)();
216             return;
217         }
218     }
220     format = ibl.bootModes[eIdx].u.ethBoot.bootFormat;
222     /* If the data format was based on the name extension, determine
223      * the boot data format */
224     if (format == ibl_BOOT_FORMAT_NAME)  {
226         ext = strrchr (iblStatus.ethParams.fileName, '.');
228         if (ext != NULL)  {
230             if (!strcmp (ext, ".bis"))
231                 format = ibl_BOOT_FORMAT_BIS;
233             else if (!strcmp (ext, ".ais"))
234                 format = ibl_BOOT_FORMAT_BIS;
236             else if (!strcmp (ext, ".out"))
237                 format = ibl_BOOT_FORMAT_COFF;
239             else if (!strcmp (ext, ".coff"))
240                 format = ibl_BOOT_FORMAT_COFF;
242             else if (!strcmp (ext, ".btbl"))
243                 format = ibl_BOOT_FORMAT_BTBL;
244             
245             else if (!strcmp (ext, ".bin"))
246                 format = ibl_BOOT_FORMAT_BBLOB;
248             else if (!strcmp (ext, ".blob"))
249                 format = ibl_BOOT_FORMAT_BBLOB;
251         }
253         /* Name match failed it didn't change */
254         if (format == ibl_BOOT_FORMAT_NAME)  {
256             iblStatus.nameDetectFailCnt += 1;
258             /* Close up the peripheral */
259             (*net_boot_module.close)();
261             return;
262         }
264     }
267     entry = iblBoot (&net_boot_module, format, &ibl.bootModes[eIdx].u.ethBoot.blob);
270     /* Before closing the module read any remaining data. In the coff boot mode the boot may
271      * detect an exit before the entire file has been read. Read the rest of the file
272      * to make the server happy */
274     do  {
276         dataSize = (*net_boot_module.query)();  /* Will return -1 when the data is done */
278         if (dataSize > 0)  {
280             while (dataSize > 0)  {
281             
282                 n = MIN(dataSize, sizeof(buf));
283                 (*net_boot_module.read)(buf, n);
284                 dataSize = dataSize - n;
285             }
287         /* Do not peek if the data size returned in the query was > 0 */
288         }  else if (dataSize == 0) {
290             (*net_boot_module.peek)(buf, 1);
291         }
293     } while (dataSize >= 0);
297     /* Close up the peripheral */
298     (*net_boot_module.close)();
301 #ifdef DEVICE_PA
302     hwPaDisable ();
303 #endif
305 #ifdef DEVICE_CPDMA
306     /* Cpdma configuration. */
307     hwCpdmaRxDisable ((cpdmaRxCfg_t *)targetGetCpdmaRxConfig());
308     hwCpdmaTxDisable ((cpdmaTxCfg_t *)targetGetCpdmaTxConfig());
309 #endif
311 #ifdef DEVICE_QM
312     targetFreeQs ();
313     /* Queue manager configuration */
314     hwQmTeardown ();
315 #endif
318     if (entry != 0)  {
320         iblStatus.exitAddress = entry;
321         exit = (void (*)())entry;
322         (*exit)();
324     }