add initial support for the crisarchitecture used on foxboards to openwrt
[openwrt/staging/lynxis/omap.git] / target / linux / etrax-2.6 / image / e100boot / src / sbl / serial.c
1 /*!***************************************************************************
2 *!
3 *! FILE NAME : serial.c
4 *!
5 *! DESCRIPTION: Serial boot stuff for e100boot.
6 *!
7 *! ---------------------------------------------------------------------------
8 *! HISTORY
9 *!
10 *! DATE NAME CHANGES
11 *! ---- ---- -------
12 *! 1996 Ronny Raneup Initial version
13 *! 2002 05 02 Ronny Ranerup Moved it into this file
14 *! ---------------------------------------------------------------------------
15 *! (C) Copyright 1999-2003 Axis Communications AB, LUND, SWEDEN
16 *!***************************************************************************/
17
18 /************************** Include files ********************************/
19
20 #include <conf.h>
21 #include <e100boot.h>
22 #include <serial.h>
23 #include <common.h>
24
25 /************************** Type definitions *****************************/
26
27 /************************** Global variables *****************************/
28
29 FILE *serialFd;
30 int set_baudrate = 9600; /* Baudrate for serial boot (after bootloader). */
31
32 /************************** Constants and macros *************************/
33
34 /************************** Function prototypes **************************/
35
36 int SetControlMode(FILE *fd, int value, int onoff);
37 int SetInputMode(FILE *fd, int value, int onoff);
38 int SetLocalMode(FILE *fd, int value, int onoff);
39 int SetOutputMode(FILE *fd, int value, int onoff);
40 int WaitForRead(int s, int usecs);
41 int WaitForWrite(int s, int usecs);
42 void setBaudRate(unsigned int b);
43
44 /****************************************************************************
45 *#
46 *# FUNCTION NAME: SerBoot
47 *#
48 *# DESCRIPTION: The main serial boot routine.
49 *#
50 *#---------------------------------------------------------------------------
51 *# HISTORY
52 *#
53 *# DATE NAME CHANGES
54 *# ---- ---- -------
55 *# 2000 01 07 ronny Initial version
56 *#
57 *#***************************************************************************/
58
59 void
60 SerBoot(void)
61 {
62 int seq = 0;
63 struct packet_buf *p;
64 int got_new_ack = 0;
65 int connected = 0;
66 char rec_buf;
67
68 while ((p = create_packet(seq))) {
69 int offset = 0;
70 int tr_len = 0;
71 static char fName[MAX_STRING_LEN] = {0,};
72
73 if (strcmp(fName, p->boot_file->fileName) != 0) {
74 while (connected && got_new_ack == 0) {
75 WaitForRead(fileno(serialFd), 1000000); /* Did we get data? */
76
77 if(fread(&rec_buf, 1, 1, serialFd) > 0) {
78 fwrite(&rec_buf, 1, 1, stderr);
79 if (rec_buf == '+') {
80 printf("# Got ack.\n");
81 got_new_ack = 1;
82 }
83 }
84 }
85
86 strcpy(fName, p->boot_file->fileName);
87 printf("# transmitting file '%s'\n", fName);
88 got_new_ack = 0;
89 }
90
91 printf("# transmitting %d bytes at baudrate %d.\n", (int)p->size, p->baud_rate);
92
93 // setBaudRate(p->baud_rate);
94
95 while (tr_len != p->size) {
96
97 if (WaitForRead(fileno(serialFd), 0)) { /* Did we get data? */
98 // static int connected = 0;
99 char rec_buf = 0;
100 int rec_len = 0;
101
102 if((rec_len = fread(&rec_buf, 1, 1, serialFd)) > 0) {
103 if (rec_buf == '+') {
104 if (!connected++) {
105 printf("# Got ack.\n");
106 }
107 else {
108 got_new_ack = 1;
109 printf("# Got ack.\n");
110 }
111 fwrite(&rec_buf, rec_len, 1, stderr);
112 }
113 }
114 }
115
116 if (tr_len < p->size) { /* send one byte */
117 while (!(WaitForWrite(fileno(serialFd), 1000000))) { }
118 fwrite(&p->data[offset+tr_len], 1, 1, serialFd);
119 tr_len++;
120 }
121 }
122
123 seq++; /* We have transmitted entire packet. */
124 }
125
126 printf("# Transmission done. Just listening now.\n");
127
128 while(1) {
129 if (WaitForRead(fileno(serialFd), 10000000)) { /* Did we get data? */
130 char rec_buf;
131 int rec_len = 0;
132
133 if((rec_len = fread(&rec_buf, 1, 1, serialFd)) > 0) {
134 fwrite(&rec_buf, rec_len, 1, stderr);
135 }
136 }
137 }
138 }
139
140 /****************************************************************************
141 *#
142 *# FUNCTION NAME: SetupSerial
143 *#
144 *# PARAMETERS:
145 *#
146 *# DESCRIPTION:
147 *#
148 *#---------------------------------------------------------------------------
149 *# HISTORY
150 *#
151 *# DATE NAME CHANGES
152 *# ---- ---- -------
153 *# 970325 ronny Initial version
154 *#
155 *#***************************************************************************/
156
157 int
158 SetupSerial(void)
159 {
160 int baudRates[] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
161 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200};
162 struct termios ti;
163 int baudrate;
164
165 if ((serialFd = fopen(device, "r+")) == NULL) {
166 perror("Can't open modem");
167 return FALSE;
168 }
169
170 /* Important. Remember this!!!!!!! */
171 /* setvbuf(serialFd, NULL, _IONBF, 0); */
172
173 setvbuf(serialFd, NULL, _IONBF, 0);
174 setvbuf(stdout, NULL, _IONBF, 0);
175
176 if (fcntl(fileno(serialFd), F_SETFL, O_NONBLOCK) == -1) {
177 perror("fcntl");
178 return FALSE;
179 }
180
181 tcflush(fileno(serialFd), TCIOFLUSH);
182
183 if (tcgetattr(fileno(serialFd), &ti)) {
184 perror("tcgetattr");
185 return FALSE;
186 }
187
188 ti.c_cc[VMIN] = 1;
189 ti.c_cc[VTIME] = 0;
190 ti.c_cc[VSTART] = 0x11;
191 ti.c_cc[VSTOP] = 0x13;
192
193 if (tcsetattr(fileno(serialFd), TCSANOW, &ti)) {
194 perror("tcsetattr");
195 return FALSE;
196 }
197
198 //if (db3) printf("outspeed: %d, inspeed: %d\n", baudRates[cfgetospeed(&ti)], baudRates[cfgetispeed(&ti)]);
199 {
200 int new_baudrate = 0;
201
202 if (set_baudrate <= 50) {
203 baudrate = B50;
204 new_baudrate = 50;
205 }
206 else if (set_baudrate <= 75) {
207 baudrate = B75;
208 new_baudrate = 75;
209 }
210 else if (set_baudrate <= 110) {
211 baudrate = B110;
212 new_baudrate = 110;
213 }
214 else if (set_baudrate <= 134) {
215 baudrate = B134;
216 new_baudrate = 134;
217 }
218 else if (set_baudrate <= 150) {
219 baudrate = B150;
220 new_baudrate = 150;
221 }
222 else if (set_baudrate <= 200) {
223 baudrate = B200;
224 new_baudrate = 200;
225 }
226 else if (set_baudrate <= 300) {
227 baudrate = B300;
228 new_baudrate = 300;
229 }
230 else if (set_baudrate <= 600) {
231 baudrate = B600;
232 new_baudrate = 600;
233 }
234 else if (set_baudrate <= 1200) {
235 baudrate = B1200;
236 new_baudrate = 1200;
237 }
238 else if (set_baudrate <= 1800) {
239 baudrate = B1800;
240 new_baudrate = 1800;
241 }
242 else if (set_baudrate <= 2400) {
243 baudrate = B2400;
244 new_baudrate = 2400;
245 }
246 else if (set_baudrate <= 4800) {
247 baudrate = B4800;
248 new_baudrate = 4800;
249 }
250 else if (set_baudrate <= 9600) {
251 baudrate = B9600;
252 new_baudrate = 9600;
253 }
254 else if (set_baudrate <= 19200) {
255 baudrate = B19200;
256 new_baudrate = 19200;
257 }
258 else if (set_baudrate <= 38400)
259 baudrate = B38400;
260 #if defined(B57600) /* POSIX only defines <= 38400 */
261 else if (set_baudrate <= 57600) {
262 baudrate = B57600;
263 new_baudrate = 57600;
264 }
265 #endif
266 #if defined(B115200)
267 else if (set_baudrate <= 115200) {
268 baudrate = B115200;
269 new_baudrate = 115200;
270 }
271 #endif
272 #if defined(B230400)
273 else if (set_baudrate <= 230400) {
274 baudrate = B230400;
275 new_baudrate = 230400;
276 }
277 #endif
278 else {
279 baudrate = B38400;
280 }
281
282 cfsetispeed(&ti, B9600);
283 cfsetospeed(&ti, baudrate);
284 tcsetattr(fileno(serialFd), TCSANOW, &ti);
285
286 // printf("* baudrate set to %d\n", new_baudrate);
287 set_baudrate = new_baudrate;
288
289 if (db3) printf("outspeed: %d, inspeed: %d\n", baudRates[cfgetospeed(&ti)], baudRates[cfgetispeed(&ti)]);
290 }
291
292 cfmakeraw(&ti);
293
294 SetInputMode(serialFd, IXON, FALSE);
295 SetInputMode(serialFd, IXOFF, FALSE);
296 SetInputMode(serialFd, IXANY, FALSE);
297 SetInputMode(serialFd, ICRNL, FALSE);
298 SetInputMode(serialFd, IGNPAR, TRUE);
299 SetInputMode(serialFd, IGNBRK, TRUE);
300 SetInputMode(serialFd, IGNPAR, TRUE);
301 SetInputMode(serialFd, INPCK, FALSE);
302
303 SetOutputMode(serialFd, OPOST, FALSE);
304 SetOutputMode(serialFd, ONLCR, FALSE);
305 #ifdef OXTABS
306 SetOutputMode(serialFd, OXTABS, FALSE);
307 #endif
308
309 #ifdef ENOEOT
310 SetOutputMode(serialFd, ENOEOT, FALSE);
311 #endif
312
313 SetLocalMode(serialFd, ECHO, FALSE);
314 SetLocalMode(serialFd, ISIG, FALSE);
315
316 SetLocalMode(serialFd, ICANON, FALSE);
317
318 SetControlMode(serialFd, PARENB, FALSE);
319 SetControlMode(serialFd, CLOCAL, TRUE);
320 SetControlMode(serialFd, CREAD, TRUE);
321
322 /* Disable hardware flow control. */
323 #if defined(CRTSCTS)
324
325 SetControlMode(serialFd, CRTSCTS, FALSE);
326 #if defined(CRTSXOFF)
327 SetControlMode(serialFd, CRTSXOFF, FALSE);
328 #endif
329
330 #elif defined(CCTS_OFLOW)
331
332 SetControlMode(serialFd, CCTS_OFLOW, FALSE);
333 SetControlMode(serialFd, CRTS_IFLOW, FALSE);
334
335 #elif defined(CNEW_RTSCTS)
336
337 SetControlMode(serialFd, CNEW_RTSCTS, FALSE);
338
339 #else
340 printf("Cannot set hardware flow control. Set it manually with a terminal program.\n");
341 #endif
342
343 return TRUE;
344 }
345
346 void
347 setBaudRate(unsigned int b)
348 {
349 int baudRates[] = {0, 50, 75, 110, 134, 150, 200, 300, 600,
350 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200};
351 struct termios ti;
352
353 if (tcgetattr(fileno(serialFd), &ti)) {
354 perror("tcgetattr");
355 exit(EXIT_FAILURE);
356 }
357 }
358
359 /****************************************************************************
360 *#
361 *# FUNCTION NAME: SetInputMode
362 *#
363 *# PARAMETERS:
364 *#
365 *# DESCRIPTION:
366 *#
367 *#---------------------------------------------------------------------------
368 *# HISTORY
369 *#
370 *# DATE NAME CHANGES
371 *# ---- ---- -------
372 *# 970325 ronny Initial version
373 *#
374 *#***************************************************************************/
375
376 int
377 SetInputMode(FILE *fd, int value, int onoff)
378 {
379 struct termios settings;
380 int result;
381
382 result = tcgetattr(fileno(fd), &settings);
383 if (result < 0)
384 {
385 perror("error in tcgetattr");
386 return FALSE;
387 }
388
389 if (onoff)
390 settings.c_iflag |= value;
391 else
392 settings.c_iflag &= ~value;
393
394 result = tcsetattr(fileno(fd), TCSANOW, &settings);
395 if (result < 0)
396 {
397 perror("error in tcgetattr");
398 return FALSE;
399 }
400
401 return 1;
402 }
403
404 /****************************************************************************
405 *#
406 *# FUNCTION NAME: SetOutputMode
407 *#
408 *# PARAMETERS:
409 *#
410 *# DESCRIPTION:
411 *#
412 *#---------------------------------------------------------------------------
413 *# HISTORY
414 *#
415 *# DATE NAME CHANGES
416 *# ---- ---- -------
417 *# 2001 May 16 ronny Initial version
418 *#
419 *#***************************************************************************/
420
421 int
422 SetOutputMode(FILE *fd, int value, int onoff)
423 {
424 struct termios settings;
425 int result;
426
427 result = tcgetattr(fileno(fd), &settings);
428 if (result < 0)
429 {
430 perror("error in tcgetattr");
431 return FALSE;
432 }
433
434 if (onoff)
435 settings.c_oflag |= value;
436 else
437 settings.c_oflag &= ~value;
438
439 result = tcsetattr(fileno(fd), TCSANOW, &settings);
440 if (result < 0)
441 {
442 perror("error in tcgetattr");
443 return FALSE;
444 }
445
446 return 1;
447 }
448
449 /****************************************************************************
450 *#
451 *# FUNCTION NAME: SetControlMode
452 *#
453 *# PARAMETERS:
454 *#
455 *# DESCRIPTION:
456 *#
457 *#---------------------------------------------------------------------------
458 *# HISTORY
459 *#
460 *# DATE NAME CHANGES
461 *# ---- ---- -------
462 *# 970325 ronny Initial version
463 *#
464 *#***************************************************************************/
465
466 int
467 SetControlMode(FILE *fd, int value, int onoff)
468 {
469 #if !defined(_WIN32)
470 struct termios settings;
471 int result;
472
473 result = tcgetattr(fileno(fd), &settings);
474 if (result < 0)
475 {
476 perror("error in tcgetattr");
477 return FALSE;
478 }
479
480 if (onoff)
481 settings.c_cflag |= value;
482 else
483 settings.c_cflag &= ~value;
484
485 result = tcsetattr(fileno(fd), TCSANOW, &settings);
486 if (result < 0)
487 {
488 perror("error in tcgetattr");
489 return FALSE;
490 }
491 #endif
492
493 return TRUE;
494 }
495 /****************************************************************************
496 *#
497 *# FUNCTION NAME: SetLocalMode
498 *#
499 *# PARAMETERS:
500 *#
501 *# DESCRIPTION:
502 *#
503 *#---------------------------------------------------------------------------
504 *# HISTORY
505 *#
506 *# DATE NAME CHANGES
507 *# ---- ---- -------
508 *# 970325 ronny Initial version
509 *#
510 *#***************************************************************************/
511
512 int
513 SetLocalMode(FILE *fd, int value, int onoff)
514 {
515 #if !defined(_WIN32)
516 struct termios settings;
517 int result;
518
519 result = tcgetattr(fileno(fd), &settings);
520 if (result < 0)
521 {
522 perror("error in tcgetattr");
523 return FALSE;
524 }
525
526 if (onoff)
527 settings.c_lflag |= value;
528 else
529 settings.c_lflag &= ~value;
530
531 result = tcsetattr(fileno(fd), TCSANOW, &settings);
532 if (result < 0)
533 {
534 perror("error in tcgetattr");
535 return FALSE;
536 }
537 #endif
538
539 return TRUE;
540 }
541
542 /****************************************************************************
543 *#
544 *# FUNCTION NAME: WaitForRead
545 *#
546 *# PARAMETERS: Timeout in usecs.
547 *#
548 *# DESCRIPTION:
549 *#
550 *#---------------------------------------------------------------------------
551 *# HISTORY
552 *#
553 *# DATE NAME CHANGES
554 *# ---- ---- -------
555 *# 961001 ronny Initial version
556 *# 971204 ronny usecs was a only one tenth of what it should be.
557 *#
558 *#***************************************************************************/
559
560 int
561 WaitForRead(int s, int usecs)
562 {
563 fd_set mask;
564 int ret;
565 struct timeval tm;
566
567 tm.tv_sec = usecs/1000000;
568 tm.tv_usec = usecs%1000000;
569
570 FD_ZERO(&mask);
571 FD_SET(s, &mask);
572
573 if ((ret = select(FD_SETSIZE, &mask, NULL, NULL, &tm)) == -1) {
574 printf("<<< select failed with return: %d.\n", ret);
575 return FALSE;
576 }
577 else {
578 if (db3) printf("* select returned OK:%d\n", ret);
579 }
580
581 if (FD_ISSET(s, &mask) == 0) {
582 if (db2) printf("<<< WaitForRead. No data to read.\n");
583 return FALSE;
584 }
585
586 if (db3) printf("<<< WaitForRead OK. Returned:%d.\n", ret);
587
588 return TRUE;
589 }
590
591 /****************************************************************************
592 *#
593 *# FUNCTION NAME: WaitForWrite
594 *#
595 *# PARAMETERS:
596 *#
597 *# DESCRIPTION:
598 *#
599 *#---------------------------------------------------------------------------
600 *# HISTORY
601 *#
602 *# DATE NAME CHANGES
603 *# ---- ---- -------
604 *# 2000-11-20 ronny Initial version
605 *#
606 *#***************************************************************************/
607
608 int
609 WaitForWrite(int s, int usecs)
610 {
611 fd_set mask;
612 int ret;
613 struct timeval tm;
614
615 tm.tv_sec = usecs/1000000;
616 tm.tv_usec = usecs%1000000;
617
618 FD_ZERO(&mask);
619 FD_SET(s, &mask);
620
621 if ((ret = select(FD_SETSIZE, NULL, &mask, NULL, &tm)) == -1) {
622 printf("<<< select failed with return: %d.\n", ret);
623 return FALSE;
624 }
625 else {
626 if (db3) printf("* select returned OK:%d\n", ret);
627 }
628
629 if (FD_ISSET(s, &mask) == 0) {
630 if (db2) printf("<<< WaitForWrite. No data to read.\n");
631 return FALSE;
632 }
633
634 if (db3) printf("<<< WaitForWrite OK. Returned:%d.\n", ret);
635
636 return TRUE;
637 }