tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / nand_fdl / common / src / packet.c
1 #include <linux/string.h>
2 #include <asm/arch/sci_types.h>
3 #include <asm/arch/packet.h>
4 #include <asm/arch/fdl_stdio.h>
5 //#include "fdl_main.h"
6 #include <asm/arch/fdl_crc.h>
7 #include <asm/arch/sio_drv.h>
8 #include <asm/arch/usb_boot.h>
9 #include <asm/arch/virtual_com.h>
10 #include <asm/arch/fdl_channel.h>
11
12
13 extern void FDL_SendAckPacket (cmd_pkt_type pkt_type);
14
15
16 struct FDL_ChannelHandler *gFdlUsedChannel;
17
18
19 static PACKET_T  packet[ PACKET_MAX_NUM ];
20
21 static PACKET_T *packet_free_list;
22 static PACKET_T *packet_completed_list;
23 static PACKET_T *packet_receiving;
24
25 void FDL_PacketInit (void)
26 {
27     uint32 i = 0;
28
29     packet_free_list = &packet[0];
30
31     for (i = 0; i < PACKET_MAX_NUM; i++)
32     {
33         memset (&packet[i], 0, sizeof (PACKET_T));
34         packet[i].next   = &packet[i+1];
35     }
36
37     packet[PACKET_MAX_NUM-1].next = PNULL;
38
39     packet_completed_list = NULL;
40     packet_receiving      = NULL;
41
42     gFdlUsedChannel = FDL_ChannelGet();
43 }
44
45
46 PACKET_T *FDL_MallocPacket (void)
47 {
48     PACKET_T   *tmp_ptr = NULL;
49
50     if (NULL != packet_free_list)
51     {
52         tmp_ptr = packet_free_list;
53         packet_free_list = tmp_ptr->next;
54
55         // only clear the packet header
56         memset ((void *)tmp_ptr, 0, 32);
57
58         tmp_ptr->next       = NULL;
59         tmp_ptr->pkt_state  = PKT_NONE;
60         tmp_ptr->ack_flag   = 0;
61         tmp_ptr->data_size  = 0;
62     }
63
64     return tmp_ptr;
65 }
66
67 void FDL_FreePacket (PACKET_T *ptr)
68 {
69     ptr->next        = packet_free_list;
70     packet_free_list = ptr;
71 }
72
73 PACKET_T   *FDL_GetPacket (void)
74 {
75     PACKET_T *ptr;
76
77     // waiting for a packet
78     while (NULL == packet_completed_list)
79     {
80         FDL_PacketDoIdle();
81     }
82
83     // remove from completed list
84     ptr                     = packet_completed_list;
85     packet_completed_list   = ptr->next;
86     ptr->next               = NULL;
87     return ptr;
88 }
89
90 void FDL_PacketDoIdle (void)
91 {
92     //FDL_BOOT_MODE_E          boot_mode;
93     unsigned char *pdata      = NULL;
94     PACKET_T       *packet_ptr = NULL;
95     PACKET_T       *tmp_ptr    = NULL;
96     uint32          crc;
97     uint32 boot_mode = FDL_GetBootMode();
98     unsigned char   ch;
99     int ch1;
100
101     // try get a packet to handle the receive char
102     packet_ptr = packet_receiving;
103
104     if (NULL == packet_ptr)
105     {
106         packet_ptr = FDL_MallocPacket();
107
108         if (NULL != packet_ptr)
109         {
110             packet_receiving    = packet_ptr;
111             packet_ptr->next    = NULL;
112         }
113         else
114         {
115             return ;
116         }
117     }
118
119     pdata  = (unsigned char *) & (packet_ptr->packet_body);
120
121     while (1)
122     {
123         /*
124         * here the reason that we don't call GetChar is
125         * that GetChar() isnot exited until got data from
126         * outside,FDL_PacketDoIdle() is called also in norflash write and erase
127         * so we have to exited when no char recieived here,
128         * usb virtual com is the same handle
129         */
130         ch1 = gFdlUsedChannel->GetSingleChar (gFdlUsedChannel);
131
132         if (ch1 == -1)
133         {
134             return;
135         }
136
137         ch = ch1&0xff;
138
139         if (packet_ptr->data_size > MAX_PKT_SIZE)
140         {
141             packet_receiving = NULL;
142             FDL_FreePacket (packet_ptr);
143             sio_trace ("data_size error : datasize = %d  MAX_PKT_SIZE = %d\n", packet_ptr->data_size, MAX_PKT_SIZE);
144             printf("\n\n\n%s %s %d\n\n\n", __FILE__, __FUNCTION__, __LINE__);
145             SEND_ERROR_RSP (BSL_REP_VERIFY_ERROR)
146             //return;
147         }
148
149         // try handle this input data
150         //printf(" %02x  %d\n", ch1, packet_ptr->pkt_state);
151         switch (packet_ptr->pkt_state)
152         {
153             case PKT_NONE:
154                 if (HDLC_FLAG == ch)
155                 {
156                     packet_ptr->pkt_state = PKT_HEAD;
157                     packet_ptr->data_size = 0;
158                 }
159                 break;
160             case PKT_HEAD:
161                 if (HDLC_FLAG != ch)
162                 {
163                     if (HDLC_ESCAPE == ch)
164                     {
165                         // Try get the "true" data.
166                         //ch = sio_get_char();
167                         ch = gFdlUsedChannel->GetChar (gFdlUsedChannel);
168                         ch = ch ^ HDLC_ESCAPE_MASK;
169                     }
170                     packet_ptr->pkt_state = PKT_GATHER;
171                     *(pdata + packet_ptr->data_size) = ch;
172                     //*(pdata++) = ch;
173                     packet_ptr->data_size += 1;
174                 }
175                 break;
176             case PKT_GATHER:
177                 if (HDLC_FLAG == ch) 
178                                 {
179 end:
180                     packet_ptr->pkt_state = PKT_RECV;
181                     //check the packet. CRC should be 0
182 #ifndef CONFIG_FRMCHECK
183                     crc = crc_16_l_calc((unsigned short *)&packet_ptr->packet_body, packet_ptr->data_size);
184 #else
185                     crc = frm_chk((unsigned short *)&packet_ptr->packet_body, packet_ptr->data_size);
186 #endif
187                     if (0 != crc){
188                         int k;
189                         printf("%4x%4x", packet_ptr->packet_body.type, packet_ptr->packet_body.size);
190                         for(k = 0;  k  < packet_ptr->data_size - 4; k++)
191                         {
192                             printf("%2x", packet_ptr->packet_body.content[k]);
193                         }
194                         printf("\n\n\n\n");
195
196                         //Verify error, reject this packet.
197                         FDL_FreePacket(packet_ptr);
198                         packet_receiving = NULL;
199                         //if check result failed, notify PC
200                         SEND_ERROR_RSP (BSL_REP_VERIFY_ERROR)
201                         printf("crc failed\n\n\n%s %s %d\n\n\n", __FILE__, __FUNCTION__, __LINE__);
202                         //return ;
203                     } else {
204                         //Check there are free packet?
205                         if ((NULL != packet_free_list) && (BSL_CMD_MIDST_DATA == packet_ptr->packet_body.type)) {
206                         //send a ACK
207 #if defined (NOR_FDL_SC6600L) || defined (NOR_FDL_SC6800H)
208                             packet_ptr->ack_flag = 1;
209                             FDL_SendAckPacket (BSL_REP_ACK);
210 #endif
211                         }
212                         //It is a complete packet, move to completed list.
213                         packet_ptr->next = NULL;
214                         if (NULL == packet_completed_list) {
215                             packet_completed_list = packet_ptr;
216                         } else {
217                             //added to the tail
218                             tmp_ptr = packet_completed_list;
219                             while (NULL != tmp_ptr->next) {
220                             tmp_ptr = tmp_ptr->next;
221                             }
222                             tmp_ptr->next = packet_ptr;
223                         }
224                         //set to null for next transfer
225                         packet_receiving = NULL;
226                         return ;
227                     }
228                 } else {
229                     /** Process the byte read by GetSingleChar*/
230                     if(ch == HDLC_ESCAPE)
231                         ch = gFdlUsedChannel->GetChar(gFdlUsedChannel) 
232                                 ^ HDLC_ESCAPE_MASK;
233                     *(pdata + packet_ptr->data_size) = ch;
234                     packet_ptr->data_size += 1;
235                     if(boot_mode == 0x5A){ // In USB Mode
236                         packet_ptr->data_size += gFdlUsedChannel->Read(gFdlUsedChannel,
237                             pdata + packet_ptr->data_size, MAX_PKT_SIZE);
238                         goto end;
239                     }
240                 }
241                 break;
242             default:
243                 break;
244         }
245     }
246 }
247
248 /******************************************************************************
249  * write_packet
250  ******************************************************************************/
251 void FDL_WritePacket (const void *buf, int len)
252 {
253     gFdlUsedChannel->Write (gFdlUsedChannel, buf, len);
254
255 }
256
257 uint32  FDL_DataProcess (PACKET_T *packet_ptr_src, PACKET_T *packet_ptr_dest)
258 {
259     unsigned short  crc, size;
260     int32           write_len;  /*orginal length*/
261     int32           send_len;   /*length after encode*/
262     int32           i;
263     uint8           curval;
264
265     uint8          *des_ptr = NULL;
266     uint8          *src_ptr = NULL;
267
268     size = packet_ptr_src->packet_body.size;
269     write_len = size + sizeof (unsigned short) + PACKET_HEADER_SIZE;
270     src_ptr = (uint8 *) &packet_ptr_src->packet_body;
271
272     packet_ptr_src->packet_body.size = EndianConv_16 (packet_ptr_src->packet_body.size);
273     packet_ptr_src->packet_body.type = EndianConv_16 (packet_ptr_src->packet_body.type);
274
275     /*src CRC calculation*/
276 #ifndef  CONFIG_FRMCHECK
277     crc = crc_16_l_calc ( (const unsigned short *) (& (packet_ptr_src->packet_body)), size + PACKET_HEADER_SIZE);
278 #else
279     crc = frm_chk ( (const unsigned short *) (& (packet_ptr_src->packet_body)), size + PACKET_HEADER_SIZE);
280
281     crc = EndianConv_16 (crc);
282 #endif
283     packet_ptr_src->packet_body.content[ size ] = (crc >> 8) & 0xFF;
284     packet_ptr_src->packet_body.content[ size+1 ] = (crc)    & 0xFF;
285
286     /*******************************************
287     *    des data preparation
288     ********************************************/
289
290     des_ptr = (uint8 *) &packet_ptr_dest->packet_body;
291     /*head flag*/
292     * (des_ptr++) = HDLC_FLAG;
293     send_len = 1;
294
295     /*middle part process*/
296     for (i = 0; i < write_len; i++)
297     {
298         curval = * (src_ptr + i);
299
300         if ( (HDLC_FLAG == curval) || (HDLC_ESCAPE == curval))
301         {
302             * (des_ptr++) = HDLC_ESCAPE;
303             * (des_ptr++) = ~HDLC_ESCAPE_MASK & curval;
304             send_len++;
305         }
306         else
307         {
308             * (des_ptr++) = curval;
309         }
310
311         send_len++;
312     }
313
314     /*end flag*/
315     * (des_ptr++) = HDLC_FLAG;
316     send_len++;
317
318     return send_len;
319 }
320 /******************************************************************************
321  * FDL_SendPacket
322  ******************************************************************************/
323 void FDL_SendPacket (PACKET_T *packet_ptr)
324 {
325     int32           send_len;   /*length after encode*/
326     PACKET_T       *tmp_packet_ptr = NULL;
327
328     // send a ACK packet to notify PC that we are ready.
329     tmp_packet_ptr = FDL_MallocPacket();
330
331     if (NULL == tmp_packet_ptr)
332     {
333
334         FDL_FreePacket (packet_receiving);
335         tmp_packet_ptr = FDL_MallocPacket();
336     }
337
338     send_len = FDL_DataProcess (packet_ptr, tmp_packet_ptr);
339
340     FDL_WritePacket ( (char *) (& (tmp_packet_ptr->packet_body)), send_len);
341
342     FDL_FreePacket (tmp_packet_ptr);
343
344 }
345
346 /******************************************************************************
347  * FDL_SendAckPacket_packet
348  ******************************************************************************/
349 void FDL_SendAckPacket (cmd_pkt_type  pkt_type)
350 {
351
352     unsigned long ack_packet_src[8];
353     unsigned long ack_packet_dst[8];
354     PACKET_T *packet_ptr = (PACKET_T *) ack_packet_src;
355
356     int32           send_len;   /*length after encode*/
357     PACKET_T       *tmp_packet_ptr = NULL;
358
359     packet_ptr->packet_body.type = pkt_type;
360     packet_ptr->packet_body.size = 0;
361
362     tmp_packet_ptr = (PACKET_T *) ack_packet_dst;
363
364     send_len = FDL_DataProcess (packet_ptr, tmp_packet_ptr);
365     FDL_WritePacket ( (char *) (& (tmp_packet_ptr->packet_body)), send_len);
366
367 }