start.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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