Changeset dc033a1 in mainline for uspace/srv/console/console.c
- Timestamp:
- 2009-03-22T17:45:15Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade
- Children:
- 3fe00ee
- Parents:
- 0a5116db
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/console/console.c
r0a5116db rdc033a1 63 63 int prev_console = 0; 64 64 65 /** Information about framebuffer 66 */ 65 /** Information about framebuffer */ 67 66 struct { 68 67 int phone; /**< Framebuffer phone */ … … 90 89 * faster virtual console 91 90 * switching */ 92 /** Size of fb_buf. */ 93 #define FB_BUF_SIZE 256 94 95 /** Buffer for sending characters to FB driver. */ 96 static char fb_buf[FB_BUF_SIZE]; 97 98 /* Properties of fb_buf data. */ 99 static int fb_buf_row; /**< Row where fb_buf data belong. */ 100 static int fb_buf_col; /**< Column where fb_buf data start. */ 101 static int fb_console; /**< VC to which fb_buf data belong. */ 102 int fb_bi = 0; /**< Number of valid chars in fb_buf. */ 91 92 /** Information on row-span yet unsent to FB driver. */ 93 struct { 94 int row; /**< Row where the span lies. */ 95 int col; /**< Leftmost column of the span. */ 96 int n; /**< Width of the span. */ 97 } fb_pending; 103 98 104 99 /** Size of cwrite_buf. */ … … 107 102 /** Buffer for receiving data via the CONSOLE_WRITE call from the client. */ 108 103 static char cwrite_buf[CWRITE_BUF_SIZE]; 104 105 static void fb_putchar(char c, int row, int col); 109 106 110 107 … … 176 173 } 177 174 178 /** Write a character vector to FB driver via IPC. */ 179 static ssize_t fb_write(const char *buf, size_t nbyte, int row, int col) 180 { 181 ipcarg_t rc; 182 ipc_call_t answer; 183 aid_t req; 184 185 async_serialize_start(); 186 187 req = async_send_2(fb_info.phone, FB_WRITE, row, col, &answer); 188 rc = ipc_data_write_start(fb_info.phone, (void *) buf, nbyte); 189 190 if (rc != EOK) { 191 async_wait_for(req, NULL); 192 async_serialize_end(); 193 return (ssize_t) rc; 194 } 195 196 async_wait_for(req, &rc); 197 async_serialize_end(); 198 199 if (rc == EOK) 200 return (ssize_t) IPC_GET_ARG1(answer); 201 else 202 return -1; 203 } 204 205 /** Flush buffered characters to FB. */ 206 static void fb_buf_flush(void) 175 /** Send an area of screenbuffer to the FB driver. */ 176 static void fb_update_area(connection_t *conn, int x, int y, int w, int h) 177 { 178 int i, j; 179 int rc; 180 attrs_t *attrs; 181 keyfield_t *field; 182 183 if (interbuffer) { 184 for (j = 0; j < h; j++) { 185 for (i = 0; i < w; i++) { 186 interbuffer[i + j * w] = 187 *get_field_at(&conn->screenbuffer, 188 x + i, y + j); 189 } 190 } 191 192 rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, 193 x, y, w, h); 194 } else { 195 rc = ENOTSUP; 196 } 197 198 if (rc != 0) { 199 attrs = &conn->screenbuffer.attrs; 200 201 for (j = 0; j < h; j++) { 202 for (i = 0; i < w; i++) { 203 field = get_field_at(&conn->screenbuffer, 204 x + i, y + j); 205 if (!attrs_same(*attrs, field->attrs)) 206 set_attrs(&field->attrs); 207 attrs = &field->attrs; 208 209 fb_putchar(field->character, y + j, x + i); 210 } 211 } 212 } 213 } 214 215 /** Flush pending cells to FB. */ 216 static void fb_pending_flush(void) 207 217 { 208 218 screenbuffer_t *scr; 209 int i; 210 211 scr = &(connections[fb_console].screenbuffer); 212 213 if (fb_bi > 0) { 214 if (fb_write(fb_buf, fb_bi, fb_buf_row, fb_buf_col) < 0) { 215 /* Try falling back to char-by-char. */ 216 for (i = 0; i < fb_bi; i++) { 217 async_msg_3(fb_info.phone, FB_PUTCHAR, fb_buf[i], 218 fb_buf_row, fb_buf_col + i); 219 } 220 } 221 fb_bi = 0; 222 } 223 } 219 220 scr = &(connections[active_console].screenbuffer); 221 222 if (fb_pending.n > 0) { 223 fb_update_area(&connections[active_console], fb_pending.col, 224 fb_pending.row, fb_pending.n, 1); 225 fb_pending.n = 0; 226 } 227 } 228 229 /** Mark a character cell as changed. 230 * 231 * This adds the cell to the pending rowspan if possible. Otherwise 232 * the old span is flushed first. 233 */ 234 static void cell_mark_changed(int row, int col) 235 { 236 if (fb_pending.n != 0) { 237 if (row != fb_pending.row || 238 col != fb_pending.col + fb_pending.n) { 239 fb_pending_flush(); 240 } 241 } 242 243 if (fb_pending.n == 0) { 244 fb_pending.row = row; 245 fb_pending.col = col; 246 } 247 248 ++fb_pending.n; 249 } 250 224 251 225 252 /** Print a character to the active VC with buffering. */ 226 static void prtchr(char c, int row, int col) 227 { 228 if (fb_bi >= FB_BUF_SIZE) 229 fb_buf_flush(); 230 231 if (fb_bi == 0) { 232 fb_buf_row = row; 233 fb_buf_col = col; 234 fb_console = active_console; 235 } 236 237 fb_buf[fb_bi++] = c; 238 } 239 240 /** Check key and process special keys. 241 * 242 * 243 */ 253 static void fb_putchar(char c, int row, int col) 254 { 255 async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col); 256 } 257 258 /** Process a character from the client (TTY emulation). */ 244 259 static void write_char(int console, char key) 245 260 { … … 249 264 switch (key) { 250 265 case '\n': 251 fb_ buf_flush();266 fb_pending_flush(); 252 267 flush_cursor = true; 253 268 scr->position_y++; … … 255 270 break; 256 271 case '\r': 257 fb_buf_flush();258 272 break; 259 273 case '\t': 260 fb_buf_flush();261 274 scr->position_x += 8; 262 275 scr->position_x -= scr->position_x % 8; 263 276 break; 264 277 case '\b': 265 fb_buf_flush();266 278 if (scr->position_x == 0) 267 279 break; 268 280 scr->position_x--; 269 281 if (console == active_console) 270 prtchr(' ',scr->position_y, scr->position_x);282 cell_mark_changed(scr->position_y, scr->position_x); 271 283 screenbuffer_putchar(scr, ' '); 272 284 break; 273 285 default: 274 286 if (console == active_console) 275 prtchr(key,scr->position_y, scr->position_x);287 cell_mark_changed(scr->position_y, scr->position_x); 276 288 277 289 screenbuffer_putchar(scr, key); … … 280 292 281 293 if (scr->position_x >= scr->size_x) { 282 fb_buf_flush();283 294 flush_cursor = true; 284 295 scr->position_y++; … … 286 297 287 298 if (scr->position_y >= scr->size_y) { 299 fb_pending_flush(); 288 300 scr->position_y = scr->size_y - 1; 289 301 screenbuffer_clear_line(scr, scr->top_line); … … 310 322 return; 311 323 312 fb_ buf_flush();324 fb_pending_flush(); 313 325 314 326 if (newcons == KERNEL_CONSOLE) { … … 338 350 curs_visibility(false); 339 351 if (interbuffer) { 340 for ( i = 0; i < conn->screenbuffer.size_x; i++)341 for ( j = 0; j < conn->screenbuffer.size_y; j++) {352 for (j = 0; j < conn->screenbuffer.size_y; j++) { 353 for (i = 0; i < conn->screenbuffer.size_x; i++) { 342 354 unsigned int size_x; 343 355 344 356 size_x = conn->screenbuffer.size_x; 345 interbuffer[ i + j * size_x] =357 interbuffer[j * size_x + i] = 346 358 *get_field_at(&conn->screenbuffer, i, j); 347 359 } 360 } 348 361 /* This call can preempt, but we are already at the end */ 349 rc = async_req_0_0(fb_info.phone, FB_DRAW_TEXT_DATA); 362 rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, 363 0, 0, conn->screenbuffer.size_x, 364 conn->screenbuffer.size_y); 350 365 } 351 366 … … 366 381 continue; 367 382 368 prtchr(field->character, j, i);383 fb_putchar(field->character, j, i); 369 384 } 370 385 } … … 479 494 ipcarg_t arg1, arg2, arg3, arg4; 480 495 connection_t *conn; 496 screenbuffer_t *scr; 481 497 482 498 if ((consnum = find_free_connection()) == -1) { … … 535 551 break; 536 552 case CONSOLE_GOTO: 537 fb_buf_flush();538 553 screenbuffer_goto(&conn->screenbuffer, 539 554 IPC_GET_ARG2(call), IPC_GET_ARG1(call)); … … 547 562 break; 548 563 case CONSOLE_FLUSH: 549 fb_ buf_flush();550 if (consnum == active_console) 564 fb_pending_flush(); 565 if (consnum == active_console) { 551 566 async_req_0_0(fb_info.phone, FB_FLUSH); 567 568 scr = &(connections[consnum].screenbuffer); 569 curs_goto(scr->position_y, scr->position_x); 570 } 552 571 break; 553 572 case CONSOLE_SET_STYLE: 554 fb_ buf_flush();573 fb_pending_flush(); 555 574 arg1 = IPC_GET_ARG1(call); 556 575 screenbuffer_set_style(&conn->screenbuffer, arg1); … … 559 578 break; 560 579 case CONSOLE_SET_COLOR: 561 fb_ buf_flush();580 fb_pending_flush(); 562 581 arg1 = IPC_GET_ARG1(call); 563 582 arg2 = IPC_GET_ARG2(call); … … 569 588 break; 570 589 case CONSOLE_SET_RGB_COLOR: 571 fb_ buf_flush();590 fb_pending_flush(); 572 591 arg1 = IPC_GET_ARG1(call); 573 592 arg2 = IPC_GET_ARG2(call); … … 578 597 break; 579 598 case CONSOLE_CURSOR_VISIBILITY: 580 fb_ buf_flush();599 fb_pending_flush(); 581 600 arg1 = IPC_GET_ARG1(call); 582 601 conn->screenbuffer.is_cursor_visible = arg1; … … 684 703 interbuffer = as_get_mappable_page(ib_size); 685 704 705 fb_pending.n = 0; 706 686 707 if (as_area_create(interbuffer, ib_size, AS_AREA_READ | 687 708 AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) {
Note:
See TracChangeset
for help on using the changeset viewer.