source: mainline/uspace/lib/fb/screenbuffer.c@ fbcdeb8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fbcdeb8 was fbcdeb8, checked in by Martin Decky <martin@…>, 14 years ago

Remove the two-phase way of creating virtual memory areas (first asking for a mappable address and then mapping it) which was prone to race conditions when two or more calls to as_get_mappable_page() and as_area_create() were interleaved. This for example caused the e1k driver to randomly fail.

The memory area related syscalls and IPC calls have all been altered to accept a special value (void *) -1, representing a demand to atomically search for a mappable address space "hole" and map to it.

Individual changes:

  • IPC_M_SHARE_OUT: the destination address space area is supplied by the kernel, the callee only specifies the lower bound

(the address is returned to the callee via a pointer in an IPC reply argument)

  • IPC_M_SHARE_IN: the destination address space ares is supplied by the kernel, the callee only specifies the lower bound

(the address is returned to the caller as usual via an IPC argument)

  • SYS_AS_GET_UNMAPPED_AREA was removed
  • dummy implementations of SYS_PHYSMEM_UNMAP and SYS_IOSPACE_DISABLE were added for the sake of symmetry (they do nothing yet)
  • SYS_PHYSMEM_MAP and SYS_DMAMEM_MAP were altered to accept (void *) -1 as address space area base and a lower bound
  • kernel as_area_create() and as_area_share() were altered to accept (void *) -1 as address space area base and a lower bound
  • uspace libraries and programs were altered to reflect the new API
  • Property mode set to 100644
