start.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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/machdep.h>
  14. #include <asm/errno.h>
  15. #include <asm/processor.h>
  16. #include <asm/delay.h>
  17. #include <asm/btext.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. #ifdef CONFIG_PPC_PREP
  51. volatile unsigned char *base;
  52. #elif defined(CONFIG_GEMINI)
  53. /* should already be mapped by the kernel boot */
  54. sccc = (volatile unsigned char *) 0xffeffb0d;
  55. sccd = (volatile unsigned char *) 0xffeffb08;
  56. TXRDY = 0x20;
  57. RXRDY = 1;
  58. DLAB = 0x80;
  59. #elif defined(CONFIG_405GP)
  60. sccc = (volatile unsigned char *)0xef600305;
  61. sccd = (volatile unsigned char *)0xef600300;
  62. TXRDY = 0x20;
  63. RXRDY = 1;
  64. DLAB = 0x80;
  65. #endif /* platform */
  66. register_sysrq_key('x', &sysrq_xmon_op);
  67. }
  68. static int scc_initialized;
  69. void xmon_init_scc(void);
  70. int
  71. xmon_write(void *handle, void *ptr, int nb)
  72. {
  73. char *p = ptr;
  74. int i, c, ct;
  75. #ifdef CONFIG_SMP
  76. static unsigned long xmon_write_lock;
  77. int lock_wait = 1000000;
  78. int locked;
  79. while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
  80. if (--lock_wait == 0)
  81. break;
  82. #endif
  83. if (!scc_initialized)
  84. xmon_init_scc();
  85. ct = 0;
  86. for (i = 0; i < nb; ++i) {
  87. while ((*sccc & TXRDY) == 0)
  88. ;
  89. c = p[i];
  90. if (c == '\n' && !ct) {
  91. c = '\r';
  92. ct = 1;
  93. --i;
  94. } else {
  95. ct = 0;
  96. }
  97. buf_access();
  98. *sccd = c;
  99. eieio();
  100. }
  101. #ifdef CONFIG_SMP
  102. if (!locked)
  103. clear_bit(0, &xmon_write_lock);
  104. #endif
  105. return nb;
  106. }
  107. int xmon_wants_key;
  108. int
  109. xmon_read(void *handle, void *ptr, int nb)
  110. {
  111. char *p = ptr;
  112. int i;
  113. if (!scc_initialized)
  114. xmon_init_scc();
  115. for (i = 0; i < nb; ++i) {
  116. while ((*sccc & RXRDY) == 0)
  117. ;
  118. buf_access();
  119. *p++ = *sccd;
  120. }
  121. return i;
  122. }
  123. int
  124. xmon_read_poll(void)
  125. {
  126. if ((*sccc & RXRDY) == 0) {
  127. ;
  128. return -1;
  129. }
  130. buf_access();
  131. return *sccd;
  132. }
  133. void
  134. xmon_init_scc(void)
  135. {
  136. scc_initialized = 1;
  137. if (via_modem) {
  138. for (;;) {
  139. xmon_write(NULL, "ATE1V1\r", 7);
  140. if (xmon_expect("OK", 5)) {
  141. xmon_write(NULL, "ATA\r", 4);
  142. if (xmon_expect("CONNECT", 40))
  143. break;
  144. }
  145. xmon_write(NULL, "+++", 3);
  146. xmon_expect("OK", 3);
  147. }
  148. }
  149. }
  150. void *xmon_stdin;
  151. void *xmon_stdout;
  152. void *xmon_stderr;
  153. void
  154. xmon_init(int arg)
  155. {
  156. xmon_map_scc();
  157. }
  158. int
  159. xmon_putc(int c, void *f)
  160. {
  161. char ch = c;
  162. if (c == '\n')
  163. xmon_putc('\r', f);
  164. return xmon_write(f, &ch, 1) == 1? c: -1;
  165. }
  166. int
  167. xmon_putchar(int c)
  168. {
  169. return xmon_putc(c, xmon_stdout);
  170. }
  171. int
  172. xmon_fputs(char *str, void *f)
  173. {
  174. int n = strlen(str);
  175. return xmon_write(f, str, n) == n? 0: -1;
  176. }
  177. int
  178. xmon_readchar(void)
  179. {
  180. char ch;
  181. for (;;) {
  182. switch (xmon_read(xmon_stdin, &ch, 1)) {
  183. case 1:
  184. return ch;
  185. case -1:
  186. xmon_printf("read(stdin) returned -1\r\n", 0, 0);
  187. return -1;
  188. }
  189. }
  190. }
  191. static char line[256];
  192. static char *lineptr;
  193. static int lineleft;
  194. int xmon_expect(const char *str, unsigned int timeout)
  195. {
  196. int c;
  197. unsigned int t0;
  198. timeout *= TB_SPEED;
  199. t0 = readtb();
  200. do {
  201. lineptr = line;
  202. for (;;) {
  203. c = xmon_read_poll();
  204. if (c == -1) {
  205. if (readtb() - t0 > timeout)
  206. return 0;
  207. continue;
  208. }
  209. if (c == '\n')
  210. break;
  211. if (c != '\r' && lineptr < &line[sizeof(line) - 1])
  212. *lineptr++ = c;
  213. }
  214. *lineptr = 0;
  215. } while (strstr(line, str) == NULL);
  216. return 1;
  217. }
  218. int
  219. xmon_getchar(void)
  220. {
  221. int c;
  222. if (lineleft == 0) {
  223. lineptr = line;
  224. for (;;) {
  225. c = xmon_readchar();
  226. if (c == -1 || c == 4)
  227. break;
  228. if (c == '\r' || c == '\n') {
  229. *lineptr++ = '\n';
  230. xmon_putchar('\n');
  231. break;
  232. }
  233. switch (c) {
  234. case 0177:
  235. case '\b':
  236. if (lineptr > line) {
  237. xmon_putchar('\b');
  238. xmon_putchar(' ');
  239. xmon_putchar('\b');
  240. --lineptr;
  241. }
  242. break;
  243. case 'U' & 0x1F:
  244. while (lineptr > line) {
  245. xmon_putchar('\b');
  246. xmon_putchar(' ');
  247. xmon_putchar('\b');
  248. --lineptr;
  249. }
  250. break;
  251. default:
  252. if (lineptr >= &line[sizeof(line) - 1])
  253. xmon_putchar('\a');
  254. else {
  255. xmon_putchar(c);
  256. *lineptr++ = c;
  257. }
  258. }
  259. }
  260. lineleft = lineptr - line;
  261. lineptr = line;
  262. }
  263. if (lineleft == 0)
  264. return -1;
  265. --lineleft;
  266. return *lineptr++;
  267. }
  268. char *
  269. xmon_fgets(char *str, int nb, void *f)
  270. {
  271. char *p;
  272. int c;
  273. for (p = str; p < str + nb - 1; ) {
  274. c = xmon_getchar();
  275. if (c == -1) {
  276. if (p == str)
  277. return NULL;
  278. break;
  279. }
  280. *p++ = c;
  281. if (c == '\n')
  282. break;
  283. }
  284. *p = 0;
  285. return str;
  286. }
  287. void
  288. xmon_enter(void)
  289. {
  290. }
  291. void
  292. xmon_leave(void)
  293. {
  294. }