start.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * Copyright (C) 1996 Paul Mackerras.
  3. */
  4. #include <linux/string.h>
  5. #include <asm/machdep.h>
  6. #include <asm/io.h>
  7. #include <asm/page.h>
  8. #include <linux/kernel.h>
  9. #include <linux/errno.h>
  10. #include <linux/sysrq.h>
  11. #include <linux/bitops.h>
  12. #include <asm/xmon.h>
  13. #include <asm/errno.h>
  14. #include <asm/processor.h>
  15. #include <asm/delay.h>
  16. #include <asm/btext.h>
  17. #include <asm/ibm4xx.h>
  18. static volatile unsigned char *sccc, *sccd;
  19. unsigned int TXRDY, RXRDY, DLAB;
  20. static int xmon_expect(const char *str, unsigned int timeout);
  21. static int via_modem;
  22. #define TB_SPEED 25000000
  23. static inline unsigned int readtb(void)
  24. {
  25. unsigned int ret;
  26. asm volatile("mftb %0" : "=r" (ret) :);
  27. return ret;
  28. }
  29. void buf_access(void)
  30. {
  31. if (DLAB)
  32. sccd[3] &= ~DLAB; /* reset DLAB */
  33. }
  34. #ifdef CONFIG_MAGIC_SYSRQ
  35. static void sysrq_handle_xmon(int key, struct pt_regs *regs,
  36. struct tty_struct *tty)
  37. {
  38. xmon(regs);
  39. }
  40. static struct sysrq_key_op sysrq_xmon_op =
  41. {
  42. .handler = sysrq_handle_xmon,
  43. .help_msg = "Xmon",
  44. .action_msg = "Entering xmon",
  45. };
  46. #endif
  47. void
  48. xmon_map_scc(void)
  49. {
  50. #if defined(CONFIG_405GP)
  51. sccd = (volatile unsigned char *)0xef600300;
  52. #elif defined(CONFIG_440EP)
  53. sccd = (volatile unsigned char *) ioremap(PPC440EP_UART0_ADDR, 8);
  54. #elif defined(CONFIG_440SP)
  55. sccd = (volatile unsigned char *) ioremap64(PPC440SP_UART0_ADDR, 8);
  56. #elif defined(CONFIG_440SPE)
  57. sccd = (volatile unsigned char *) ioremap64(PPC440SPE_UART0_ADDR, 8);
  58. #elif defined(CONFIG_44x)
  59. /* This is the default for 44x platforms. Any boards that have a
  60. different UART address need to be put in cases before this or the
  61. port will be mapped incorrectly */
  62. sccd = (volatile unsigned char *) ioremap64(PPC440GP_UART0_ADDR, 8);
  63. #endif /* platform */
  64. #ifndef CONFIG_PPC_PREP
  65. sccc = sccd + 5;
  66. TXRDY = 0x20;
  67. RXRDY = 1;
  68. DLAB = 0x80;
  69. #endif
  70. register_sysrq_key('x', &sysrq_xmon_op);
  71. }
  72. static int scc_initialized;
  73. void xmon_init_scc(void);
  74. int
  75. xmon_write(void *handle, void *ptr, int nb)
  76. {
  77. char *p = ptr;
  78. int i, c, ct;
  79. #ifdef CONFIG_SMP
  80. static unsigned long xmon_write_lock;
  81. int lock_wait = 1000000;
  82. int locked;
  83. while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
  84. if (--lock_wait == 0)
  85. break;
  86. #endif
  87. if (!scc_initialized)
  88. xmon_init_scc();
  89. ct = 0;
  90. for (i = 0; i < nb; ++i) {
  91. while ((*sccc & TXRDY) == 0)
  92. ;
  93. c = p[i];
  94. if (c == '\n' && !ct) {
  95. c = '\r';
  96. ct = 1;
  97. --i;
  98. } else {
  99. ct = 0;
  100. }
  101. buf_access();
  102. *sccd = c;
  103. eieio();
  104. }
  105. #ifdef CONFIG_SMP
  106. if (!locked)
  107. clear_bit(0, &xmon_write_lock);
  108. #endif
  109. return nb;
  110. }
  111. int xmon_wants_key;
  112. int
  113. xmon_read(void *handle, void *ptr, int nb)
  114. {
  115. char *p = ptr;
  116. int i;
  117. if (!scc_initialized)
  118. xmon_init_scc();
  119. for (i = 0; i < nb; ++i) {
  120. while ((*sccc & RXRDY) == 0)
  121. ;
  122. buf_access();
  123. *p++ = *sccd;
  124. }
  125. return i;
  126. }
  127. int
  128. xmon_read_poll(void)
  129. {
  130. if ((*sccc & RXRDY) == 0) {
  131. ;
  132. return -1;
  133. }
  134. buf_access();
  135. return *sccd;
  136. }
  137. void
  138. xmon_init_scc(void)
  139. {
  140. scc_initialized = 1;
  141. if (via_modem) {
  142. for (;;) {
  143. xmon_write(NULL, "ATE1V1\r", 7);
  144. if (xmon_expect("OK", 5)) {
  145. xmon_write(NULL, "ATA\r", 4);
  146. if (xmon_expect("CONNECT", 40))
  147. break;
  148. }
  149. xmon_write(NULL, "+++", 3);
  150. xmon_expect("OK", 3);
  151. }
  152. }
  153. }
  154. void *xmon_stdin;
  155. void *xmon_stdout;
  156. void *xmon_stderr;
  157. void
  158. xmon_init(int arg)
  159. {
  160. xmon_map_scc();
  161. }
  162. int
  163. xmon_putc(int c, void *f)
  164. {
  165. char ch = c;
  166. if (c == '\n')
  167. xmon_putc('\r', f);
  168. return xmon_write(f, &ch, 1) == 1? c: -1;
  169. }
  170. int
  171. xmon_putchar(int c)
  172. {
  173. return xmon_putc(c, xmon_stdout);
  174. }
  175. int
  176. xmon_fputs(char *str, void *f)
  177. {
  178. int n = strlen(str);
  179. return xmon_write(f, str, n) == n? 0: -1;
  180. }
  181. int
  182. xmon_readchar(void)
  183. {
  184. char ch;
  185. for (;;) {
  186. switch (xmon_read(xmon_stdin, &ch, 1)) {
  187. case 1:
  188. return ch;
  189. case -1:
  190. xmon_printf("read(stdin) returned -1\r\n", 0, 0);
  191. return -1;
  192. }
  193. }
  194. }
  195. static char line[256];
  196. static char *lineptr;
  197. static int lineleft;
  198. int xmon_expect(const char *str, unsigned int timeout)
  199. {
  200. int c;
  201. unsigned int t0;
  202. timeout *= TB_SPEED;
  203. t0 = readtb();
  204. do {
  205. lineptr = line;
  206. for (;;) {
  207. c = xmon_read_poll();
  208. if (c == -1) {
  209. if (readtb() - t0 > timeout)
  210. return 0;
  211. continue;
  212. }
  213. if (c == '\n')
  214. break;
  215. if (c != '\r' && lineptr < &line[sizeof(line) - 1])
  216. *lineptr++ = c;
  217. }
  218. *lineptr = 0;
  219. } while (strstr(line, str) == NULL);
  220. return 1;
  221. }
  222. int
  223. xmon_getchar(void)
  224. {
  225. int c;
  226. if (lineleft == 0) {
  227. lineptr = line;
  228. for (;;) {
  229. c = xmon_readchar();
  230. if (c == -1 || c == 4)
  231. break;
  232. if (c == '\r' || c == '\n') {
  233. *lineptr++ = '\n';
  234. xmon_putchar('\n');
  235. break;
  236. }
  237. switch (c) {
  238. case 0177:
  239. case '\b':
  240. if (lineptr > line) {
  241. xmon_putchar('\b');
  242. xmon_putchar(' ');
  243. xmon_putchar('\b');
  244. --lineptr;
  245. }
  246. break;
  247. case 'U' & 0x1F:
  248. while (lineptr > line) {
  249. xmon_putchar('\b');
  250. xmon_putchar(' ');
  251. xmon_putchar('\b');
  252. --lineptr;
  253. }
  254. break;
  255. default:
  256. if (lineptr >= &line[sizeof(line) - 1])
  257. xmon_putchar('\a');
  258. else {
  259. xmon_putchar(c);
  260. *lineptr++ = c;
  261. }
  262. }
  263. }
  264. lineleft = lineptr - line;
  265. lineptr = line;
  266. }
  267. if (lineleft == 0)
  268. return -1;
  269. --lineleft;
  270. return *lineptr++;
  271. }
  272. char *
  273. xmon_fgets(char *str, int nb, void *f)
  274. {
  275. char *p;
  276. int c;
  277. for (p = str; p < str + nb - 1; ) {
  278. c = xmon_getchar();
  279. if (c == -1) {
  280. if (p == str)
  281. return NULL;
  282. break;
  283. }
  284. *p++ = c;
  285. if (c == '\n')
  286. break;
  287. }
  288. *p = 0;
  289. return str;
  290. }
  291. void
  292. xmon_enter(void)
  293. {
  294. }
  295. void
  296. xmon_leave(void)
  297. {
  298. }