Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 915 lines (816 sloc) 22.708 kb
212b9de4 »
2009-10-03 Missing files
1 /*
446a0237 »
2011-07-10 Update headers
2 * Milkymist SoC (Software)
5366fece »
2011-03-03 Use timer for boot timeout
3 * Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq
427b6035 »
2009-10-17 More compliant libc includes
4 *
212b9de4 »
2009-10-03 Missing files
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License.
427b6035 »
2009-10-17 More compliant libc includes
8 *
212b9de4 »
2009-10-03 Missing files
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
427b6035 »
2009-10-17 More compliant libc includes
13 *
212b9de4 »
2009-10-03 Missing files
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
427b6035 »
2009-10-17 More compliant libc includes
18 #include <stdio.h>
212b9de4 »
2009-10-03 Missing files
19 #include <console.h>
427b6035 »
2009-10-17 More compliant libc includes
20 #include <string.h>
212b9de4 »
2009-10-03 Missing files
21 #include <uart.h>
94740792 »
2010-06-25 Fast boot from flash
22 #include <blockdev.h>
06b19ac6 »
2010-06-24 Removed ML401 support
23 #include <fatfs.h>
212b9de4 »
2009-10-03 Missing files
24 #include <crc.h>
25 #include <system.h>
26 #include <board.h>
bb633f49 »
2010-10-01 Basic console operation
27 #include <irq.h>
212b9de4 »
2009-10-03 Missing files
28 #include <version.h>
7f5a332f »
2010-03-08 Minor fixes
29 #include <net/mdio.h>
212b9de4 »
2009-10-03 Missing files
30 #include <hw/fmlbrg.h>
31 #include <hw/sysctl.h>
32 #include <hw/gpio.h>
e0f04ed6 »
2010-06-25 Flash fixes
33 #include <hw/flash.h>
46d2c61d »
2011-06-15 BIOS: reset ethernet PHY a second time
34 #include <hw/minimac.h>
212b9de4 »
2009-10-03 Missing files
35
35fda58b »
2010-10-01 Console hooks + use HAL and interrupts in BIOS
36 #include <hal/vga.h>
33fdc24f »
2010-10-05 Use hardware accelerated scrolling in BIOS
37 #include <hal/tmu.h>
35fda58b »
2010-10-01 Console hooks + use HAL and interrupts in BIOS
38 #include <hal/brd.h>
39 #include <hal/usb.h>
40 #include <hal/ukb.h>
41
212b9de4 »
2009-10-03 Missing files
42 #include "boot.h"
43 #include "splash.h"
44
e3565f94 »
2010-09-21 RCSR and WCSR commands in BIOS (Michael Walle)
45 enum {
46 CSR_IE = 1, CSR_IM, CSR_IP, CSR_ICC, CSR_DCC, CSR_CC, CSR_CFG, CSR_EBA,
47 CSR_DC, CSR_DEBA, CSR_JTX, CSR_JRX, CSR_BP0, CSR_BP1, CSR_BP2, CSR_BP3,
48 CSR_WP0, CSR_WP1, CSR_WP2, CSR_WP3,
49 };
50
c877aa23 »
2011-12-23 cosmetic changes
51 /* registers */
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
52 /* CH0 */
53 #define CH0_PRN_KEY (0xa0000000)
54 #define CH0_CARRIER_NCO (0xa0000004)
55 #define CH0_CODE_NCO (0xa0000008)
56 #define CH0_CODE_SLEW (0xa000000c)
57 #define CH0_I_EARLY (0xa0000010)
58 #define CH0_Q_EARLY (0xa0000014)
59 #define CH0_I_PROMPT (0xa0000018)
60 #define CH0_Q_PROMPT (0xa000001c)
61 #define CH0_I_LATE (0xa0000020)
62 #define CH0_Q_LATE (0xa0000024)
63 #define CH0_CARRIER_MEASUREMENT (0xa0000028)
64 #define CH0_CODE_MEASUREMENT (0xa000002c)
65 #define CH0_EPOCH (0xa0000030)
66 #define CH0_EPOCH_CHECK (0xa0000034)
67 #define CH0_EPOCH_LOAD (0xa0000038)
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
68 #define CH0_ENABLES (0xa000003c)
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
69
70 /* Status */
71 #define STATUS (0xa0000380)
72 #define NEW_DATA (0xa0000384)
73 #define TIC_COUNT (0xa0000388)
74 #define ACCUM_COUNT (0xa000038c)
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
75 #define CLEAR_STATUS (0xa0000390)
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
76 #define HW_ID (0xa00003bc)
77
78 /* Control */
79 #define RESET (0xa00003c0)
80 #define PROG_TIC (0xa00003c4)
81 #define PROG_ACCUM_INT (0xa00003c8)
82 #define TEMP (0xa00003cc)
83
84 /* PRN Codes */
f9a4ec30 »
2011-12-23 NOW is really update prn/gold codes from namuru datasheet
85 const int prn_code[37] = {
86 0x3EC, 0x3D8, 0x3B0, 0x360, 0x096, 0x12C, 0x196, 0x32C, 0x258,
87 0x374, 0x2E8, 0x3A0, 0x340, 0x280, 0x100, 0x200, 0x226,
88 0x04C, 0x098, 0x130, 0x260, 0x0C0, 0x0CE, 0x270, 0x0E0,
89 0x1C0, 0x380, 0x300, 0x056, 0x0AC, 0x158, 0x2B0, 0x160,
90 0x0B0, 0x316, 0x22C, 0x0B0};
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
91 };
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
92
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
93 /* MMIO */
94 #define MM_READ(reg) (*((volatile unsigned int *)(reg)))
f675333b »
2011-12-11 added support for short int signed read from unsigned int reg from ac…
95 #define MM_READS(reg) (short int)(*((volatile unsigned int *)(reg)))
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
96 #define MM_WRITE(reg, val) *((volatile unsigned int *)(reg)) = val
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
97
212b9de4 »
2009-10-03 Missing files
98 /* General address space functions */
99
100 #define NUMBER_OF_BYTES_ON_A_LINE 16
101 static void dump_bytes(unsigned int *ptr, int count, unsigned addr)
102 {
103 char *data = (char *)ptr;
104 int line_bytes = 0, i = 0;
105
106 putsnonl("Memory dump:");
107 while(count > 0){
108 line_bytes =
109 (count > NUMBER_OF_BYTES_ON_A_LINE)?
110 NUMBER_OF_BYTES_ON_A_LINE : count;
111
112 printf("\n0x%08x ", addr);
113 for(i=0;i<line_bytes;i++)
114 printf("%02x ", *(unsigned char *)(data+i));
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
115
212b9de4 »
2009-10-03 Missing files
116 for(;i<NUMBER_OF_BYTES_ON_A_LINE;i++)
117 printf(" ");
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
118
212b9de4 »
2009-10-03 Missing files
119 printf(" ");
120
121 for(i=0;i<line_bytes;i++) {
122 if((*(data+i) < 0x20) || (*(data+i) > 0x7e))
123 printf(".");
124 else
125 printf("%c", *(data+i));
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
126 }
212b9de4 »
2009-10-03 Missing files
127
128 for(;i<NUMBER_OF_BYTES_ON_A_LINE;i++)
129 printf(" ");
130
131 data += (char)line_bytes;
132 count -= line_bytes;
133 addr += line_bytes;
134 }
135 printf("\n");
136 }
137
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
138 static void memtest1()
139 {
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
140 volatile unsigned int *count_addr = (volatile unsigned int *)0xa00003cc;
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
141 int i;
142 int j;
166c9bec »
2011-09-13 error and pass count added to namuru memtest
143 int errors = 0;
144 int pass = 0;
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
145 puts("Start \n");
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
146 unsigned int buf[100000];
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
147 for (i = 0; i != 100; i++)
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
148 for (j = 0; j != sizeof(buf); j++) {
166c9bec »
2011-09-13 error and pass count added to namuru memtest
149 *count_addr = buf[j];
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
150 if( *count_addr != buf[j]){
166c9bec »
2011-09-13 error and pass count added to namuru memtest
151 // printf("E. %u", *count_addr);
152 errors++;
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
153 }
166c9bec »
2011-09-13 error and pass count added to namuru memtest
154 pass++;
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
155 }
166c9bec »
2011-09-13 error and pass count added to namuru memtest
156 printf("Errors: %u \n", errors);
21494e33 »
2011-11-26 added some utils to bios (namuru memory test and support to visualize…
157 printf("Cycles: %u \n", pass);
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
158 puts("Done \n");
159 }
160
c877aa23 »
2011-12-23 cosmetic changes
161 static void init()
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
162 {
163 char *c;
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
164 printf("\n");
165 printf("Initializing Correlator: \n");
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
166 /* prog tic*/
167 MM_WRITE(PROG_TIC,0x18ffff);
168 printf("Prog TIC\n");
169 /* prog accum int*/
170 MM_WRITE(PROG_ACCUM_INT,0x1fff);
171 printf("Accum TIC\n");
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
172 /* prn */
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
173 MM_WRITE(CH0_PRN_KEY,0x300);
4ead3125 »
2011-08-07 Separate Accumlator status from init
174 printf("CH0 PRN Key \n");
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
175 /* carrier nco */
176 MM_WRITE(CH0_CARRIER_NCO,0x9f0000);
4ead3125 »
2011-08-07 Separate Accumlator status from init
177 printf("Carrier NCO\n");
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
178 /* code nco */
179 MM_WRITE(CH0_CODE_NCO,0x3ff00);
4ead3125 »
2011-08-07 Separate Accumlator status from init
180 printf("CH0 Code NCO\n");
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
181 /* code slew */
182 MM_WRITE(CH0_CODE_SLEW,0x400); // this will be based upon a variable
4ead3125 »
2011-08-07 Separate Accumlator status from init
183 printf("CH0 Code SLEW\n");
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
184 /* logic enable */
185 MM_WRITE(CH0_ENABLES,0xff);
186 printf("CH0 LOGIC ENABLED\n");
4ead3125 »
2011-08-07 Separate Accumlator status from init
187 /* epoch load */
188 MM_WRITE(CH0_EPOCH_LOAD,0xff);
189 printf("CH0 Epoch Load\n");
190 printf("Done\n");
191 }
c877aa23 »
2011-12-23 cosmetic changes
192 static void measure()
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
193 {
194 char *c;
195 while(1)
196 {
197 MM_WRITE(CLEAR_STATUS,0x0f);
198 if(readchar_nonblock())
199 {
200 c = readchar();
201 if(c == 'q')
202 break;
203 }
204 }
205 printf("Bye\n");
206 }
c877aa23 »
2011-12-23 cosmetic changes
207 static void accumone()
f675333b »
2011-12-11 added support for short int signed read from unsigned int reg from ac…
208 {
209 char *c;
210 // short int value;
211 printf("Accumulator: \n");
212 printf("I_P\n");
213 /* missing polling accum int pin */
214 while(1)
215 {
216
217 // volatile unsigned int *ch_prompt = CH0_I_PROMPT;
218 // value = (short int) *ch_prompt;
219 //printf("%d\n",(short int)(*((volatile unsigned int *)(CH0_I_PROMPT))));
220 printf("%d\n",MM_READS(CH0_I_PROMPT));
221 MM_WRITE(CLEAR_STATUS,0x0f);
222 MM_WRITE(CH0_ENABLES,0xff);
223 if(readchar_nonblock())
224 {
225 c = readchar();
226 if(c == 'q')
227 break;
228 }
229 }
230 printf("\n");
231
232 }
c877aa23 »
2011-12-23 cosmetic changes
233 static void accumu()
4ead3125 »
2011-08-07 Separate Accumlator status from init
234 {
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
235 char *c;
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
236 printf("Accumulators: \n");
237 printf("I_E\tQ_E\tI_P\tQ_P\tI_L\tQ_L\n");
4ead3125 »
2011-08-07 Separate Accumlator status from init
238 /* missing polling accum int pin */
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
239 while(1)
240 {
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
241 printf("%02d\t%02d\t%02d\t%02d\t%02d\t%02d\n",(MM_READ(CH0_I_EARLY)),(MM_READ(CH0_Q_EARLY)),(MM_READ(CH0_I_PROMPT)),(MM_READ(CH0_Q_PROMPT)),(MM_READ(CH0_I_LATE)),(MM_READ(CH0_Q_LATE)));
242 MM_WRITE(CLEAR_STATUS,0x0f);
243 MM_WRITE(CH0_ENABLES,0xff);
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
244 if(readchar_nonblock())
245 {
246 c = readchar();
247 if(c == 'q')
248 break;
249 }
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
250 }
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
251 printf("\n");
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
252
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
253 }
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
254
c877aa23 »
2011-12-23 cosmetic changes
255 static void accums()
21494e33 »
2011-11-26 added some utils to bios (namuru memory test and support to visualize…
256 {
257 char *c;
258 printf("Accumulators: \n");
259 printf("I_E\tQ_E\tI_P\tQ_P\tI_L\tQ_L\n");
260 /* missing polling accum int pin */
261 while(1)
262 {
263 printf("%d\t%d\t%d\t%d\t%d\t%d\n",(MM_READS(CH0_I_EARLY)),(MM_READS(CH0_Q_EARLY)),(MM_READS(CH0_I_PROMPT)),(MM_READS(CH0_Q_PROMPT)),(MM_READS(CH0_I_LATE)),(MM_READS(CH0_Q_LATE)));
264 MM_WRITE(CLEAR_STATUS,0x0f);
265 MM_WRITE(CH0_ENABLES,0xff);
266 if(readchar_nonblock())
267 {
268 c = readchar();
269 if(c == 'q')
270 break;
271 }
272 }
273 printf("\n");
274
275 }
276
c877aa23 »
2011-12-23 cosmetic changes
277 static void status()
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
278 {
279 char *c;
280 printf("\n");
281 printf("Status: \n");
21494e33 »
2011-11-26 added some utils to bios (namuru memory test and support to visualize…
282 printf("TIC_COUNT\tACCUM_COUNT\tCARRIER_MEASURE\tCODE_MEASURE\t\tSTATUS\tNEW_DATA\n");
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
283 while(1)
284 {
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
285 printf("%02d\t\t%02d\t\t%02d\t\t%02d\t\t%02d\t\t%02d\n",(MM_READ(TIC_COUNT)),(MM_READ(ACCUM_COUNT)),(MM_READ(CH0_CARRIER_MEASUREMENT)),(MM_READ(CH0_CODE_MEASUREMENT)),(MM_READ(STATUS)),(MM_READ(NEW_DATA)));
c877aa23 »
2011-12-23 cosmetic changes
286 MM_WRITE(CLEAR_STATUS,0x0f);
99cc5f53 »
2011-12-23 updated gold codes
287 // MM_WRITE(CH0_ENABLES,0xff);
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
288 if(readchar_nonblock())
289 {
290 c = readchar();
291 if(c == 'q')
292 break;
293 }
294 }
f1a33d93 »
2011-08-16 load PRN key/set clear flag added to accumulator/status loop,
295 MM_WRITE(STATUS,0x0); //clear status_read flag
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
296 printf("\n");
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
297 }
212b9de4 »
2009-10-03 Missing files
298
c877aa23 »
2011-12-23 cosmetic changes
299 static void acq()
21494e33 »
2011-11-26 added some utils to bios (namuru memory test and support to visualize…
300 {
301 char *c;
302 printf("Accumulators: \n");
303 printf("I_E\tQ_E\tI_P\tQ_P\tI_L\tQ_L\n");
304 /* missing polling accum int pin */
305 while(1)
306 {
307 printf("%02d\t%02d\t%02d\t%02d\t%02d\t%02d\n",(MM_READ(CH0_I_EARLY)),(MM_READ(CH0_Q_EARLY)),(MM_READ(CH0_I_PROMPT)),(MM_READ(CH0_Q_PROMPT)),(MM_READ(CH0_I_LATE)),(MM_READ(CH0_Q_LATE)));
308 MM_WRITE(CLEAR_STATUS,0x0f);
309 MM_WRITE(CH0_ENABLES,0xff);
310 if(readchar_nonblock())
311 {
312 c = readchar();
313 if(c == 'q')
314 break;
315 }
316 }
317 printf("\n");
318
319 }
320
321 static void printmath()
322 {
323 /* int positive = 20;
324 int negative = -20; */
325 volatile signed short int positive = 30;
326 volatile signed short int negative = -30;
327 float floating = 0;
328 printf("Positive value as unsigned: %u \n", positive);
329 printf("Negative value as unsigned: %u \n", negative);
330 printf("Float value as unsigned: %u \n", floating);
331 printf("Positive value as signed: %d \n", positive);
332 printf("Negative value as signed: %d \n", negative);
333 // printf("Float value as float: %f \n", &floating);
334 }
335
212b9de4 »
2009-10-03 Missing files
336 static void mr(char *startaddr, char *len)
337 {
338 char *c;
339 unsigned int *addr;
340 unsigned int length;
341
342 if(*startaddr == 0) {
343 printf("mr <address> [length]\n");
344 return;
345 }
346 addr = (unsigned *)strtoul(startaddr, &c, 0);
347 if(*c != 0) {
348 printf("incorrect address\n");
349 return;
350 }
351 if(*len == 0) {
352 length = 1;
353 } else {
354 length = strtoul(len, &c, 0);
355 if(*c != 0) {
356 printf("incorrect length\n");
357 return;
358 }
359 }
360
361 dump_bytes(addr, length, (unsigned)addr);
362 }
363
364 static void mw(char *addr, char *value, char *count)
365 {
366 char *c;
367 unsigned int *addr2;
368 unsigned int value2;
369 unsigned int count2;
370 unsigned int i;
371
372 if((*addr == 0) || (*value == 0)) {
373 printf("mw <address> <value> [count]\n");
374 return;
375 }
376 addr2 = (unsigned int *)strtoul(addr, &c, 0);
377 if(*c != 0) {
378 printf("incorrect address\n");
379 return;
380 }
381 value2 = strtoul(value, &c, 0);
382 if(*c != 0) {
383 printf("incorrect value\n");
384 return;
385 }
386 if(*count == 0) {
387 count2 = 1;
388 } else {
389 count2 = strtoul(count, &c, 0);
390 if(*c != 0) {
391 printf("incorrect count\n");
392 return;
393 }
394 }
395 for (i=0;i<count2;i++) *addr2++ = value2;
396 }
397
398 static void mc(char *dstaddr, char *srcaddr, char *count)
399 {
400 char *c;
401 unsigned int *dstaddr2;
402 unsigned int *srcaddr2;
403 unsigned int count2;
404 unsigned int i;
405
406 if((*dstaddr == 0) || (*srcaddr == 0)) {
407 printf("mc <dst> <src> [count]\n");
408 return;
409 }
410 dstaddr2 = (unsigned int *)strtoul(dstaddr, &c, 0);
411 if(*c != 0) {
412 printf("incorrect destination address\n");
413 return;
414 }
415 srcaddr2 = (unsigned int *)strtoul(srcaddr, &c, 0);
416 if(*c != 0) {
417 printf("incorrect source address\n");
418 return;
419 }
420 if(*count == 0) {
421 count2 = 1;
422 } else {
423 count2 = strtoul(count, &c, 0);
424 if(*c != 0) {
425 printf("incorrect count\n");
426 return;
427 }
428 }
429 for (i=0;i<count2;i++) *dstaddr2++ = *srcaddr2++;
430 }
431
432 static void crc(char *startaddr, char *len)
433 {
434 char *c;
435 char *addr;
436 unsigned int length;
437
438 if((*startaddr == 0)||(*len == 0)) {
439 printf("crc <address> <length>\n");
440 return;
441 }
442 addr = (char *)strtoul(startaddr, &c, 0);
443 if(*c != 0) {
444 printf("incorrect address\n");
445 return;
446 }
447 length = strtoul(len, &c, 0);
448 if(*c != 0) {
449 printf("incorrect length\n");
450 return;
451 }
452
453 printf("CRC32: %08x\n", crc32((unsigned char *)addr, length));
454 }
455
e3565f94 »
2010-09-21 RCSR and WCSR commands in BIOS (Michael Walle)
456 /* processor registers */
457 static int parse_csr(const char *csr)
458 {
35fda58b »
2010-10-01 Console hooks + use HAL and interrupts in BIOS
459 if(!strcmp(csr, "ie")) return CSR_IE;
460 if(!strcmp(csr, "im")) return CSR_IM;
461 if(!strcmp(csr, "ip")) return CSR_IP;
462 if(!strcmp(csr, "icc")) return CSR_ICC;
463 if(!strcmp(csr, "dcc")) return CSR_DCC;
464 if(!strcmp(csr, "cc")) return CSR_CC;
465 if(!strcmp(csr, "cfg")) return CSR_CFG;
466 if(!strcmp(csr, "eba")) return CSR_EBA;
467 if(!strcmp(csr, "dc")) return CSR_DC;
468 if(!strcmp(csr, "deba")) return CSR_DEBA;
469 if(!strcmp(csr, "jtx")) return CSR_JTX;
470 if(!strcmp(csr, "jrx")) return CSR_JRX;
471 if(!strcmp(csr, "bp0")) return CSR_BP0;
472 if(!strcmp(csr, "bp1")) return CSR_BP1;
473 if(!strcmp(csr, "bp2")) return CSR_BP2;
474 if(!strcmp(csr, "bp3")) return CSR_BP3;
475 if(!strcmp(csr, "wp0")) return CSR_WP0;
476 if(!strcmp(csr, "wp1")) return CSR_WP1;
477 if(!strcmp(csr, "wp2")) return CSR_WP2;
478 if(!strcmp(csr, "wp3")) return CSR_WP3;
e3565f94 »
2010-09-21 RCSR and WCSR commands in BIOS (Michael Walle)
479
480 return 0;
481 }
482
483 static void rcsr(char *csr)
484 {
485 unsigned int csr2;
486 register unsigned int value;
487
488 if(*csr == 0) {
489 printf("rcsr <csr>\n");
490 return;
491 }
492
493 csr2 = parse_csr(csr);
494 if(csr2 == 0) {
495 printf("incorrect csr\n");
496 return;
497 }
498
35fda58b »
2010-10-01 Console hooks + use HAL and interrupts in BIOS
499 switch(csr2) {
e3565f94 »
2010-09-21 RCSR and WCSR commands in BIOS (Michael Walle)
500 case CSR_IE: asm volatile ("rcsr %0,ie":"=r"(value)); break;
501 case CSR_IM: asm volatile ("rcsr %0,im":"=r"(value)); break;
502 case CSR_IP: asm volatile ("rcsr %0,ip":"=r"(value)); break;
503 case CSR_CC: asm volatile ("rcsr %0,cc":"=r"(value)); break;
504 case CSR_CFG: asm volatile ("rcsr %0,cfg":"=r"(value)); break;
505 case CSR_EBA: asm volatile ("rcsr %0,eba":"=r"(value)); break;
506 case CSR_DEBA: asm volatile ("rcsr %0,deba":"=r"(value)); break;
507 case CSR_JTX: asm volatile ("rcsr %0,jtx":"=r"(value)); break;
508 case CSR_JRX: asm volatile ("rcsr %0,jrx":"=r"(value)); break;
509 default: printf("csr write only\n"); return;
510 }
511
512 printf("%08x\n", value);
513 }
514
515 static void wcsr(char *csr, char *value)
516 {
517 char *c;
518 unsigned int csr2;
519 register unsigned int value2;
520
521 if((*csr == 0) || (*value == 0)) {
522 printf("wcsr <csr> <address>\n");
523 return;
524 }
525
526 csr2 = parse_csr(csr);
527 if(csr2 == 0) {
528 printf("incorrect csr\n");
529 return;
530 }
531 value2 = strtoul(value, &c, 0);
532 if(*c != 0) {
533 printf("incorrect value\n");
534 return;
535 }
536
35fda58b »
2010-10-01 Console hooks + use HAL and interrupts in BIOS
537 switch(csr2) {
e3565f94 »
2010-09-21 RCSR and WCSR commands in BIOS (Michael Walle)
538 case CSR_IE: asm volatile ("wcsr ie,%0"::"r"(value2)); break;
539 case CSR_IM: asm volatile ("wcsr im,%0"::"r"(value2)); break;
540 case CSR_ICC: asm volatile ("wcsr icc,%0"::"r"(value2)); break;
541 case CSR_DCC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break;
542 case CSR_EBA: asm volatile ("wcsr eba,%0"::"r"(value2)); break;
543 case CSR_DC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break;
544 case CSR_DEBA: asm volatile ("wcsr deba,%0"::"r"(value2)); break;
545 case CSR_JTX: asm volatile ("wcsr jtx,%0"::"r"(value2)); break;
546 case CSR_JRX: asm volatile ("wcsr jrx,%0"::"r"(value2)); break;
547 case CSR_BP0: asm volatile ("wcsr bp0,%0"::"r"(value2)); break;
548 case CSR_BP1: asm volatile ("wcsr bp1,%0"::"r"(value2)); break;
549 case CSR_BP2: asm volatile ("wcsr bp2,%0"::"r"(value2)); break;
550 case CSR_BP3: asm volatile ("wcsr bp3,%0"::"r"(value2)); break;
551 case CSR_WP0: asm volatile ("wcsr wp0,%0"::"r"(value2)); break;
552 case CSR_WP1: asm volatile ("wcsr wp1,%0"::"r"(value2)); break;
553 case CSR_WP2: asm volatile ("wcsr wp2,%0"::"r"(value2)); break;
554 case CSR_WP3: asm volatile ("wcsr wp3,%0"::"r"(value2)); break;
555 default: printf("csr read only\n"); return;
556 }
557 }
558
559
212b9de4 »
2009-10-03 Missing files
560 /* CF filesystem functions */
561
562 static int lscb(const char *filename, const char *longname, void *param)
563 {
564 printf("%12s [%s]\n", filename, longname);
565 return 1;
566 }
567
e42c3da8 »
2010-07-26 Memory card support in BIOS
568 static void ls(char *dev)
569 {
c6eb9ead »
2010-08-31 Flash boot support
570 if(!fatfs_init(BLOCKDEV_MEMORY_CARD)) return;
06b19ac6 »
2010-06-24 Removed ML401 support
571 fatfs_list_files(lscb, NULL);
572 fatfs_done();
212b9de4 »
2009-10-03 Missing files
573 }
574
e42c3da8 »
2010-07-26 Memory card support in BIOS
575 static void load(char *filename, char *addr, char *dev)
212b9de4 »
2009-10-03 Missing files
576 {
577 char *c;
578 unsigned int *addr2;
579
580 if((*filename == 0) || (*addr == 0)) {
581 printf("load <filename> <address>\n");
582 return;
583 }
584 addr2 = (unsigned *)strtoul(addr, &c, 0);
585 if(*c != 0) {
586 printf("incorrect address\n");
587 return;
588 }
c6eb9ead »
2010-08-31 Flash boot support
589 if(!fatfs_init(BLOCKDEV_MEMORY_CARD)) return;
06b19ac6 »
2010-06-24 Removed ML401 support
590 fatfs_load(filename, (char *)addr2, 16*1024*1024, NULL);
591 fatfs_done();
212b9de4 »
2009-10-03 Missing files
592 }
593
7f5a332f »
2010-03-08 Minor fixes
594 static void mdior(char *reg)
595 {
596 char *c;
597 int reg2;
598
599 if(*reg == 0) {
600 printf("mdior <register>\n");
601 return;
602 }
603 reg2 = strtoul(reg, &c, 0);
604 if(*c != 0) {
605 printf("incorrect register\n");
606 return;
607 }
608
609 printf("%04x\n", mdio_read(brd_desc->ethernet_phyadr, reg2));
610 }
611
612 static void mdiow(char *reg, char *value)
613 {
614 char *c;
615 int reg2;
616 int value2;
617
618 if((*reg == 0) || (*value == 0)) {
619 printf("mdiow <register> <value>\n");
620 return;
621 }
622 reg2 = strtoul(reg, &c, 0);
623 if(*c != 0) {
624 printf("incorrect address\n");
625 return;
626 }
627 value2 = strtoul(value, &c, 0);
628 if(*c != 0) {
629 printf("incorrect value\n");
630 return;
631 }
632
633 mdio_write(brd_desc->ethernet_phyadr, reg2, value2);
634 }
635
212b9de4 »
2009-10-03 Missing files
636 /* Init + command line */
637
638 static void help()
639 {
156b2344 »
2010-10-05 Update help
640 puts("Milkymist(tm) BIOS (bootloader)");
641 puts("Don't know what to do? Try 'flashboot'.\n");
212b9de4 »
2009-10-03 Missing files
642 puts("Available commands:");
bb633f49 »
2010-10-01 Basic console operation
643 puts("cons - switch console mode");
212b9de4 »
2009-10-03 Missing files
644 puts("flush - flush FML bridge cache");
645 puts("mr - read address space");
646 puts("mw - write address space");
647 puts("mc - copy address space");
648 puts("crc - compute CRC32 of a part of the address space");
e3565f94 »
2010-09-21 RCSR and WCSR commands in BIOS (Michael Walle)
649 puts("rcsr - read processor CSR");
650 puts("wcsr - write processor CSR");
94740792 »
2010-06-25 Fast boot from flash
651 puts("ls - list files on the filesystem");
652 puts("load - load a file from the filesystem");
b2b7b650 »
2010-03-05 TFTP boot working
653 puts("netboot - boot via TFTP");
c6eb9ead »
2010-08-31 Flash boot support
654 puts("serialboot - boot via SFL");
94740792 »
2010-06-25 Fast boot from flash
655 puts("fsboot - boot from the filesystem");
156b2344 »
2010-10-05 Update help
656 puts("flashboot - boot from flash");
7f5a332f »
2010-03-08 Minor fixes
657 puts("mdior - read MDIO register");
658 puts("mdiow - write MDIO register");
82e4e557 »
2010-10-05 Version command + fixes
659 puts("version - display version");
920039a8 »
2010-01-14 New reset system
660 puts("reboot - system reset");
82e4e557 »
2010-10-05 Version command + fixes
661 puts("reconf - reload FPGA configuration");
c877aa23 »
2011-12-23 cosmetic changes
662 puts("init - init correlator essential registers");
663 puts("status - dump status to screen");
664 puts("measure - no dump,measure TPs with scope ");
665 puts("accums - dump accumlators as signed to screen");
666 puts("accumu - dump accumlators as un-signed to screen");
667 puts("accumone - dump one accumlator as signed to screen");
67e3a3e3 »
2011-08-06 namuru related bios commands WIP
668 puts("memtest1 - memory speed test, use a stopwatch!");
21494e33 »
2011-11-26 added some utils to bios (namuru memory test and support to visualize…
669 puts("printmath - confirm some signed/unsiged visualization");
212b9de4 »
2009-10-03 Missing files
670 }
671
672 static char *get_token(char **str)
673 {
674 char *c, *d;
675
676 c = (char *)strchr(*str, ' ');
677 if(c == NULL) {
678 d = *str;
679 *str = *str+strlen(*str);
680 return d;
681 }
682 *c = 0;
683 d = *str;
684 *str = c+1;
685 return d;
686 }
687
688 static void do_command(char *c)
689 {
690 char *token;
691
692 token = get_token(&c);
693
bb633f49 »
2010-10-01 Basic console operation
694 if(strcmp(token, "cons") == 0) vga_set_console(!vga_get_console());
695 else if(strcmp(token, "flush") == 0) flush_bridge_cache();
212b9de4 »
2009-10-03 Missing files
696 else if(strcmp(token, "mr") == 0) mr(get_token(&c), get_token(&c));
697 else if(strcmp(token, "mw") == 0) mw(get_token(&c), get_token(&c), get_token(&c));
698 else if(strcmp(token, "mc") == 0) mc(get_token(&c), get_token(&c), get_token(&c));
699 else if(strcmp(token, "crc") == 0) crc(get_token(&c), get_token(&c));
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
700
e42c3da8 »
2010-07-26 Memory card support in BIOS
701 else if(strcmp(token, "ls") == 0) ls(get_token(&c));
702 else if(strcmp(token, "load") == 0) load(get_token(&c), get_token(&c), get_token(&c));
c6eb9ead »
2010-08-31 Flash boot support
703
b2b7b650 »
2010-03-05 TFTP boot working
704 else if(strcmp(token, "netboot") == 0) netboot();
c6eb9ead »
2010-08-31 Flash boot support
705 else if(strcmp(token, "serialboot") == 0) serialboot();
706 else if(strcmp(token, "fsboot") == 0) fsboot(BLOCKDEV_MEMORY_CARD);
707 else if(strcmp(token, "flashboot") == 0) flashboot();
920039a8 »
2010-01-14 New reset system
708
7f5a332f »
2010-03-08 Minor fixes
709 else if(strcmp(token, "mdior") == 0) mdior(get_token(&c));
710 else if(strcmp(token, "mdiow") == 0) mdiow(get_token(&c), get_token(&c));
711
82e4e557 »
2010-10-05 Version command + fixes
712 else if(strcmp(token, "version") == 0) puts(VERSION);
920039a8 »
2010-01-14 New reset system
713 else if(strcmp(token, "reboot") == 0) reboot();
82e4e557 »
2010-10-05 Version command + fixes
714 else if(strcmp(token, "reconf") == 0) reconf();
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
715
212b9de4 »
2009-10-03 Missing files
716 else if(strcmp(token, "help") == 0) help();
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
717
c877aa23 »
2011-12-23 cosmetic changes
718 else if(strcmp(token, "init") == 0) init();
719 else if(strcmp(token, "status") == 0) status();
720 else if(strcmp(token, "measure") == 0) measure();
721 else if(strcmp(token, "accums") == 0) accums();
722 else if(strcmp(token, "accumu") == 0) accumu();
723 else if(strcmp(token, "accumone") == 0) accumone();
0f659fe2 »
2011-07-24 added in bios specific commands for gps correlator diagnostic/setup WIP
724 else if(strcmp(token, "memtest1") == 0) memtest1();
21494e33 »
2011-11-26 added some utils to bios (namuru memory test and support to visualize…
725 else if(strcmp(token, "printmath") == 0) printmath();
4bfe81b0 »
2010-09-05 More sophisticated SDRAM clocking + disallow continuous read bursts (…
726
e3565f94 »
2010-09-21 RCSR and WCSR commands in BIOS (Michael Walle)
727 else if(strcmp(token, "rcsr") == 0) rcsr(get_token(&c));
728 else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c));
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
729
212b9de4 »
2009-10-03 Missing files
730 else if(strcmp(token, "") != 0)
731 printf("Command not found\n");
732 }
733
734 static int test_user_abort()
735 {
736 char c;
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
737
58f78a72 »
2010-10-01 Cosmetic changes
738 puts("I: Press Q or ESC to abort boot");
5366fece »
2011-03-03 Use timer for boot timeout
739 CSR_TIMER0_COUNTER = 0;
028c9f6c »
2011-11-22 software: remove redundant clk_frequency
740 CSR_TIMER0_COMPARE = 2*CSR_FREQUENCY;
5366fece »
2011-03-03 Use timer for boot timeout
741 CSR_TIMER0_CONTROL = TIMER_ENABLE;
742 while(CSR_TIMER0_CONTROL & TIMER_ENABLE) {
212b9de4 »
2009-10-03 Missing files
743 if(readchar_nonblock()) {
744 c = readchar();
1f2f148a »
2010-10-01 Toggle console with ESC
745 if((c == 'Q')||(c == '\e')) {
212b9de4 »
2009-10-03 Missing files
746 puts("I: Aborted boot on user request");
747 return 0;
748 }
3a85405c »
2010-11-04 F8 boots from network
749 if(c == 0x07) {
3c1d14af »
2011-04-29 BIOS: enable video output on user triggered netboot
750 vga_unblank();
3a85405c »
2010-11-04 F8 boots from network
751 vga_set_console(1);
752 netboot();
753 return 0;
754 }
212b9de4 »
2009-10-03 Missing files
755 }
756 }
757 return 1;
758 }
759
99cc4577 »
2010-08-30 New flash map and standby/rescue bitstream
760 int rescue;
761
212b9de4 »
2009-10-03 Missing files
762 extern unsigned int _edata;
763
764 static void crcbios()
765 {
99cc4577 »
2010-08-30 New flash map and standby/rescue bitstream
766 unsigned int offset_bios;
212b9de4 »
2009-10-03 Missing files
767 unsigned int length;
768 unsigned int expected_crc;
769 unsigned int actual_crc;
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
770
212b9de4 »
2009-10-03 Missing files
771 /*
772 * _edata is located right after the end of the flat
773 * binary image. The CRC tool writes the 32-bit CRC here.
774 * We also use the address of _edata to know the length
775 * of our code.
776 */
99cc4577 »
2010-08-30 New flash map and standby/rescue bitstream
777 offset_bios = rescue ? FLASH_OFFSET_RESCUE_BIOS : FLASH_OFFSET_REGULAR_BIOS;
212b9de4 »
2009-10-03 Missing files
778 expected_crc = _edata;
99cc4577 »
2010-08-30 New flash map and standby/rescue bitstream
779 length = (unsigned int)&_edata - offset_bios;
780 actual_crc = crc32((unsigned char *)offset_bios, length);
212b9de4 »
2009-10-03 Missing files
781 if(expected_crc == actual_crc)
782 printf("I: BIOS CRC passed (%08x)\n", actual_crc);
783 else {
784 printf("W: BIOS CRC failed (expected %08x, got %08x)\n", expected_crc, actual_crc);
785 printf("W: The system will continue, but expect problems.\n");
786 }
787 }
788
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
789 static void print_mac()
790 {
791 unsigned char *macadr = (unsigned char *)FLASH_OFFSET_MAC_ADDRESS;
792
793 printf("I: MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", macadr[0], macadr[1], macadr[2], macadr[3], macadr[4], macadr[5]);
794 }
795
212b9de4 »
2009-10-03 Missing files
796 static const char banner[] =
58f78a72 »
2010-10-01 Cosmetic changes
797 "\nMILKYMIST(tm) v"VERSION" BIOS http://www.milkymist.org\n"
c877aa23 »
2011-12-23 cosmetic changes
798 "Modified to assist Namuru Correlator \n\n"
799 "(c) Copyleft 2011 Cristian Paul Peñaranda Rojas \n\n"
a0260673 »
2011-04-23 BIOS: report rescue mode to the application using R4
800 "(c) Copyright 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq\n\n"
212b9de4 »
2009-10-03 Missing files
801 "This program is free software: you can redistribute it and/or modify\n"
802 "it under the terms of the GNU General Public License as published by\n"
803 "the Free Software Foundation, version 3 of the License.\n\n";
804
a6fa88db »
2009-11-13 reboot command
805 static void boot_sequence()
806 {
807 if(test_user_abort()) {
c6eb9ead »
2010-08-31 Flash boot support
808 if(rescue) {
809 netboot();
810 serialboot();
811 fsboot(BLOCKDEV_MEMORY_CARD);
812 flashboot();
813 } else {
814 fsboot(BLOCKDEV_MEMORY_CARD);
815 flashboot();
816 netboot();
817 serialboot();
818 }
a6fa88db »
2009-11-13 reboot command
819 printf("E: No boot medium found\n");
820 }
821 }
822
1f2f148a »
2010-10-01 Toggle console with ESC
823 static void readstr(char *s, int size)
824 {
2b7f981d »
2010-10-04 Atomic console prints
825 char c[2];
1f2f148a »
2010-10-01 Toggle console with ESC
826 int ptr;
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
827
2b7f981d »
2010-10-04 Atomic console prints
828 c[1] = 0;
1f2f148a »
2010-10-01 Toggle console with ESC
829 ptr = 0;
830 while(1) {
2b7f981d »
2010-10-04 Atomic console prints
831 c[0] = readchar();
832 switch(c[0]) {
1f2f148a »
2010-10-01 Toggle console with ESC
833 case 0x7f:
834 case 0x08:
835 if(ptr > 0) {
836 ptr--;
837 putsnonl("\x08 \x08");
838 }
839 break;
840 case '\e':
841 vga_set_console(!vga_get_console());
842 break;
3a85405c »
2010-11-04 F8 boots from network
843 case 0x07:
844 break;
1f2f148a »
2010-10-01 Toggle console with ESC
845 case '\r':
846 case '\n':
847 s[ptr] = 0x00;
848 putsnonl("\n");
849 return;
850 default:
2b7f981d »
2010-10-04 Atomic console prints
851 putsnonl(c);
82e4e557 »
2010-10-05 Version command + fixes
852 s[ptr] = c[0];
1f2f148a »
2010-10-01 Toggle console with ESC
853 ptr++;
854 break;
855 }
856 }
857 }
858
46d2c61d »
2011-06-15 BIOS: reset ethernet PHY a second time
859 static void ethreset_delay()
860 {
861 CSR_TIMER0_COUNTER = 0;
028c9f6c »
2011-11-22 software: remove redundant clk_frequency
862 CSR_TIMER0_COMPARE = CSR_FREQUENCY >> 2;
46d2c61d »
2011-06-15 BIOS: reset ethernet PHY a second time
863 CSR_TIMER0_CONTROL = TIMER_ENABLE;
864 while(CSR_TIMER0_CONTROL & TIMER_ENABLE);
865 }
866
867 static void ethreset()
868 {
869 CSR_MINIMAC_SETUP = MINIMAC_SETUP_PHYRST;
870 ethreset_delay();
871 CSR_MINIMAC_SETUP = 0;
872 ethreset_delay();
873 }
874
920039a8 »
2010-01-14 New reset system
875 int main(int i, char **c)
212b9de4 »
2009-10-03 Missing files
876 {
877 char buffer[64];
878
631a8262 »
2011-11-22 bios: lock gdbstub ROM
879 /* lock gdbstub ROM */
880 CSR_DBG_CTRL = DBG_CTRL_GDB_ROM_LOCK;
881
efaf4216 »
2011-11-22 bios: enable bus errors
882 /* enable bus errors */
883 CSR_DBG_CTRL = DBG_CTRL_BUS_ERR_EN;
884
99cc4577 »
2010-08-30 New flash map and standby/rescue bitstream
885 CSR_GPIO_OUT = GPIO_LED1;
ab96e51c »
2010-11-18 Fix rescue mode detection
886 rescue = !((unsigned int)main > FLASH_OFFSET_REGULAR_BIOS);
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
887
35fda58b »
2010-10-01 Console hooks + use HAL and interrupts in BIOS
888 irq_setmask(0);
889 irq_enable(1);
890 uart_init();
00eea7cd »
2011-04-28 BIOS: disable splash screen and console to prevent unnecessary screen…
891 vga_init(!(rescue || (CSR_GPIO_IN & GPIO_BTN2)));
212b9de4 »
2009-10-03 Missing files
892 putsnonl(banner);
35fda58b »
2010-10-01 Console hooks + use HAL and interrupts in BIOS
893 crcbios();
c877aa23 »
2011-12-23 cosmetic changes
894 // brd_init();
f675333b »
2011-12-11 added support for short int signed read from unsigned int reg from ac…
895 //tmu_init(); /* < for hardware-accelerated scrolling */
21494e33 »
2011-11-26 added some utils to bios (namuru memory test and support to visualize…
896 //usb_init();
897 //ukb_init();
35fda58b »
2010-10-01 Console hooks + use HAL and interrupts in BIOS
898
99cc4577 »
2010-08-30 New flash map and standby/rescue bitstream
899 if(rescue)
900 printf("I: Booting in rescue mode\n");
b6ec68c8 »
2010-10-28 MAC address in flash + SoC versioning
901
21494e33 »
2011-11-26 added some utils to bios (namuru memory test and support to visualize…
902 //splash_display();
c877aa23 »
2011-12-23 cosmetic changes
903 //ethreset(); /* < that pesky ethernet PHY needs two resets at times... */
904 //print_mac();
905 //boot_sequence(); //enable for rtems booting from NOR
f675333b »
2011-12-11 added support for short int signed read from unsigned int reg from ac…
906 //vga_unblank();
907 //vga_set_console(1);
212b9de4 »
2009-10-03 Missing files
908 while(1) {
909 putsnonl("\e[1mBIOS>\e[0m ");
910 readstr(buffer, 64);
911 do_command(buffer);
912 }
913 return 0;
914 }
Something went wrong with that request. Please try again.