start.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  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/sysrq.h>
  15. #include <linux/bitops.h>
  16. #include <asm/xmon.h>
  17. #include <asm/prom.h>
  18. #include <asm/bootx.h>
  19. #include <asm/machdep.h>
  20. #include <asm/errno.h>
  21. #include <asm/pmac_feature.h>
  22. #include <asm/processor.h>
  23. #include <asm/delay.h>
  24. #include <asm/btext.h>
  25. static volatile unsigned char *sccc, *sccd;
  26. unsigned int TXRDY, RXRDY, DLAB;
  27. static int xmon_expect(const char *str, unsigned int timeout);
  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. #define TB_SPEED 25000000
  34. static inline unsigned int readtb(void)
  35. {
  36. unsigned int ret;
  37. asm volatile("mftb %0" : "=r" (ret) :);
  38. return ret;
  39. }
  40. void buf_access(void)
  41. {
  42. if (DLAB)
  43. sccd[3] &= ~DLAB; /* reset DLAB */
  44. }
  45. extern int adb_init(void);
  46. #ifdef CONFIG_PPC_CHRP
  47. /*
  48. * This looks in the "ranges" property for the primary PCI host bridge
  49. * to find the physical address of the start of PCI/ISA I/O space.
  50. * It is basically a cut-down version of pci_process_bridge_OF_ranges.
  51. */
  52. static unsigned long chrp_find_phys_io_base(void)
  53. {
  54. struct device_node *node;
  55. unsigned int *ranges;
  56. unsigned long base = CHRP_ISA_IO_BASE;
  57. int rlen = 0;
  58. int np;
  59. node = find_devices("isa");
  60. if (node != NULL) {
  61. node = node->parent;
  62. if (node == NULL || node->type == NULL
  63. || strcmp(node->type, "pci") != 0)
  64. node = NULL;
  65. }
  66. if (node == NULL)
  67. node = find_devices("pci");
  68. if (node == NULL)
  69. return base;
  70. ranges = (unsigned int *) get_property(node, "ranges", &rlen);
  71. np = prom_n_addr_cells(node) + 5;
  72. while ((rlen -= np * sizeof(unsigned int)) >= 0) {
  73. if ((ranges[0] >> 24) == 1 && ranges[2] == 0) {
  74. /* I/O space starting at 0, grab the phys base */
  75. base = ranges[np - 3];
  76. break;
  77. }
  78. ranges += np;
  79. }
  80. return base;
  81. }
  82. #endif /* CONFIG_PPC_CHRP */
  83. #ifdef CONFIG_MAGIC_SYSRQ
  84. static void sysrq_handle_xmon(int key, struct pt_regs *regs,
  85. struct tty_struct *tty)
  86. {
  87. xmon(regs);
  88. }
  89. static struct sysrq_key_op sysrq_xmon_op =
  90. {
  91. .handler = sysrq_handle_xmon,
  92. .help_msg = "Xmon",
  93. .action_msg = "Entering xmon",
  94. };
  95. #endif
  96. void
  97. xmon_map_scc(void)
  98. {
  99. #ifdef CONFIG_PPC_MULTIPLATFORM
  100. volatile unsigned char *base;
  101. if (_machine == _MACH_Pmac) {
  102. struct device_node *np;
  103. unsigned long addr;
  104. #ifdef CONFIG_BOOTX_TEXT
  105. if (!use_screen && !use_serial
  106. && !machine_is_compatible("iMac")) {
  107. /* see if there is a keyboard in the device tree
  108. with a parent of type "adb" */
  109. for (np = find_devices("keyboard"); np; np = np->next)
  110. if (np->parent && np->parent->type
  111. && strcmp(np->parent->type, "adb") == 0)
  112. break;
  113. /* needs to be hacked if xmon_printk is to be used
  114. from within find_via_pmu() */
  115. #ifdef CONFIG_ADB_PMU
  116. if (np != NULL && boot_text_mapped && find_via_pmu())
  117. use_screen = 1;
  118. #endif
  119. #ifdef CONFIG_ADB_CUDA
  120. if (np != NULL && boot_text_mapped && find_via_cuda())
  121. use_screen = 1;
  122. #endif
  123. }
  124. if (!use_screen && (np = find_devices("escc")) != NULL) {
  125. /*
  126. * look for the device node for the serial port
  127. * we're using and see if it says it has a modem
  128. */
  129. char *name = xmon_use_sccb? "ch-b": "ch-a";
  130. char *slots;
  131. int l;
  132. np = np->child;
  133. while (np != NULL && strcmp(np->name, name) != 0)
  134. np = np->sibling;
  135. if (np != NULL) {
  136. /* XXX should parse this properly */
  137. channel_node = np;
  138. slots = get_property(np, "slot-names", &l);
  139. if (slots != NULL && l >= 10
  140. && strcmp(slots+4, "Modem") == 0)
  141. via_modem = 1;
  142. }
  143. }
  144. btext_drawstring("xmon uses ");
  145. if (use_screen)
  146. btext_drawstring("screen and keyboard\n");
  147. else {
  148. if (via_modem)
  149. btext_drawstring("modem on ");
  150. btext_drawstring(xmon_use_sccb? "printer": "modem");
  151. btext_drawstring(" port\n");
  152. }
  153. #endif /* CONFIG_BOOTX_TEXT */
  154. #ifdef CHRP_ESCC
  155. addr = 0xc1013020;
  156. #else
  157. addr = 0xf3013020;
  158. #endif
  159. TXRDY = 4;
  160. RXRDY = 1;
  161. np = find_devices("mac-io");
  162. if (np && np->n_addrs)
  163. addr = np->addrs[0].address + 0x13020;
  164. base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
  165. sccc = base + (addr & ~PAGE_MASK);
  166. sccd = sccc + 0x10;
  167. }
  168. #ifdef CONFIG_PPC_CHRP
  169. else {
  170. base = (volatile unsigned char *) isa_io_base;
  171. if (_machine == _MACH_chrp)
  172. base = (volatile unsigned char *)
  173. ioremap(chrp_find_phys_io_base(), 0x1000);
  174. sccc = base + 0x3fd;
  175. sccd = base + 0x3f8;
  176. if (xmon_use_sccb) {
  177. sccc -= 0x100;
  178. sccd -= 0x100;
  179. }
  180. TXRDY = 0x20;
  181. RXRDY = 1;
  182. DLAB = 0x80;
  183. }
  184. #endif /* CONFIG_PPC_CHRP */
  185. #elif defined(CONFIG_GEMINI)
  186. /* should already be mapped by the kernel boot */
  187. sccc = (volatile unsigned char *) 0xffeffb0d;
  188. sccd = (volatile unsigned char *) 0xffeffb08;
  189. TXRDY = 0x20;
  190. RXRDY = 1;
  191. DLAB = 0x80;
  192. #elif defined(CONFIG_405GP)
  193. sccc = (volatile unsigned char *)0xef600305;
  194. sccd = (volatile unsigned char *)0xef600300;
  195. TXRDY = 0x20;
  196. RXRDY = 1;
  197. DLAB = 0x80;
  198. #endif /* platform */
  199. register_sysrq_key('x', &sysrq_xmon_op);
  200. }
  201. static int scc_initialized = 0;
  202. void xmon_init_scc(void);
  203. extern void cuda_poll(void);
  204. static inline void do_poll_adb(void)
  205. {
  206. #ifdef CONFIG_ADB_PMU
  207. if (sys_ctrler == SYS_CTRLER_PMU)
  208. pmu_poll_adb();
  209. #endif /* CONFIG_ADB_PMU */
  210. #ifdef CONFIG_ADB_CUDA
  211. if (sys_ctrler == SYS_CTRLER_CUDA)
  212. cuda_poll();
  213. #endif /* CONFIG_ADB_CUDA */
  214. }
  215. int
  216. xmon_write(void *handle, void *ptr, int nb)
  217. {
  218. char *p = ptr;
  219. int i, c, ct;
  220. #ifdef CONFIG_SMP
  221. static unsigned long xmon_write_lock;
  222. int lock_wait = 1000000;
  223. int locked;
  224. while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
  225. if (--lock_wait == 0)
  226. break;
  227. #endif
  228. #ifdef CONFIG_BOOTX_TEXT
  229. if (use_screen) {
  230. /* write it on the screen */
  231. for (i = 0; i < nb; ++i)
  232. btext_drawchar(*p++);
  233. goto out;
  234. }
  235. #endif
  236. if (!scc_initialized)
  237. xmon_init_scc();
  238. ct = 0;
  239. for (i = 0; i < nb; ++i) {
  240. while ((*sccc & TXRDY) == 0)
  241. do_poll_adb();
  242. c = p[i];
  243. if (c == '\n' && !ct) {
  244. c = '\r';
  245. ct = 1;
  246. --i;
  247. } else {
  248. ct = 0;
  249. }
  250. buf_access();
  251. *sccd = c;
  252. eieio();
  253. }
  254. out:
  255. #ifdef CONFIG_SMP
  256. if (!locked)
  257. clear_bit(0, &xmon_write_lock);
  258. #endif
  259. return nb;
  260. }
  261. int xmon_wants_key;
  262. int xmon_adb_keycode;
  263. #ifdef CONFIG_BOOTX_TEXT
  264. static int xmon_adb_shiftstate;
  265. static unsigned char xmon_keytab[128] =
  266. "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
  267. "yt123465=97-80]o" /* 0x10 - 0x1f */
  268. "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
  269. "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
  270. "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
  271. "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
  272. static unsigned char xmon_shift_keytab[128] =
  273. "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
  274. "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
  275. "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
  276. "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
  277. "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
  278. "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
  279. static int
  280. xmon_get_adb_key(void)
  281. {
  282. int k, t, on;
  283. xmon_wants_key = 1;
  284. for (;;) {
  285. xmon_adb_keycode = -1;
  286. t = 0;
  287. on = 0;
  288. do {
  289. if (--t < 0) {
  290. on = 1 - on;
  291. btext_drawchar(on? 0xdb: 0x20);
  292. btext_drawchar('\b');
  293. t = 200000;
  294. }
  295. do_poll_adb();
  296. } while (xmon_adb_keycode == -1);
  297. k = xmon_adb_keycode;
  298. if (on)
  299. btext_drawstring(" \b");
  300. /* test for shift keys */
  301. if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
  302. xmon_adb_shiftstate = (k & 0x80) == 0;
  303. continue;
  304. }
  305. if (k >= 0x80)
  306. continue; /* ignore up transitions */
  307. k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
  308. if (k != 0)
  309. break;
  310. }
  311. xmon_wants_key = 0;
  312. return k;
  313. }
  314. #endif /* CONFIG_BOOTX_TEXT */
  315. int
  316. xmon_read(void *handle, void *ptr, int nb)
  317. {
  318. char *p = ptr;
  319. int i;
  320. #ifdef CONFIG_BOOTX_TEXT
  321. if (use_screen) {
  322. for (i = 0; i < nb; ++i)
  323. *p++ = xmon_get_adb_key();
  324. return i;
  325. }
  326. #endif
  327. if (!scc_initialized)
  328. xmon_init_scc();
  329. for (i = 0; i < nb; ++i) {
  330. while ((*sccc & RXRDY) == 0)
  331. do_poll_adb();
  332. buf_access();
  333. *p++ = *sccd;
  334. }
  335. return i;
  336. }
  337. int
  338. xmon_read_poll(void)
  339. {
  340. if ((*sccc & RXRDY) == 0) {
  341. do_poll_adb();
  342. return -1;
  343. }
  344. buf_access();
  345. return *sccd;
  346. }
  347. static unsigned char scc_inittab[] = {
  348. 13, 0, /* set baud rate divisor */
  349. 12, 1,
  350. 14, 1, /* baud rate gen enable, src=rtxc */
  351. 11, 0x50, /* clocks = br gen */
  352. 5, 0xea, /* tx 8 bits, assert DTR & RTS */
  353. 4, 0x46, /* x16 clock, 1 stop */
  354. 3, 0xc1, /* rx enable, 8 bits */
  355. };
  356. void
  357. xmon_init_scc(void)
  358. {
  359. if ( _machine == _MACH_chrp )
  360. {
  361. sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
  362. sccd[0] = 12; eieio(); /* DLL = 9600 baud */
  363. sccd[1] = 0; eieio();
  364. sccd[2] = 0; eieio(); /* FCR = 0 */
  365. sccd[3] = 3; eieio(); /* LCR = 8N1 */
  366. sccd[1] = 0; eieio(); /* IER = 0 */
  367. }
  368. else if ( _machine == _MACH_Pmac )
  369. {
  370. int i, x;
  371. if (channel_node != 0)
  372. pmac_call_feature(
  373. PMAC_FTR_SCC_ENABLE,
  374. channel_node,
  375. PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
  376. printk(KERN_INFO "Serial port locked ON by debugger !\n");
  377. if (via_modem && channel_node != 0) {
  378. unsigned int t0;
  379. pmac_call_feature(
  380. PMAC_FTR_MODEM_ENABLE,
  381. channel_node, 0, 1);
  382. printk(KERN_INFO "Modem powered up by debugger !\n");
  383. t0 = readtb();
  384. while (readtb() - t0 < 3*TB_SPEED)
  385. eieio();
  386. }
  387. /* use the B channel if requested */
  388. if (xmon_use_sccb) {
  389. sccc = (volatile unsigned char *)
  390. ((unsigned long)sccc & ~0x20);
  391. sccd = sccc + 0x10;
  392. }
  393. for (i = 20000; i != 0; --i) {
  394. x = *sccc; eieio();
  395. }
  396. *sccc = 9; eieio(); /* reset A or B side */
  397. *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
  398. for (i = 0; i < sizeof(scc_inittab); ++i) {
  399. *sccc = scc_inittab[i];
  400. eieio();
  401. }
  402. }
  403. scc_initialized = 1;
  404. if (via_modem) {
  405. for (;;) {
  406. xmon_write(NULL, "ATE1V1\r", 7);
  407. if (xmon_expect("OK", 5)) {
  408. xmon_write(NULL, "ATA\r", 4);
  409. if (xmon_expect("CONNECT", 40))
  410. break;
  411. }
  412. xmon_write(NULL, "+++", 3);
  413. xmon_expect("OK", 3);
  414. }
  415. }
  416. }
  417. #if 0
  418. extern int (*prom_entry)(void *);
  419. int
  420. xmon_exit(void)
  421. {
  422. struct prom_args {
  423. char *service;
  424. } args;
  425. for (;;) {
  426. args.service = "exit";
  427. (*prom_entry)(&args);
  428. }
  429. }
  430. #endif
  431. void *xmon_stdin;
  432. void *xmon_stdout;
  433. void *xmon_stderr;
  434. void
  435. xmon_init(int arg)
  436. {
  437. xmon_map_scc();
  438. }
  439. int
  440. xmon_putc(int c, void *f)
  441. {
  442. char ch = c;
  443. if (c == '\n')
  444. xmon_putc('\r', f);
  445. return xmon_write(f, &ch, 1) == 1? c: -1;
  446. }
  447. int
  448. xmon_putchar(int c)
  449. {
  450. return xmon_putc(c, xmon_stdout);
  451. }
  452. int
  453. xmon_fputs(char *str, void *f)
  454. {
  455. int n = strlen(str);
  456. return xmon_write(f, str, n) == n? 0: -1;
  457. }
  458. int
  459. xmon_readchar(void)
  460. {
  461. char ch;
  462. for (;;) {
  463. switch (xmon_read(xmon_stdin, &ch, 1)) {
  464. case 1:
  465. return ch;
  466. case -1:
  467. xmon_printf("read(stdin) returned -1\r\n", 0, 0);
  468. return -1;
  469. }
  470. }
  471. }
  472. static char line[256];
  473. static char *lineptr;
  474. static int lineleft;
  475. int xmon_expect(const char *str, unsigned int timeout)
  476. {
  477. int c;
  478. unsigned int t0;
  479. timeout *= TB_SPEED;
  480. t0 = readtb();
  481. do {
  482. lineptr = line;
  483. for (;;) {
  484. c = xmon_read_poll();
  485. if (c == -1) {
  486. if (readtb() - t0 > timeout)
  487. return 0;
  488. continue;
  489. }
  490. if (c == '\n')
  491. break;
  492. if (c != '\r' && lineptr < &line[sizeof(line) - 1])
  493. *lineptr++ = c;
  494. }
  495. *lineptr = 0;
  496. } while (strstr(line, str) == NULL);
  497. return 1;
  498. }
  499. int
  500. xmon_getchar(void)
  501. {
  502. int c;
  503. if (lineleft == 0) {
  504. lineptr = line;
  505. for (;;) {
  506. c = xmon_readchar();
  507. if (c == -1 || c == 4)
  508. break;
  509. if (c == '\r' || c == '\n') {
  510. *lineptr++ = '\n';
  511. xmon_putchar('\n');
  512. break;
  513. }
  514. switch (c) {
  515. case 0177:
  516. case '\b':
  517. if (lineptr > line) {
  518. xmon_putchar('\b');
  519. xmon_putchar(' ');
  520. xmon_putchar('\b');
  521. --lineptr;
  522. }
  523. break;
  524. case 'U' & 0x1F:
  525. while (lineptr > line) {
  526. xmon_putchar('\b');
  527. xmon_putchar(' ');
  528. xmon_putchar('\b');
  529. --lineptr;
  530. }
  531. break;
  532. default:
  533. if (lineptr >= &line[sizeof(line) - 1])
  534. xmon_putchar('\a');
  535. else {
  536. xmon_putchar(c);
  537. *lineptr++ = c;
  538. }
  539. }
  540. }
  541. lineleft = lineptr - line;
  542. lineptr = line;
  543. }
  544. if (lineleft == 0)
  545. return -1;
  546. --lineleft;
  547. return *lineptr++;
  548. }
  549. char *
  550. xmon_fgets(char *str, int nb, void *f)
  551. {
  552. char *p;
  553. int c;
  554. for (p = str; p < str + nb - 1; ) {
  555. c = xmon_getchar();
  556. if (c == -1) {
  557. if (p == str)
  558. return NULL;
  559. break;
  560. }
  561. *p++ = c;
  562. if (c == '\n')
  563. break;
  564. }
  565. *p = 0;
  566. return str;
  567. }
  568. void
  569. xmon_enter(void)
  570. {
  571. #ifdef CONFIG_ADB_PMU
  572. if (_machine == _MACH_Pmac) {
  573. pmu_suspend();
  574. }
  575. #endif
  576. }
  577. void
  578. xmon_leave(void)
  579. {
  580. #ifdef CONFIG_ADB_PMU
  581. if (_machine == _MACH_Pmac) {
  582. pmu_resume();
  583. }
  584. #endif
  585. }