cirbuf.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1992,1991,1990 Carnegie Mellon University
  4. * All Rights Reserved.
  5. *
  6. * Permission to use, copy, modify and distribute this software and its
  7. * documentation is hereby granted, provided that both the copyright
  8. * notice and this permission notice appear in all copies of the
  9. * software, derivative works or modified versions, and any portions
  10. * thereof, and that both notices appear in supporting documentation.
  11. *
  12. * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13. * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15. *
  16. * Carnegie Mellon requests users of this software to return to
  17. *
  18. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  19. * School of Computer Science
  20. * Carnegie Mellon University
  21. * Pittsburgh PA 15213-3890
  22. *
  23. * any improvements or extensions that they make and grant Carnegie Mellon
  24. * the rights to redistribute these changes.
  25. */
  26. /*
  27. * Author: David B. Golub, Carnegie Mellon University
  28. * Date: 7/90
  29. *
  30. * Circular buffers for TTY
  31. */
  32. #include <string.h>
  33. #include <device/cirbuf.h>
  34. #include <kern/debug.h>
  35. #include <kern/kalloc.h>
  36. /* read at c_cf, write at c_cl */
  37. /* if c_cf == c_cl, buffer is empty */
  38. /* if c_cl == c_cf - 1, buffer is full */
  39. #if DEBUG
  40. #include <mach/boolean.h>
  41. boolean_t cb_check_enable = FALSE;
  42. #define CB_CHECK(cb) if (cb_check_enable) cb_check(cb)
  43. void
  44. cb_check(struct cirbuf *cb)
  45. {
  46. if (!(cb->c_cf >= cb->c_start && cb->c_cf < cb->c_end))
  47. panic("cf %x out of range [%x..%x)",
  48. cb->c_cf, cb->c_start, cb->c_end);
  49. if (!(cb->c_cl >= cb->c_start && cb->c_cl < cb->c_end))
  50. panic("cl %x out of range [%x..%x)",
  51. cb->c_cl, cb->c_start, cb->c_end);
  52. if (cb->c_cf <= cb->c_cl) {
  53. if (!(cb->c_cc == cb->c_cl - cb->c_cf))
  54. panic("cc %x should be %x",
  55. cb->c_cc,
  56. cb->c_cl - cb->c_cf);
  57. }
  58. else {
  59. if (!(cb->c_cc == cb->c_end - cb->c_cf
  60. + cb->c_cl - cb->c_start))
  61. panic("cc %x should be %x",
  62. cb->c_cc,
  63. cb->c_end - cb->c_cf +
  64. cb->c_cl - cb->c_start);
  65. }
  66. }
  67. #else /* DEBUG */
  68. #define CB_CHECK(cb)
  69. #endif /* DEBUG */
  70. /*
  71. * Put one character in circular buffer.
  72. */
  73. int putc(
  74. int c,
  75. struct cirbuf *cb)
  76. {
  77. char *ow, *nw;
  78. ow = cb->c_cl;
  79. nw = ow+1;
  80. if (nw == cb->c_end)
  81. nw = cb->c_start;
  82. if (nw == cb->c_cf)
  83. return 1; /* not entered */
  84. *ow = c;
  85. cb->c_cl = nw;
  86. cb->c_cc++;
  87. CB_CHECK(cb);
  88. return 0;
  89. }
  90. /*
  91. * Get one character from circular buffer.
  92. */
  93. int getc(struct cirbuf *cb)
  94. {
  95. unsigned char *nr;
  96. int c;
  97. nr = (unsigned char *)cb->c_cf;
  98. if (nr == (unsigned char *)cb->c_cl) {
  99. CB_CHECK(cb);
  100. return -1; /* empty */
  101. }
  102. c = *nr;
  103. nr++;
  104. if (nr == (unsigned char *)cb->c_end)
  105. nr = (unsigned char *)cb->c_start;
  106. cb->c_cf = (char *)nr;
  107. cb->c_cc--;
  108. CB_CHECK(cb);
  109. return c;
  110. }
  111. /*
  112. * Get lots of characters.
  113. * Return number moved.
  114. */
  115. int
  116. q_to_b( struct cirbuf *cb,
  117. char *cp,
  118. int count)
  119. {
  120. char *ocp = cp;
  121. int i;
  122. while (count != 0) {
  123. if (cb->c_cl == cb->c_cf)
  124. break; /* empty */
  125. if (cb->c_cl < cb->c_cf)
  126. i = cb->c_end - cb->c_cf;
  127. else
  128. i = cb->c_cl - cb->c_cf;
  129. if (i > count)
  130. i = count;
  131. memcpy(cp, cb->c_cf, i);
  132. cp += i;
  133. count -= i;
  134. cb->c_cf += i;
  135. cb->c_cc -= i;
  136. if (cb->c_cf == cb->c_end)
  137. cb->c_cf = cb->c_start;
  138. CB_CHECK(cb);
  139. }
  140. CB_CHECK(cb);
  141. return cp - ocp;
  142. }
  143. /*
  144. * Add character array to buffer and return number of characters
  145. * NOT entered.
  146. */
  147. int
  148. b_to_q( char *cp,
  149. int count,
  150. struct cirbuf *cb)
  151. {
  152. int i;
  153. char *lim;
  154. while (count != 0) {
  155. lim = cb->c_cf - 1;
  156. if (lim < cb->c_start)
  157. lim = cb->c_end - 1;
  158. if (cb->c_cl == lim)
  159. break;
  160. if (cb->c_cl < lim)
  161. i = lim - cb->c_cl;
  162. else
  163. i = cb->c_end - cb->c_cl;
  164. if (i > count)
  165. i = count;
  166. memcpy(cb->c_cl, cp, i);
  167. cp += i;
  168. count -= i;
  169. cb->c_cc += i;
  170. cb->c_cl += i;
  171. if (cb->c_cl == cb->c_end)
  172. cb->c_cl = cb->c_start;
  173. CB_CHECK(cb);
  174. }
  175. CB_CHECK(cb);
  176. return count;
  177. }
  178. /*
  179. * Return number of contiguous characters up to a character
  180. * that matches the mask.
  181. */
  182. int
  183. ndqb( struct cirbuf *cb,
  184. int mask)
  185. {
  186. char *cp, *lim;
  187. if (cb->c_cl < cb->c_cf)
  188. lim = cb->c_end;
  189. else
  190. lim = cb->c_cl;
  191. if (mask == 0)
  192. return (lim - cb->c_cf);
  193. cp = cb->c_cf;
  194. while (cp < lim) {
  195. if (*cp & mask)
  196. break;
  197. cp++;
  198. }
  199. return (cp - cb->c_cf);
  200. }
  201. /*
  202. * Flush characters from circular buffer.
  203. */
  204. void
  205. ndflush(struct cirbuf *cb,
  206. int count)
  207. {
  208. int i;
  209. while (count != 0) {
  210. if (cb->c_cl == cb->c_cf)
  211. break; /* empty */
  212. if (cb->c_cl < cb->c_cf)
  213. i = cb->c_end - cb->c_cf;
  214. else
  215. i = cb->c_cl - cb->c_cf;
  216. if (i > count)
  217. i = count;
  218. count -= i;
  219. cb->c_cf += i;
  220. cb->c_cc -= i;
  221. if (cb->c_cf == cb->c_end)
  222. cb->c_cf = cb->c_start;
  223. CB_CHECK(cb);
  224. }
  225. CB_CHECK(cb);
  226. }
  227. /*
  228. * Empty a circular buffer.
  229. */
  230. void cb_clear(struct cirbuf *cb)
  231. {
  232. cb->c_cf = cb->c_start;
  233. cb->c_cl = cb->c_start;
  234. cb->c_cc = 0;
  235. }
  236. /*
  237. * Allocate character space for a circular buffer.
  238. */
  239. void
  240. cb_alloc(
  241. struct cirbuf *cb,
  242. vm_size_t buf_size)
  243. {
  244. char *buf;
  245. buf = (char *)kalloc(buf_size);
  246. cb->c_start = buf;
  247. cb->c_end = buf + buf_size;
  248. cb->c_cf = buf;
  249. cb->c_cl = buf;
  250. cb->c_cc = 0;
  251. cb->c_hog = buf_size - 1;
  252. CB_CHECK(cb);
  253. }
  254. /*
  255. * Free character space for a circular buffer.
  256. */
  257. void
  258. cb_free(struct cirbuf *cb)
  259. {
  260. vm_size_t size;
  261. size = cb->c_end - cb->c_start;
  262. kfree((vm_offset_t)cb->c_start, size);
  263. }