cons.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include <alloca.h>
  2. #include <linux/kernel.h>
  3. #include <asm/console.h>
  4. #include "hwrpb.h"
  5. #include "system.h"
  6. #include "aboot.h"
  7. #include "cons.h"
  8. #include "utils.h"
  9. #include "string.h"
  10. #ifndef CCB_OPEN_CONSOLE /* new callback w/ ARM v4 */
  11. # define CCB_OPEN_CONSOLE 0x07
  12. #endif
  13. #ifndef CCB_CLOSE_CONSOLE /* new callback w/ ARM v4 */
  14. # define CCB_CLOSE_CONSOLE 0x08
  15. #endif
  16. long cons_dev; /* console device */
  17. long
  18. cons_puts(const char *str, long len)
  19. {
  20. long remaining, written;
  21. union ccb_stsdef {
  22. long int l_sts;
  23. struct {
  24. int written;
  25. unsigned discard : 29;
  26. unsigned v_sts0 : 1;
  27. unsigned v_sts1 : 1;
  28. unsigned v_err : 1;
  29. } s;
  30. } ccb_sts;
  31. for (remaining = len; remaining; remaining -= written) {
  32. ccb_sts.l_sts = dispatch(CCB_PUTS, cons_dev, str, remaining);
  33. if (!ccb_sts.s.v_err) {
  34. written = ccb_sts.s.written;
  35. str += written;
  36. } else {
  37. if (ccb_sts.s.v_sts1)
  38. halt(); /* This is a hard error */
  39. written = 0;
  40. }
  41. }
  42. return len;
  43. }
  44. void
  45. cons_putchar(char c)
  46. {
  47. char buf[2];
  48. buf[0] = c;
  49. buf[1] = 0;
  50. cons_puts(buf,1);
  51. }
  52. int
  53. cons_getchar(void)
  54. {
  55. long c;
  56. while ((c = dispatch(CCB_GETC, cons_dev)) < 0)
  57. ;
  58. return c;
  59. }
  60. long
  61. cons_getenv(long index, char *envval, long maxlen)
  62. {
  63. /*
  64. * This may seem silly, but some SRM implementations have
  65. * problems returning values to buffers that are not 8 byte
  66. * aligned. We work around this by always using a buffer
  67. * allocated on the stack (which guaranteed to by 8 byte
  68. * aligned).
  69. */
  70. char * tmp = alloca(maxlen);
  71. long len;
  72. len = dispatch(CCB_GET_ENV, index, tmp, maxlen - 1);
  73. if (len >= 0) {
  74. memcpy(envval, tmp, len);
  75. envval[len] = '\0';
  76. }
  77. return len;
  78. }
  79. long
  80. cons_open(const char *devname)
  81. {
  82. return dispatch(CCB_OPEN, devname, strlen(devname));
  83. }
  84. long
  85. cons_close(long dev)
  86. {
  87. return dispatch(CCB_CLOSE, dev);
  88. }
  89. long
  90. cons_read(long dev, void *buf, long count, long offset)
  91. {
  92. static char readbuf[SECT_SIZE]; /* minimize frame size */
  93. if ((count & (SECT_SIZE-1)) == 0 && (offset & (SECT_SIZE-1)) == 0) {
  94. /* I/O is aligned... this is easy! */
  95. return dispatch(CCB_READ, dev, count, buf,
  96. offset / SECT_SIZE);
  97. } else {
  98. long bytesleft, iocount, blockoffset, iosize, lbn, retval;
  99. bytesleft = count;
  100. iocount = 0;
  101. blockoffset = offset % SECT_SIZE;
  102. lbn = offset / SECT_SIZE;
  103. while (bytesleft > 0) {
  104. if ((blockoffset == 0) && (bytesleft >= SECT_SIZE)) {
  105. /*
  106. * This portion of the I/O is aligned,
  107. * so read it straight in:
  108. */
  109. iosize = SECT_SIZE;
  110. retval = dispatch(CCB_READ, dev, iosize, buf,
  111. lbn);
  112. if (retval != iosize) {
  113. printf("read error 0x%lx\n",retval);
  114. return -1;
  115. }
  116. } else {
  117. /*
  118. * Not aligned; must read it into a
  119. * temporary buffer and go from there.
  120. */
  121. retval = dispatch(CCB_READ, dev, SECT_SIZE,
  122. readbuf, lbn);
  123. if (retval != SECT_SIZE) {
  124. printf("read error, lbn %ld: 0x%lx\n",
  125. lbn, retval);
  126. return -1;
  127. }
  128. iosize = bytesleft;
  129. if (blockoffset + iosize >= SECT_SIZE) {
  130. iosize = SECT_SIZE - blockoffset;
  131. }
  132. memcpy(buf, readbuf + blockoffset, iosize);
  133. }
  134. buf += iosize;
  135. iocount += iosize;
  136. bytesleft -= iosize;
  137. blockoffset = 0;
  138. ++lbn;
  139. }
  140. return iocount;
  141. }
  142. }
  143. void cons_open_console(void)
  144. {
  145. dispatch(CCB_OPEN_CONSOLE);
  146. }
  147. void cons_close_console(void)
  148. {
  149. dispatch(CCB_CLOSE_CONSOLE);
  150. }
  151. void
  152. cons_init(void)
  153. {
  154. char envval[256];
  155. if (cons_getenv(ENV_TTY_DEV, envval, sizeof(envval)) < 0) {
  156. halt(); /* better than random crash */
  157. }
  158. cons_dev = simple_strtoul(envval, 0, 10);
  159. cons_open_console();
  160. }