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