cons.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright (c) 1988-1994, The University of Utah and
  3. * the Computer Systems Laboratory (CSL). All rights reserved.
  4. *
  5. * Permission to use, copy, modify and distribute this software is hereby
  6. * granted provided that (1) source code retains these copyright, permission,
  7. * and disclaimer notices, and (2) redistributions including binaries
  8. * reproduce the notices in supporting documentation, and (3) all advertising
  9. * materials mentioning features or use of this software display the following
  10. * acknowledgement: ``This product includes software developed by the
  11. * Computer Systems Laboratory at the University of Utah.''
  12. *
  13. * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
  14. * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
  15. * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  16. *
  17. * CSL requests users of this software to return to csl-dist@cs.utah.edu any
  18. * improvements that they make and grant CSL redistribution rights.
  19. *
  20. * Utah $Hdr: cons.c 1.14 94/12/14$
  21. */
  22. #include <string.h>
  23. #include <kern/debug.h>
  24. #include <sys/types.h>
  25. #include <device/conf.h>
  26. #include <mach/boolean.h>
  27. #include <device/cons.h>
  28. #ifdef MACH_KMSG
  29. #include <device/io_req.h>
  30. #include <device/kmsg.h>
  31. #endif /* MACH_KMSG */
  32. static boolean_t cn_inited = FALSE;
  33. static struct consdev *cn_tab = 0; /* physical console device info */
  34. /*
  35. * ROM getc/putc primitives.
  36. * On some architectures, the boot ROM provides basic character input/output
  37. * routines that can be used before devices are configured or virtual memory
  38. * is enabled. This can be useful to debug (or catch panics from) code early
  39. * in the bootstrap procedure.
  40. */
  41. int (*romgetc)(char c) = 0;
  42. void (*romputc)(char c) = 0;
  43. #if CONSBUFSIZE > 0
  44. /*
  45. * Temporary buffer to store console output before a console is selected.
  46. * This is statically allocated so it can be called before malloc/kmem_alloc
  47. * have been initialized. It is initialized so it won't be clobbered as
  48. * part of the zeroing of BSS (on PA/Mach).
  49. */
  50. static char consbuf[CONSBUFSIZE] = { 0 };
  51. static char *consbp = consbuf;
  52. static boolean_t consbufused = FALSE;
  53. #endif /* CONSBUFSIZE > 0 */
  54. void
  55. cninit(void)
  56. {
  57. struct consdev *cp;
  58. dev_ops_t cn_ops;
  59. int x;
  60. if (cn_inited)
  61. return;
  62. /*
  63. * Collect information about all possible consoles
  64. * and find the one with highest priority
  65. */
  66. for (cp = constab; cp->cn_probe; cp++) {
  67. (*cp->cn_probe)(cp);
  68. if (cp->cn_pri > CN_DEAD &&
  69. (cn_tab == NULL || cp->cn_pri > cn_tab->cn_pri))
  70. cn_tab = cp;
  71. }
  72. /*
  73. * Found a console, initialize it.
  74. */
  75. if ((cp = cn_tab)) {
  76. /*
  77. * Initialize as console
  78. */
  79. (*cp->cn_init)(cp);
  80. /*
  81. * Look up its dev_ops pointer in the device table and
  82. * place it in the device indirection table.
  83. */
  84. if (dev_name_lookup(cp->cn_name, &cn_ops, &x) == FALSE)
  85. panic("cninit: dev_name_lookup failed");
  86. dev_set_indirection("console", cn_ops, minor(cp->cn_dev));
  87. #if CONSBUFSIZE > 0
  88. /*
  89. * Now that the console is initialized, dump any chars in
  90. * the temporary console buffer.
  91. */
  92. if (consbufused) {
  93. char *cbp = consbp;
  94. do {
  95. if (*cbp)
  96. cnputc(*cbp);
  97. if (++cbp == &consbuf[CONSBUFSIZE])
  98. cbp = consbuf;
  99. } while (cbp != consbp);
  100. consbufused = FALSE;
  101. }
  102. #endif /* CONSBUFSIZE > 0 */
  103. cn_inited = TRUE;
  104. return;
  105. }
  106. /*
  107. * No console device found, not a problem for BSD, fatal for Mach
  108. */
  109. panic("can't find a console device");
  110. }
  111. int
  112. cngetc(void)
  113. {
  114. if (cn_tab)
  115. return ((*cn_tab->cn_getc)(cn_tab->cn_dev, 1));
  116. if (romgetc)
  117. return ((*romgetc)(1));
  118. return (0);
  119. }
  120. int
  121. cnmaygetc(void)
  122. {
  123. if (cn_tab)
  124. return((*cn_tab->cn_getc)(cn_tab->cn_dev, 0));
  125. if (romgetc)
  126. return ((*romgetc)(0));
  127. return (0);
  128. }
  129. void
  130. cnputc(c)
  131. char c;
  132. {
  133. if (c == 0)
  134. return;
  135. #ifdef MACH_KMSG
  136. /* XXX: Assume that All output routines always use cnputc. */
  137. kmsg_putchar (c);
  138. #endif
  139. #if defined(MACH_HYP) && 0
  140. {
  141. /* Also output on hypervisor's emergency console, for
  142. * debugging */
  143. unsigned char d = c;
  144. hyp_console_write(&d, 1);
  145. }
  146. #endif /* MACH_HYP */
  147. if (cn_tab) {
  148. (*cn_tab->cn_putc)(cn_tab->cn_dev, c);
  149. if (c == '\n')
  150. (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r');
  151. } else if (romputc) {
  152. (*romputc)(c);
  153. if (c == '\n')
  154. (*romputc)('\r');
  155. }
  156. #if CONSBUFSIZE > 0
  157. else {
  158. if (consbufused == FALSE) {
  159. consbp = consbuf;
  160. consbufused = TRUE;
  161. memset(consbuf, 0, CONSBUFSIZE);
  162. }
  163. *consbp++ = c;
  164. if (consbp >= &consbuf[CONSBUFSIZE])
  165. consbp = consbuf;
  166. }
  167. #endif /* CONSBUFSIZE > 0 */
  168. }