start_32.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. /*
  2. * Copyright (C) 1996 Paul Mackerras.
  3. */
  4. #include <linux/config.h>
  5. #include <linux/string.h>
  6. #include <asm/machdep.h>
  7. #include <asm/io.h>
  8. #include <asm/page.h>
  9. #include <linux/adb.h>
  10. #include <linux/pmu.h>
  11. #include <linux/cuda.h>
  12. #include <linux/kernel.h>
  13. #include <linux/errno.h>
  14. #include <linux/bitops.h>
  15. #include <asm/xmon.h>
  16. #include <asm/prom.h>
  17. #include <asm/bootx.h>
  18. #include <asm/machdep.h>
  19. #include <asm/errno.h>
  20. #include <asm/pmac_feature.h>
  21. #include <asm/processor.h>
  22. #include <asm/delay.h>
  23. #include <asm/btext.h>
  24. #include <asm/time.h>
  25. #include "nonstdio.h"
  26. static volatile unsigned char __iomem *sccc, *sccd;
  27. unsigned int TXRDY, RXRDY, DLAB;
  28. static int use_serial;
  29. static int use_screen;
  30. static int via_modem;
  31. static int xmon_use_sccb;
  32. static struct device_node *channel_node;
  33. void buf_access(void)
  34. {
  35. if (DLAB)
  36. sccd[3] &= ~DLAB; /* reset DLAB */
  37. }
  38. extern int adb_init(void);
  39. #ifdef CONFIG_PPC_CHRP
  40. /*
  41. * This looks in the "ranges" property for the primary PCI host bridge
  42. * to find the physical address of the start of PCI/ISA I/O space.
  43. * It is basically a cut-down version of pci_process_bridge_OF_ranges.
  44. */
  45. static unsigned long chrp_find_phys_io_base(void)
  46. {
  47. struct device_node *node;
  48. unsigned int *ranges;
  49. unsigned long base = CHRP_ISA_IO_BASE;
  50. int rlen = 0;
  51. int np;
  52. node = find_devices("isa");
  53. if (node != NULL) {
  54. node = node->parent;
  55. if (node == NULL || node->type == NULL
  56. || strcmp(node->type, "pci") != 0)
  57. node = NULL;
  58. }
  59. if (node == NULL)
  60. node = find_devices("pci");
  61. if (node == NULL)
  62. return base;
  63. ranges = (unsigned int *) get_property(node, "ranges", &rlen);
  64. np = prom_n_addr_cells(node) + 5;
  65. while ((rlen -= np * sizeof(unsigned int)) >= 0) {
  66. if ((ranges[0] >> 24) == 1 && ranges[2] == 0) {
  67. /* I/O space starting at 0, grab the phys base */
  68. base = ranges[np - 3];
  69. break;
  70. }
  71. ranges += np;
  72. }
  73. return base;
  74. }
  75. #endif /* CONFIG_PPC_CHRP */
  76. void xmon_map_scc(void)
  77. {
  78. #ifdef CONFIG_PPC_MULTIPLATFORM
  79. volatile unsigned char __iomem *base;
  80. if (_machine == _MACH_Pmac) {
  81. struct device_node *np;
  82. unsigned long addr;
  83. #ifdef CONFIG_BOOTX_TEXT
  84. if (!use_screen && !use_serial
  85. && !machine_is_compatible("iMac")) {
  86. /* see if there is a keyboard in the device tree
  87. with a parent of type "adb" */
  88. for (np = find_devices("keyboard"); np; np = np->next)
  89. if (np->parent && np->parent->type
  90. && strcmp(np->parent->type, "adb") == 0)
  91. break;
  92. /* needs to be hacked if xmon_printk is to be used
  93. from within find_via_pmu() */
  94. #ifdef CONFIG_ADB_PMU
  95. if (np != NULL && boot_text_mapped && find_via_pmu())
  96. use_screen = 1;
  97. #endif
  98. #ifdef CONFIG_ADB_CUDA
  99. if (np != NULL && boot_text_mapped && find_via_cuda())
  100. use_screen = 1;
  101. #endif
  102. }
  103. if (!use_screen && (np = find_devices("escc")) != NULL) {
  104. /*
  105. * look for the device node for the serial port
  106. * we're using and see if it says it has a modem
  107. */
  108. char *name = xmon_use_sccb? "ch-b": "ch-a";
  109. char *slots;
  110. int l;
  111. np = np->child;
  112. while (np != NULL && strcmp(np->name, name) != 0)
  113. np = np->sibling;
  114. if (np != NULL) {
  115. /* XXX should parse this properly */
  116. channel_node = np;
  117. slots = get_property(np, "slot-names", &l);
  118. if (slots != NULL && l >= 10
  119. && strcmp(slots+4, "Modem") == 0)
  120. via_modem = 1;
  121. }
  122. }
  123. btext_drawstring("xmon uses ");
  124. if (use_screen)
  125. btext_drawstring("screen and keyboard\n");
  126. else {
  127. if (via_modem)
  128. btext_drawstring("modem on ");
  129. btext_drawstring(xmon_use_sccb? "printer": "modem");
  130. btext_drawstring(" port\n");
  131. }
  132. #endif /* CONFIG_BOOTX_TEXT */
  133. #ifdef CHRP_ESCC
  134. addr = 0xc1013020;
  135. #else
  136. addr = 0xf3013020;
  137. #endif
  138. TXRDY = 4;
  139. RXRDY = 1;
  140. np = find_devices("mac-io");
  141. if (np && np->n_addrs)
  142. addr = np->addrs[0].address + 0x13020;
  143. base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
  144. sccc = base + (addr & ~PAGE_MASK);
  145. sccd = sccc + 0x10;
  146. } else {
  147. base = (volatile unsigned char *) isa_io_base;
  148. #ifdef CONFIG_PPC_CHRP
  149. if (_machine == _MACH_chrp)
  150. base = (volatile unsigned char __iomem *)
  151. ioremap(chrp_find_phys_io_base(), 0x1000);
  152. #endif
  153. sccc = base + 0x3fd;
  154. sccd = base + 0x3f8;
  155. if (xmon_use_sccb) {
  156. sccc -= 0x100;
  157. sccd -= 0x100;
  158. }
  159. TXRDY = 0x20;
  160. RXRDY = 1;
  161. DLAB = 0x80;
  162. }
  163. #elif defined(CONFIG_GEMINI)
  164. /* should already be mapped by the kernel boot */
  165. sccc = (volatile unsigned char __iomem *) 0xffeffb0d;
  166. sccd = (volatile unsigned char __iomem *) 0xffeffb08;
  167. TXRDY = 0x20;
  168. RXRDY = 1;
  169. DLAB = 0x80;
  170. #elif defined(CONFIG_405GP)
  171. sccc = (volatile unsigned char __iomem *)0xef600305;
  172. sccd = (volatile unsigned char __iomem *)0xef600300;
  173. TXRDY = 0x20;
  174. RXRDY = 1;
  175. DLAB = 0x80;
  176. #endif /* platform */
  177. }
  178. static int scc_initialized = 0;
  179. void xmon_init_scc(void);
  180. extern void cuda_poll(void);
  181. static inline void do_poll_adb(void)
  182. {
  183. #ifdef CONFIG_ADB_PMU
  184. if (sys_ctrler == SYS_CTRLER_PMU)
  185. pmu_poll_adb();
  186. #endif /* CONFIG_ADB_PMU */
  187. #ifdef CONFIG_ADB_CUDA
  188. if (sys_ctrler == SYS_CTRLER_CUDA)
  189. cuda_poll();
  190. #endif /* CONFIG_ADB_CUDA */
  191. }
  192. int xmon_write(void *ptr, int nb)
  193. {
  194. char *p = ptr;
  195. int i, c, ct;
  196. #ifdef CONFIG_SMP
  197. static unsigned long xmon_write_lock;
  198. int lock_wait = 1000000;
  199. int locked;
  200. while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
  201. if (--lock_wait == 0)
  202. break;
  203. #endif
  204. #ifdef CONFIG_BOOTX_TEXT
  205. if (use_screen) {
  206. /* write it on the screen */
  207. for (i = 0; i < nb; ++i)
  208. btext_drawchar(*p++);
  209. goto out;
  210. }
  211. #endif
  212. if (!scc_initialized)
  213. xmon_init_scc();
  214. ct = 0;
  215. for (i = 0; i < nb; ++i) {
  216. while ((*sccc & TXRDY) == 0)
  217. do_poll_adb();
  218. c = p[i];
  219. if (c == '\n' && !ct) {
  220. c = '\r';
  221. ct = 1;
  222. --i;
  223. } else {
  224. ct = 0;
  225. }
  226. buf_access();
  227. *sccd = c;
  228. eieio();
  229. }
  230. out:
  231. #ifdef CONFIG_SMP
  232. if (!locked)
  233. clear_bit(0, &xmon_write_lock);
  234. #endif
  235. return nb;
  236. }
  237. int xmon_wants_key;
  238. int xmon_adb_keycode;
  239. #ifdef CONFIG_BOOTX_TEXT
  240. static int xmon_adb_shiftstate;
  241. static unsigned char xmon_keytab[128] =
  242. "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
  243. "yt123465=97-80]o" /* 0x10 - 0x1f */
  244. "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
  245. "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
  246. "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
  247. "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
  248. static unsigned char xmon_shift_keytab[128] =
  249. "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
  250. "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
  251. "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
  252. "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
  253. "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
  254. "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
  255. static int xmon_get_adb_key(void)
  256. {
  257. int k, t, on;
  258. xmon_wants_key = 1;
  259. for (;;) {
  260. xmon_adb_keycode = -1;
  261. t = 0;
  262. on = 0;
  263. do {
  264. if (--t < 0) {
  265. on = 1 - on;
  266. btext_drawchar(on? 0xdb: 0x20);
  267. btext_drawchar('\b');
  268. t = 200000;
  269. }
  270. do_poll_adb();
  271. } while (xmon_adb_keycode == -1);
  272. k = xmon_adb_keycode;
  273. if (on)
  274. btext_drawstring(" \b");
  275. /* test for shift keys */
  276. if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
  277. xmon_adb_shiftstate = (k & 0x80) == 0;
  278. continue;
  279. }
  280. if (k >= 0x80)
  281. continue; /* ignore up transitions */
  282. k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
  283. if (k != 0)
  284. break;
  285. }
  286. xmon_wants_key = 0;
  287. return k;
  288. }
  289. #endif /* CONFIG_BOOTX_TEXT */
  290. int xmon_readchar(void)
  291. {
  292. #ifdef CONFIG_BOOTX_TEXT
  293. if (use_screen)
  294. return xmon_get_adb_key();
  295. #endif
  296. if (!scc_initialized)
  297. xmon_init_scc();
  298. while ((*sccc & RXRDY) == 0)
  299. do_poll_adb();
  300. buf_access();
  301. return *sccd;
  302. }
  303. int xmon_read_poll(void)
  304. {
  305. if ((*sccc & RXRDY) == 0) {
  306. do_poll_adb();
  307. return -1;
  308. }
  309. buf_access();
  310. return *sccd;
  311. }
  312. static unsigned char scc_inittab[] = {
  313. 13, 0, /* set baud rate divisor */
  314. 12, 1,
  315. 14, 1, /* baud rate gen enable, src=rtxc */
  316. 11, 0x50, /* clocks = br gen */
  317. 5, 0xea, /* tx 8 bits, assert DTR & RTS */
  318. 4, 0x46, /* x16 clock, 1 stop */
  319. 3, 0xc1, /* rx enable, 8 bits */
  320. };
  321. void xmon_init_scc(void)
  322. {
  323. if ( _machine == _MACH_chrp )
  324. {
  325. sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
  326. sccd[0] = 12; eieio(); /* DLL = 9600 baud */
  327. sccd[1] = 0; eieio();
  328. sccd[2] = 0; eieio(); /* FCR = 0 */
  329. sccd[3] = 3; eieio(); /* LCR = 8N1 */
  330. sccd[1] = 0; eieio(); /* IER = 0 */
  331. }
  332. else if ( _machine == _MACH_Pmac )
  333. {
  334. int i, x;
  335. unsigned long timeout;
  336. if (channel_node != 0)
  337. pmac_call_feature(
  338. PMAC_FTR_SCC_ENABLE,
  339. channel_node,
  340. PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
  341. printk(KERN_INFO "Serial port locked ON by debugger !\n");
  342. if (via_modem && channel_node != 0) {
  343. unsigned int t0;
  344. pmac_call_feature(
  345. PMAC_FTR_MODEM_ENABLE,
  346. channel_node, 0, 1);
  347. printk(KERN_INFO "Modem powered up by debugger !\n");
  348. t0 = get_tbl();
  349. timeout = 3 * tb_ticks_per_sec;
  350. if (timeout == 0)
  351. /* assume 25MHz if tb_ticks_per_sec not set */
  352. timeout = 75000000;
  353. while (get_tbl() - t0 < timeout)
  354. eieio();
  355. }
  356. /* use the B channel if requested */
  357. if (xmon_use_sccb) {
  358. sccc = (volatile unsigned char *)
  359. ((unsigned long)sccc & ~0x20);
  360. sccd = sccc + 0x10;
  361. }
  362. for (i = 20000; i != 0; --i) {
  363. x = *sccc; eieio();
  364. }
  365. *sccc = 9; eieio(); /* reset A or B side */
  366. *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
  367. for (i = 0; i < sizeof(scc_inittab); ++i) {
  368. *sccc = scc_inittab[i];
  369. eieio();
  370. }
  371. }
  372. scc_initialized = 1;
  373. if (via_modem) {
  374. for (;;) {
  375. xmon_write("ATE1V1\r", 7);
  376. if (xmon_expect("OK", 5)) {
  377. xmon_write("ATA\r", 4);
  378. if (xmon_expect("CONNECT", 40))
  379. break;
  380. }
  381. xmon_write("+++", 3);
  382. xmon_expect("OK", 3);
  383. }
  384. }
  385. }
  386. void xmon_enter(void)
  387. {
  388. #ifdef CONFIG_ADB_PMU
  389. if (_machine == _MACH_Pmac) {
  390. pmu_suspend();
  391. }
  392. #endif
  393. }
  394. void xmon_leave(void)
  395. {
  396. #ifdef CONFIG_ADB_PMU
  397. if (_machine == _MACH_Pmac) {
  398. pmu_resume();
  399. }
  400. #endif
  401. }