annotate target-utils/libcommon/cmd_baud_switch.c @ 635:658a83ff7221

gsm-fw/sysglue/flashboot.S: buglet in the previous change
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 01 Sep 2014 18:45:37 +0000
parents 437f9365249c
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
37
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
1 /*
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
2 * Baud rate switching command
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
3 */
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
4
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
5 #include <stdlib.h>
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
6 #include "types.h"
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
7 #include "ns16550.h"
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
8
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
9 extern struct ns16550_regs *uart_base;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
10 extern int serial_in_poll();
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
11
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
12 static const struct tab {
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
13 int baud;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
14 int divisor;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
15 } rate_table[] = {
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
16 /*
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
17 * First support the rates and divisors implemented by the
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
18 * Calypso boot ROM. Dividing 13 MHz by 7 gives an approximation
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
19 * of 115200 (x16); the divisors used by the boot ROM code for
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
20 * the slower baud rates are all 7x the usual PC value.
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
21 */
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
22 {115200, 7},
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
23 {57600, 7 * 2},
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
24 {38400, 7 * 3},
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
25 {28800, 7 * 4},
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
26 {19200, 7 * 6},
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
27 /*
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
28 * Going faster than ~115200 baud means using a divisor
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
29 * less than 7, resulting in a non-standard baud rate.
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
30 * The /1, /2 and /4 seem like reasonable choices.
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
31 */
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
32 {812500, 1},
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
33 {406250, 2},
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
34 {203125, 4},
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
35 /* that's all we really need to support */
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
36 {0, 0}
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
37 };
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
38
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
39 /*
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
40 * The following helper function actually switches the UART
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
41 * baud rate divisor. Call serial_flush() first. It returns the
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
42 * old divisor value.
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
43 *
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
44 * Note the u8 type for both the new and old divisor values.
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
45 * All supported divisors are well below 255, so we don't bother
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
46 * with the upper byte.
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
47 */
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
48 static u8
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
49 actually_switch_baud(newdiv)
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
50 u8 newdiv;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
51 {
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
52 volatile struct ns16550_regs *regs;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
53 u8 save_lcr, save_old_baud;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
54
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
55 regs = uart_base;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
56 save_lcr = regs->lcr;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
57 regs->lcr = save_lcr | NS16550_LCR_DLAB;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
58 save_old_baud = regs->datareg;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
59 regs->datareg = newdiv;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
60 regs->lcr = save_lcr;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
61 return(save_old_baud);
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
62 }
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
63
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
64 void
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
65 cmd_baud_switch(argbulk)
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
66 char *argbulk;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
67 {
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
68 char *argv[2];
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
69 int baudarg;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
70 struct tab *tp;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
71 u8 save_old_baud;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
72 int c;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
73
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
74 if (parse_args(argbulk, 1, 1, argv, 0) < 0)
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
75 return;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
76 baudarg = atoi(argv[0]);
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
77 for (tp = rate_table; tp->baud; tp++)
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
78 if (tp->baud == baudarg)
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
79 break;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
80 if (!tp->baud) {
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
81 printf("ERROR: invalid/unimplemented baud rate argument\n");
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
82 return;
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
83 }
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
84
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
85 /* do it */
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
86 serial_flush();
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
87 save_old_baud = actually_switch_baud(tp->divisor);
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
88
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
89 /*
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
90 * After getting the echo of this command at the old baud rate
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
91 * (see the serial flush call just before switching the divisor),
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
92 * the line will go silent from the user's perspective.
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
93 * The user should wait just a little bit, then send us a 0x55 ('U')
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
94 * at the new baud rate - we should be in the below loop waiting
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
95 * for this character by then. Receiving that character
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
96 * correctly (0x55 was chosen for the bit pattern - unlikely to
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
97 * be received if the sender is sending at a wrong baud rate)
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
98 * will cause us to conclude this command and return a new '='
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
99 * prompt at the new baud rate.
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
100 *
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
101 * If we get something else, we assume that someone messed up,
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
102 * switch back to the old baud rate, scribble an error message
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
103 * and return.
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
104 */
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
105 do
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
106 c = serial_in_poll();
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
107 while (c < 0);
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
108 if (c != 0x55) {
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
109 actually_switch_baud(save_old_baud);
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
110 printf("ERROR: no \'U\' received, switched back to old baud rate\n");
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
111 }
437f9365249c loadagent: baud rate switching implemented
Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
parents:
diff changeset
112 }