FreeCalypso > hg > freecalypso-sw
annotate target-utils/libcommon/cmd_baud_switch.c @ 206:9539929b3414
pirexplore: flashid command implemented
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Mon, 23 Dec 2013 19:32:22 +0000 |
parents | 437f9365249c |
children |
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 } |