File size: 9.7 KB
Line 
1/*
2 * Copyright (c) 2006 Josef Cejka
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup console
30 * @{
31 */
32/** @file
33 */
34
35#include <io/style.h>
36#include <malloc.h>
37#include <unistd.h>
38#include <assert.h>
39#include <bool.h>
40#include <as.h>
41#include "screenbuffer.h"
42
43/** Structure for buffering state of one virtual console.
44 *
45 */
46struct screenbuffer {
47 size_t size; /**< Structure size */
48 screenbuffer_flag_t flags; /**< Screenbuffer flags */
49
50 sysarg_t cols; /**< Number of columns */
51 sysarg_t rows; /**< Number of rows */
52
53 sysarg_t col; /**< Current column */
54 sysarg_t row; /**< Current row */
55 bool cursor_visible; /**< Cursor visibility */
56
57 char_attrs_t attrs; /**< Current attributes */
58
59 sysarg_t top_row; /**< The first row in the cyclic buffer */
60 charfield_t data[]; /**< Screen contents (cyclic buffer) */
61};
62
63/** Create a screenbuffer.
64 *
65 * @param[in] cols Number of columns.
66 * @param[in] rows Number of rows.
67 * @param[in] flags Screenbuffer flags.
68 *
69 * @return New screenbuffer.
70 * @return NULL on failure.
71 *
72 */
73screenbuffer_t *screenbuffer_create(sysarg_t cols, sysarg_t rows,
74 screenbuffer_flag_t flags)
75{
76 size_t size =
77 sizeof(screenbuffer_t) + cols * rows * sizeof(charfield_t);
78 screenbuffer_t *scrbuf;
79
80 if ((flags & SCREENBUFFER_FLAG_SHARED) == SCREENBUFFER_FLAG_SHARED) {
81 scrbuf = (screenbuffer_t *) as_area_create((void *) -1, size,
82 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
83 if (scrbuf == (void *) -1)
84 return NULL;
85 } else {
86 scrbuf = (screenbuffer_t *) malloc(size);
87 if (scrbuf == NULL)
88 return NULL;
89 }
90
91 scrbuf->size = size;
92 scrbuf->flags = flags;
93 scrbuf->cols = cols;
94 scrbuf->rows = rows;
95 scrbuf->cursor_visible = false;
96
97 scrbuf->attrs.type = CHAR_ATTR_STYLE;
98 scrbuf->attrs.val.style = STYLE_NORMAL;
99
100 scrbuf->top_row = 0;
101 screenbuffer_clear(scrbuf);
102
103 return scrbuf;
104}
105
106/** Return keyfield by coordinates
107 *
108 * The back buffer is organized as a cyclic buffer.
109 * Therefore we must take into account the topmost column.
110 *
111 * @param scrbuf Screenbuffer
112 * @param col Column position on screen
113 * @param row Row position on screen
114 *
115 * @return Keyfield structure on (row, col)
116 *
117 */
118charfield_t *screenbuffer_field_at(screenbuffer_t *scrbuf, sysarg_t col,
119 sysarg_t row)
120{
121 return scrbuf->data +
122 ((row + scrbuf->top_row) % scrbuf->rows) * scrbuf->cols +
123 col;
124}
125
126bool screenbuffer_cursor_at(screenbuffer_t *scrbuf, sysarg_t col, sysarg_t row)
127{
128 return ((scrbuf->cursor_visible) && (scrbuf->col == col) &&
129 (scrbuf->row == row));
130}
131
132sysarg_t screenbuffer_get_top_row(screenbuffer_t *scrbuf)
133{
134 return scrbuf->top_row;
135}
136
137static sysarg_t screenbuffer_update_rows(screenbuffer_t *scrbuf)
138{
139 if (scrbuf->row == scrbuf->rows) {
140 scrbuf->row = scrbuf->rows - 1;
141 scrbuf->top_row = (scrbuf->top_row + 1) % scrbuf->rows;
142 screenbuffer_clear_row(scrbuf, scrbuf->row);
143
144 return scrbuf->rows;
145 }
146
147 return 2;
148}
149
150static sysarg_t screenbuffer_update_cols(screenbuffer_t *scrbuf)
151{
152 /* Column overflow */
153 if (scrbuf->col == scrbuf->cols) {
154 scrbuf->col = 0;
155 scrbuf->row++;
156 return screenbuffer_update_rows(scrbuf);
157 }
158
159 return 1;
160}
161
162/** Store one character to screenbuffer.
163 *
164 * Its position is determined by scrbuf->col
165 * and scrbuf->row.
166 *
167 * @param scrbuf Screenbuffer.
168 * @param ch Character to store.
169 * @param update Update coordinates.
170 *
171 * @return Number of rows which have been affected. In usual
172 * situations this is 1. If the current position was
173 * updated to a new row, this value is 2.
174 *
175 */
176sysarg_t screenbuffer_putchar(screenbuffer_t *scrbuf, wchar_t ch, bool update)
177{
178 assert(scrbuf->col < scrbuf->cols);
179 assert(scrbuf->row < scrbuf->rows);
180
181 charfield_t *field =
182 screenbuffer_field_at(scrbuf, scrbuf->col, scrbuf->row);
183
184 field->ch = ch;
185 field->attrs = scrbuf->attrs;
186 field->flags |= CHAR_FLAG_DIRTY;
187
188 if (update) {
189 scrbuf->col++;
190 return screenbuffer_update_cols(scrbuf);
191 }
192
193 return 1;
194}
195
196/** Jump to a new row in screenbuffer.
197 *
198 * @param scrbuf Screenbuffer.
199 *
200 * @return Number of rows which have been affected. In usual
201 * situations this is 2 (the original row and the new
202 * row).
203 *
204 */
205sysarg_t screenbuffer_newline(screenbuffer_t *scrbuf)
206{
207 assert(scrbuf->col < scrbuf->cols);
208 assert(scrbuf->row < scrbuf->rows);
209
210 scrbuf->col = 0;
211 scrbuf->row++;
212
213 return screenbuffer_update_rows(scrbuf);
214}
215
216/** Jump to a new row in screenbuffer.
217 *
218 * @param scrbuf Screenbuffer.
219 * @param tab_size Tab size.
220 *
221 * @return Number of rows which have been affected. In usual
222 * situations this is 1. If the current position was
223 * updated to a new row, this value is 2.
224 *
225 */
226sysarg_t screenbuffer_tabstop(screenbuffer_t *scrbuf, sysarg_t tab_size)
227{
228 assert(scrbuf->col < scrbuf->cols);
229 assert(scrbuf->row < scrbuf->rows);
230
231 sysarg_t spaces = tab_size - scrbuf->cols % tab_size;
232 sysarg_t flush = 1;
233
234 for (sysarg_t i = 0; i < spaces; i++)
235 flush += screenbuffer_putchar(scrbuf, ' ', true) - 1;
236
237 return flush;
238}
239
240/** Jump to the previous character in screenbuffer.
241 *
242 * Currently no scrollback is supported.
243 *
244 * @param scrbuf Screenbuffer.
245 *
246 * @return Number of rows which have been affected. In usual
247 * situations this is 1. If the current position was
248 * updated to the previous row, this value is 2.
249 * @return 0 if no backspace is possible.
250 *
251 */
252sysarg_t screenbuffer_backspace(screenbuffer_t *scrbuf)
253{
254 assert(scrbuf->col < scrbuf->cols);
255 assert(scrbuf->row < scrbuf->rows);
256
257 if ((scrbuf->col == 0) && (scrbuf->row == 0))
258 return 0;
259
260 if (scrbuf->col == 0) {
261 scrbuf->col = scrbuf->cols - 1;
262 scrbuf->row--;
263
264 screenbuffer_putchar(scrbuf, ' ', false);
265 return 2;
266 }
267
268 scrbuf->col--;
269 screenbuffer_putchar(scrbuf, ' ', false);
270 return 1;
271}
272
273/** Clear the screenbuffer.
274 *
275 * @param scrbuf Screenbuffer.
276 *
277 */
278void screenbuffer_clear(screenbuffer_t *scrbuf)
279{
280 for (size_t pos = 0; pos < (scrbuf->cols * scrbuf->rows); pos++) {
281 scrbuf->data[pos].ch = 0;
282 scrbuf->data[pos].attrs = scrbuf->attrs;
283 scrbuf->data[pos].flags = CHAR_FLAG_DIRTY;
284 }
285
286 scrbuf->col = 0;
287 scrbuf->row = 0;
288}
289
290/** Update current screenbuffer coordinates
291 *
292 * @param scrbuf Screenbuffer.
293 * @param col New column.
294 * @param row New row.
295 *
296 */
297void screenbuffer_set_cursor(screenbuffer_t *scrbuf, sysarg_t col, sysarg_t row)
298{
299 scrbuf->col = col;
300 scrbuf->row = row;
301}
302
303void screenbuffer_set_cursor_visibility(screenbuffer_t *scrbuf, bool visible)
304{
305 scrbuf->cursor_visible = visible;
306}
307
308/** Get current screenbuffer coordinates
309 *
310 * @param scrbuf Screenbuffer.
311 * @param col Column.
312 * @param row Row.
313 *
314 */
315void screenbuffer_get_cursor(screenbuffer_t *scrbuf, sysarg_t *col,
316 sysarg_t *row)
317{
318 assert(col);
319 assert(row);
320
321 *col = scrbuf->col;
322 *row = scrbuf->row;
323}
324
325bool screenbuffer_get_cursor_visibility(screenbuffer_t *scrbuf)
326{
327 return scrbuf->cursor_visible;
328}
329
330/** Clear one buffer row.
331 *
332 * @param scrbuf Screenbuffer.
333 * @param row Row to clear.
334 *
335 */
336void screenbuffer_clear_row(screenbuffer_t *scrbuf, sysarg_t row)
337{
338 for (sysarg_t col = 0; col < scrbuf->cols; col++) {
339 charfield_t *field =
340 screenbuffer_field_at(scrbuf, col, row);
341
342 field->ch = 0;
343 field->attrs = scrbuf->attrs;
344 field->flags |= CHAR_FLAG_DIRTY;
345 }
346}
347
348/** Set screenbuffer style.
349 *
350 * @param scrbuf Screenbuffer.
351 * @param style Style.
352 *
353 */
354void screenbuffer_set_style(screenbuffer_t *scrbuf, console_style_t style)
355{
356 scrbuf->attrs.type = CHAR_ATTR_STYLE;
357 scrbuf->attrs.val.style = style;
358}
359
360/** Set screenbuffer color.
361 *
362 * @param scrbuf Screenbuffer.
363 * @param bgcolor Background color.
364 * @param fgcolor Foreground color.
365 * @param attr Color attribute.
366 *
367 */
368void screenbuffer_set_color(screenbuffer_t *scrbuf, console_color_t bgcolor,
369 console_color_t fgcolor, console_color_attr_t attr)
370{
371 scrbuf->attrs.type = CHAR_ATTR_INDEX;
372 scrbuf->attrs.val.index.bgcolor = bgcolor;
373 scrbuf->attrs.val.index.fgcolor = fgcolor;
374 scrbuf->attrs.val.index.attr = attr;
375}
376
377/** Set screenbuffer RGB color.
378 *
379 * @param scrbuf Screenbuffer.
380 * @param bgcolor Background color.
381 * @param fgcolor Foreground color.
382 *
383 */
384void screenbuffer_set_rgb_color(screenbuffer_t *scrbuf, pixel_t bgcolor,
385 pixel_t fgcolor)
386{
387 scrbuf->attrs.type = CHAR_ATTR_RGB;
388 scrbuf->attrs.val.rgb.bgcolor = bgcolor;
389 scrbuf->attrs.val.rgb.fgcolor = fgcolor;
390}
391
392/** @}
393 */
Note: See TracBrowser for help on using the repository browser.