add new dfboot loader - a complete revison of romboot code.
[librecmc/librecmc.git] / target / linux / at91-2.6 / image / dfboot / src / com.c
1 /*----------------------------------------------------------------------------
2  *         ATMEL Microcontroller Software Support  -  ROUSSET  -
3  *----------------------------------------------------------------------------
4  * The software is delivered "AS IS" without warranty or condition of any
5  * kind, either express, implied or statutory. This includes without
6  * limitation any warranty or condition with respect to merchantability or
7  * fitness for any particular purpose, or against the infringements of
8  * intellectual property rights of others.
9  *----------------------------------------------------------------------------
10  * File Name           : com.c
11  * Object              : 
12  * Creation            : HIi   03/27/2003
13  *
14  *----------------------------------------------------------------------------
15  */
16 #include "AT91RM9200.h"
17 #include "lib_AT91RM9200.h"
18 #include "config.h"
19 #include "com.h"
20 #include "stdio.h"
21
22 static char erase_seq[] = "\b \b";              /* erase sequence       */
23
24 unsigned int usa[2] = {(unsigned int)AT91C_BASE_DBGU, (unsigned int)AT91C_ALTERNATE_USART};
25 unsigned int us;
26 int port_detected;
27
28 void at91_init_uarts(void)
29 {
30         int i;
31
32         port_detected = 0;
33         AT91F_DBGU_CfgPIO();
34         AT91F_US0_CfgPIO();
35         AT91F_US0_CfgPMC();
36
37         for(i=0; i<2; i++) {
38                 us = usa[i];
39                 AT91F_US_ResetRx((AT91PS_USART)us);
40                 AT91F_US_ResetTx((AT91PS_USART)us);
41
42                 // Configure DBGU
43                 AT91F_US_Configure(
44                         (AT91PS_USART)us, // DBGU base address
45                         AT91C_MASTER_CLOCK,            // 60 MHz
46                         AT91C_US_ASYNC_MODE,           // mode Register to be programmed
47                         115200,                        // baudrate to be programmed
48                         0                              // timeguard to be programmed
49                         );
50
51                 // Enable Transmitter
52                 AT91F_US_EnableTx((AT91PS_USART)us);
53                 // Enable Receiver
54                 AT91F_US_EnableRx((AT91PS_USART)us);
55         }
56         us = usa[0];
57 }
58
59 int at91_serial_putc(int ch)
60 {
61         if (ch == '\n')
62                 at91_serial_putc('\r');
63         while (!AT91F_US_TxReady((AT91PS_USART)us));
64         AT91F_US_PutChar((AT91PS_USART)us, (char)ch);
65         return ch;
66 }
67
68 /* This getc is modified to be able work on more than one port. On certain
69  * boards (i.e. Figment Designs VersaLink), the debug port is not available
70  * once the unit is in it's enclosure, so, if one needs to get into dfboot
71  * for any reason it is impossible. With this getc, it scans between the debug
72  * port and another port and once it receives a character, it sets that port
73  * as the debug port. */
74 int at91_serial_getc()
75 {
76         while(1) {
77                 if (!port_detected) {
78                         if (us == usa[0]) {
79                                 us = usa[1];
80                         }
81                         else {
82                                 us = usa[0];
83                         }
84                 }
85                 if(AT91F_US_RxReady((AT91PS_USART)us)) {
86                         port_detected = 1;
87                         return((int)AT91F_US_GetChar((AT91PS_USART)us));
88                 }
89         }
90 }
91
92 /*-----------------------------------------------------------------------------
93  * Function Name       : AT91F_ReadLine()
94  * Object              : 
95  * Input Parameters    : 
96  * Return value         : 
97  *-----------------------------------------------------------------------------
98  */
99 int AT91F_ReadLine (const char *const prompt, char *console_buffer)
100 {
101         char *p = console_buffer;
102         int     n = 0;                                  /* buffer index         */
103         int     plen = strlen (prompt); /* prompt length        */
104         int     col;                                    /* output column cnt    */
105         char    c;
106
107         /* print prompt */
108         if (prompt)
109                 printf(prompt);
110         col = plen;
111
112         for (;;) {
113                 c = getc();
114
115                 switch (c) {
116                         case '\r':                              /* Enter                */
117                         case '\n':
118                                 *p = '\0';
119                                 puts ("\n");
120                                 return (p - console_buffer);
121
122                         case 0x03:                              /* ^C - break   */
123                                 console_buffer[0] = '\0';       /* discard input */
124                                 return (-1);
125
126                         case 0x08:                              /* ^H  - backspace      */
127                         case 0x7F:                              /* DEL - backspace      */
128                                 if (n) {
129                                         --p;
130                                         printf(erase_seq);
131                                         col--;
132                                         n--;
133                                         }
134                                 continue;
135
136                         default:
137                         /*
138                          * Must be a normal character then
139                          */
140                         if (n < (AT91C_CB_SIZE -2)) 
141                         {
142                                 ++col;          /* echo input           */
143                                 putc(c);
144                                 *p++ = c;
145                                 ++n;
146                         } 
147                         else 
148                         {                       /* Buffer full          */
149                                 putc('\a');
150                         }
151                 }
152         }
153 }
154
155
156 /*-----------------------------------------------------------------------------
157  * Function Name       : AT91F_WaitKeyPressed()
158  * Object              : 
159  * Input Parameters    : 
160  * Return value         : 
161  *-----------------------------------------------------------------------------
162  */
163 void AT91F_WaitKeyPressed(void)
164 {
165         int c;
166         puts("KEY");
167                 c = getc();
168         putc('\n');
169 }
170
171 int puts(const char *str)
172 {
173   while(*str != 0) {
174                 at91_serial_putc(*str);
175                 str++;
176                 }
177         return 1;
178 }
179
180 int putc(int c)
181 {
182   return at91_serial_putc(c);
183 }
184
185 int putchar(c)
186 {
187         return putc(c);
188 }
189
190 int getc()
191 {
192   return at91_serial_getc();
193 }
194
195 int strlen(const char *str)
196 {
197   int len = 0;
198
199   if(str == (char *)0)
200     return 0;
201
202   while(*str++ != 0)
203     len++;
204
205   return len;
206 }
207
208 #define ZEROPAD 1               /* pad with zero */
209 #define SIGN    2               /* unsigned/signed long */
210 #define LEFT    4              /* left justified */
211 #define LARGE   8              /* use 'ABCDEF' instead of 'abcdef' */
212
213 #define do_div(n,base) ({ \
214         int __res; \
215         __res = ((unsigned) n) % (unsigned) base; \
216         n = ((unsigned) n) / (unsigned) base; \
217         __res; \
218 })
219
220 static int number(int num, int base, int size,
221                   int precision, int type)
222 {
223   char c, sign, tmp[66];
224   const char *digits="0123456789ABCDEF";
225   int i;
226
227   if (type & LEFT)
228     type &= ~ZEROPAD;
229   if (base < 2 || base > 16)
230     return 0;
231   c = (type & ZEROPAD) ? '0' : ' ';
232   sign = 0;
233
234   if(type & SIGN && num < 0)
235     {
236       sign = '-';
237       num = -num;
238       size--;
239     }
240   
241   i = 0;
242   if(num == 0)
243     tmp[i++] = digits[0];
244   else while(num != 0)
245     tmp[i++] = digits[do_div(num, base)];
246
247   if(i > precision)
248     precision = i;
249   size -= precision;
250   
251   if(!(type&(ZEROPAD+LEFT)))
252     while(size-->0)
253       putc(' ');
254   
255   if(sign)
256     putc(sign);
257
258   if (!(type & LEFT))
259     while (size-- > 0)
260       putc(c);
261
262   while (i < precision--)
263     putc('0');
264   
265   while (i-- > 0)
266     putc(tmp[i]);
267
268   while (size-- > 0)
269     putc(' ');;
270
271   return 1;
272 }
273
274 int hvfprintf(const char *fmt, va_list va)
275 {
276   char *s;
277
278         do {
279                 if(*fmt == '%') {
280                         bool done = false;
281
282                         int type = 0;
283                         int precision = 0;
284
285                         do {
286                                 fmt++;
287                                 switch(*fmt) {
288                                 case '0' :
289                                         if(!precision)
290                                                 type |= ZEROPAD;
291                                 case '1' :
292                                 case '2' :
293                                 case '3' :
294                                 case '4' :
295                                 case '5' :
296                                 case '6' :
297                                 case '7' :
298                                 case '8' :
299                                 case '9' :
300                                         precision = precision * 10 + (*fmt - '0');
301                                         break;
302                                 case '.' :
303                                         break;
304                                 case 's' :
305                                         s = va_arg(va, char *);
306                                         if(!s)
307                                                 puts("<NULL>");
308                                         else
309                                                 puts(s);
310                                         done = true;
311                                         break;
312                                 case 'c' :
313                                         putc(va_arg(va, int));
314                                         done = true;
315                                         break;
316                                 case 'd' :
317                                         number(va_arg(va, int), 10, 0, precision, type);
318                                         done = true;
319                                         break;
320                                 case 'x' :
321                                 case 'X' :
322                                         number(va_arg(va, int), 16, 0, precision, type);
323                                         done = true;
324                                         break;
325                                 case '%' :
326                                         putc(*fmt);
327                                         done = true;
328                                 default: 
329                                         putc('%');
330                                         putc(*fmt);
331                                         done = true;
332                                         break;
333                                 } 
334                         } while(!done);
335                 } else if(*fmt == '\\') {
336                         fmt++;
337                         if(*fmt == 'r') {
338                                 putc('\r');
339                         } else if(*fmt == 'n') { 
340                                 putc('\n');
341                         }
342                 } else {
343                         putc(*fmt);
344                 }
345                 fmt++;
346         } while(*fmt != 0);
347   
348   return 0;
349 }
350
351 int printf(const char *fmt, ...)
352 {
353   va_list ap;
354   int i;
355
356   va_start(ap, fmt);
357   i = hvfprintf(fmt, ap);
358   va_end(ap);
359
360   return i;
361 }