Changes in / [61c91532:a65ccc4] in mainline
- Files:
-
- 1 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
abi/include/abi/syscall.h
r61c91532 ra65ccc4 110 110 SYS_DEBUG_CONSOLE, 111 111 112 SYS_KLOG, 113 SYS_KIO_READ, 112 SYS_KLOG 114 113 } syscall_t; 115 114 -
kernel/genarch/src/drivers/ega/ega.c
r61c91532 ra65ccc4 69 69 uint8_t *backbuf; 70 70 ioport8_t *base; 71 mbstate_t mbstate;72 71 } ega_instance_t; 73 72 74 static void ega_ write(outdev_t *, const char *, size_t);73 static void ega_putuchar(outdev_t *, char32_t); 75 74 static void ega_redraw(outdev_t *); 76 75 77 76 static outdev_operations_t egadev_ops = { 78 .write = ega_ write,77 .write = ega_putuchar, 79 78 .redraw = ega_redraw, 80 79 .scroll_up = NULL, … … 539 538 } 540 539 541 static void _putuchar(ega_instance_t *instance, char32_t ch) 542 { 540 static void ega_putuchar(outdev_t *dev, char32_t ch) 541 { 542 ega_instance_t *instance = (ega_instance_t *) dev->data; 543 544 irq_spinlock_lock(&instance->lock, true); 545 543 546 switch (ch) { 544 547 case '\n': … … 561 564 ega_check_cursor(instance); 562 565 ega_move_cursor(instance); 563 }564 565 static void ega_write(outdev_t *dev, const char *s, size_t n)566 {567 ega_instance_t *instance = (ega_instance_t *) dev->data;568 569 irq_spinlock_lock(&instance->lock, true);570 571 size_t offset = 0;572 char32_t ch;573 574 while ((ch = str_decode_r(s, &offset, n, U_SPECIAL, &instance->mbstate)))575 _putuchar(instance, ch);576 566 577 567 irq_spinlock_unlock(&instance->lock, true); -
kernel/genarch/src/drivers/ns16550/ns16550.c
r61c91532 ra65ccc4 112 112 } 113 113 114 static void ns16550_ write(outdev_t *dev, const char *s, size_t n)114 static void ns16550_putuchar(outdev_t *dev, char32_t ch) 115 115 { 116 116 ns16550_instance_t *instance = (ns16550_instance_t *) dev->data; 117 117 118 if (instance->parea.mapped && !console_override) 119 return; 120 121 const char *top = s + n; 122 assert(top >= s); 123 124 for (; s < top; s++) { 125 if (*s == '\n') 118 if ((!instance->parea.mapped) || (console_override)) { 119 if (ch == '\n') 126 120 ns16550_sendb(instance, '\r'); 127 121 128 ns16550_sendb(instance, (uint8_t) *s); 122 if (ascii_check(ch)) 123 ns16550_sendb(instance, (uint8_t) ch); 124 else 125 ns16550_sendb(instance, U_SPECIAL); 129 126 } 130 127 } 131 128 132 129 static outdev_operations_t ns16550_ops = { 133 .write = ns16550_ write,130 .write = ns16550_putuchar, 134 131 .redraw = NULL 135 132 }; -
kernel/genarch/src/drivers/pl011/pl011.c
r61c91532 ra65ccc4 56 56 } 57 57 58 static void pl011_uart_ write(outdev_t *dev, const char *s, size_t n)58 static void pl011_uart_putuchar(outdev_t *dev, char32_t ch) 59 59 { 60 60 pl011_uart_t *uart = dev->data; … … 64 64 return; 65 65 66 const char *top = s + n; 67 assert(top >= s); 68 69 for (; s < top; s++) { 70 if (*s == '\n') 71 pl011_uart_sendb(uart, '\r'); 72 73 pl011_uart_sendb(uart, (uint8_t) *s); 66 if (!ascii_check(ch)) 67 pl011_uart_sendb(uart, U_SPECIAL); 68 else { 69 if (ch == '\n') 70 pl011_uart_sendb(uart, (uint8_t) '\r'); 71 pl011_uart_sendb(uart, (uint8_t) ch); 74 72 } 75 73 } 76 74 77 75 static outdev_operations_t pl011_uart_ops = { 78 .write = pl011_uart_ write,76 .write = pl011_uart_putuchar, 79 77 .redraw = NULL, 80 78 .scroll_up = NULL, -
kernel/genarch/src/fb/fb.c
r61c91532 ra65ccc4 81 81 ((glyph) * (instance)->glyphbytes + (y) * (instance)->glyphscanline) 82 82 83 #define TAB_WIDTH 884 85 83 typedef void (*rgb_conv_t)(void *, uint32_t); 86 84 … … 101 99 102 100 /** Number of rows that fit on framebuffer */ 103 unsigned int screen_rows;101 unsigned int rowtrim; 104 102 105 103 unsigned int scanline; … … 123 121 /** Current backbuffer position */ 124 122 unsigned int position; 125 126 /** Partial character between writes */127 mbstate_t mbstate;128 129 unsigned int row;130 unsigned int column;131 123 } fb_instance_t; 132 124 133 static void fb_ write(outdev_t *, const char *, size_t);125 static void fb_putuchar(outdev_t *, char32_t); 134 126 static void fb_redraw(outdev_t *); 135 127 static void fb_scroll_up(outdev_t *); … … 137 129 138 130 static outdev_operations_t fbdev_ops = { 139 .write = fb_ write,131 .write = fb_putuchar, 140 132 .redraw = fb_redraw, 141 133 .scroll_up = fb_scroll_up, … … 255 247 256 248 unsigned int rel_row = row - instance->offset_row; 257 if (rel_row >= instance-> screen_rows)249 if (rel_row >= instance->rowtrim) 258 250 return; 259 251 … … 267 259 } 268 260 261 /** Scroll screen down by one row 262 * 263 */ 264 static void screen_scroll(fb_instance_t *instance) 265 { 266 if ((!instance->parea.mapped) || (console_override)) { 267 for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) { 268 unsigned int y = ROW2Y(rel_row); 269 unsigned int row = rel_row + instance->offset_row; 270 271 for (unsigned int yd = 0; yd < FONT_SCANLINES; yd++) { 272 unsigned int x; 273 unsigned int col; 274 size_t bb_pos = BB_POS(instance, 0, row); 275 size_t bb_pos1 = BB_POS(instance, 0, row + 1); 276 277 for (col = 0, x = 0; col < instance->cols; 278 col++, x += FONT_WIDTH) { 279 uint16_t glyph; 280 281 if (row < instance->rows - 1) { 282 if (instance->backbuf[bb_pos] == 283 instance->backbuf[bb_pos1]) 284 goto skip; 285 286 glyph = instance->backbuf[bb_pos1]; 287 } else 288 glyph = 0; 289 290 memcpy(&instance->addr[FB_POS(instance, x, y + yd)], 291 &instance->glyphs[GLYPH_POS(instance, glyph, yd)], 292 instance->glyphscanline); 293 skip: 294 BB_NEXT_COL(bb_pos); 295 BB_NEXT_COL(bb_pos1); 296 } 297 } 298 } 299 } 300 301 /* 302 * Implement backbuffer scrolling by wrapping around 303 * the cyclic buffer. 304 */ 305 306 instance->start_row++; 307 if (instance->start_row == instance->rows) 308 instance->start_row = 0; 309 310 memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)], 311 instance->cols, 0); 312 } 313 269 314 static void cursor_put(fb_instance_t *instance) 270 315 { 271 unsigned int col = instance-> column;272 unsigned int row = instance-> row;316 unsigned int col = instance->position % instance->cols; 317 unsigned int row = instance->position / instance->cols; 273 318 274 319 glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, true); … … 277 322 static void cursor_remove(fb_instance_t *instance) 278 323 { 279 unsigned int col = instance-> column;280 unsigned int row = instance-> row;324 unsigned int col = instance->position % instance->cols; 325 unsigned int row = instance->position / instance->cols; 281 326 282 327 glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)], … … 328 373 static void fb_redraw_internal(fb_instance_t *instance) 329 374 { 330 for (unsigned int rel_row = 0; rel_row < instance-> screen_rows; rel_row++) {375 for (unsigned int rel_row = 0; rel_row < instance->rowtrim; rel_row++) { 331 376 unsigned int y = ROW2Y(rel_row); 332 377 unsigned int row = rel_row + instance->offset_row; … … 359 404 } 360 405 361 if (ROW2Y(instance-> screen_rows) < instance->yres) {406 if (ROW2Y(instance->rowtrim) < instance->yres) { 362 407 unsigned int y; 363 408 364 for (y = ROW2Y(instance-> screen_rows); y < instance->yres; y++)409 for (y = ROW2Y(instance->rowtrim); y < instance->yres; y++) 365 410 memcpy(&instance->addr[FB_POS(instance, 0, y)], 366 411 instance->bgscan, instance->bgscanbytes); … … 368 413 } 369 414 370 /** Scroll screen down by one row371 *372 */373 static void screen_scroll(fb_instance_t *instance)374 {375 /*376 * Implement backbuffer scrolling by wrapping around377 * the cyclic buffer.378 */379 380 instance->start_row++;381 if (instance->start_row == instance->rows)382 instance->start_row = 0;383 384 if ((!instance->parea.mapped) || (console_override)) {385 fb_redraw_internal(instance);386 }387 }388 389 static void _advance_row(fb_instance_t *instance)390 {391 instance->column = 0;392 instance->row++;393 }394 395 static void _advance_column(fb_instance_t *instance)396 {397 instance->column++;398 if (instance->column == instance->cols)399 _advance_row(instance);400 }401 402 415 /** Print character to screen 403 416 * … … 405 418 * 406 419 */ 407 static void _putuchar(fb_instance_t *instance, char32_t ch) 408 { 420 static void fb_putuchar(outdev_t *dev, char32_t ch) 421 { 422 fb_instance_t *instance = (fb_instance_t *) dev->data; 423 spinlock_lock(&instance->lock); 424 409 425 switch (ch) { 410 426 case '\n': 411 _advance_row(instance); 427 cursor_remove(instance); 428 instance->position += instance->cols; 429 instance->position -= instance->position % instance->cols; 412 430 break; 413 431 case '\r': 414 instance->column = 0; 432 cursor_remove(instance); 433 instance->position -= instance->position % instance->cols; 415 434 break; 416 435 case '\b': 417 if (instance->column > 0) 418 instance->column--; 436 cursor_remove(instance); 437 if (instance->position % instance->cols) 438 instance->position--; 419 439 break; 420 440 case '\t': 441 cursor_remove(instance); 421 442 do { 422 443 glyph_draw(instance, fb_font_glyph(' '), 423 instance->column, 424 instance->row, false); 425 _advance_column(instance); 426 } while (instance->column % TAB_WIDTH != 0); 444 instance->position % instance->cols, 445 instance->position / instance->cols, false); 446 instance->position++; 447 } while (((instance->position % instance->cols) % 8 != 0) && 448 (instance->position < instance->cols * instance->rows)); 427 449 break; 428 450 default: 429 451 glyph_draw(instance, fb_font_glyph(ch), 430 instance-> column,431 instance-> row, false);432 _advance_column(instance);433 } 434 435 while (instance->row >=instance->rows) {436 instance-> row--;452 instance->position % instance->cols, 453 instance->position / instance->cols, false); 454 instance->position++; 455 } 456 457 if (instance->position >= instance->cols * instance->rows) { 458 instance->position -= instance->cols; 437 459 screen_scroll(instance); 438 460 } 439 }440 441 static void fb_write(outdev_t *dev, const char *s, size_t n)442 {443 fb_instance_t *instance = (fb_instance_t *) dev->data;444 445 spinlock_lock(&instance->lock);446 cursor_remove(instance);447 448 size_t offset = 0;449 char32_t ch;450 451 while ((ch = str_decode_r(s, &offset, n, U_SPECIAL, &instance->mbstate)))452 _putuchar(instance, ch);453 461 454 462 cursor_put(instance); 463 455 464 spinlock_unlock(&instance->lock); 456 465 } … … 464 473 spinlock_lock(&instance->lock); 465 474 466 if (instance->offset_row >= instance-> screen_rows/ 2)467 instance->offset_row -= instance-> screen_rows/ 2;475 if (instance->offset_row >= instance->rowtrim / 2) 476 instance->offset_row -= instance->rowtrim / 2; 468 477 else 469 478 instance->offset_row = 0; … … 483 492 spinlock_lock(&instance->lock); 484 493 485 if (instance->offset_row + instance-> screen_rows/ 2 <=486 instance->rows - instance-> screen_rows)487 instance->offset_row += instance-> screen_rows/ 2;494 if (instance->offset_row + instance->rowtrim / 2 <= 495 instance->rows - instance->rowtrim) 496 instance->offset_row += instance->rowtrim / 2; 488 497 else 489 instance->offset_row = instance->rows - instance-> screen_rows;498 instance->offset_row = instance->rows - instance->rowtrim; 490 499 491 500 fb_redraw_internal(instance); … … 606 615 instance->scanline = props->scan; 607 616 608 instance-> screen_rows= Y2ROW(instance->yres);617 instance->rowtrim = Y2ROW(instance->yres); 609 618 610 619 instance->cols = X2COL(instance->xres); 611 instance->rows = FB_PAGES * instance-> screen_rows;612 613 instance->start_row = instance->rows - instance-> screen_rows;620 instance->rows = FB_PAGES * instance->rowtrim; 621 622 instance->start_row = instance->rows - instance->rowtrim; 614 623 instance->offset_row = instance->start_row; 615 instance->row = instance->start_row; 616 instance->column = 0; 624 instance->position = instance->start_row * instance->cols; 617 625 618 626 instance->glyphscanline = FONT_WIDTH * instance->pixelbytes; -
kernel/generic/include/console/chardev.h
r61c91532 ra65ccc4 81 81 /** Output character device operations interface. */ 82 82 typedef struct { 83 /** Write stringto output. */84 void (*write)(struct outdev *, c onst char *, size_t);83 /** Write character to output. */ 84 void (*write)(struct outdev *, char32_t); 85 85 86 86 /** Redraw any previously cached characters. */ -
kernel/generic/include/console/console.h
r61c91532 ra65ccc4 36 36 #define KERN_CONSOLE_H_ 37 37 38 #include <typedefs.h> 39 #include <print.h> 38 40 #include <console/chardev.h> 39 41 #include <synch/spinlock.h> … … 64 66 extern void kio_update(void *); 65 67 extern void kio_flush(void); 66 extern void kio_push_ bytes(const char *, size_t);67 extern irq_spinlock_t kio_lock;68 extern void kio_push_char(const char32_t); 69 SPINLOCK_EXTERN(kio_lock); 68 70 69 extern sysarg_t sys_kio_read(uspace_addr_t buf, size_t size, size_t at);70 71 extern sys_errno_t sys_kio(int cmd, uspace_addr_t buf, size_t size); 71 72 … … 78 79 extern void console_unlock(void); 79 80 80 extern void putstr(const char *s, size_t n);81 82 81 #endif /* KERN_CONSOLE_H_ */ 83 82 -
kernel/generic/include/stdio.h
r61c91532 ra65ccc4 37 37 38 38 #include <print.h> 39 #include <putchar.h> 39 40 40 41 #endif -
kernel/generic/src/console/console.c
r61c91532 ra65ccc4 2 2 * Copyright (c) 2003 Josef Cejka 3 3 * Copyright (c) 2005 Jakub Jermar 4 * Copyright (c) 2025 Jiří Zárevúcky5 4 * All rights reserved. 6 5 * … … 36 35 37 36 #include <abi/kio.h> 37 #include <arch.h> 38 #include <assert.h> 39 #include <atomic.h> 38 40 #include <console/chardev.h> 39 41 #include <console/console.h> 42 #include <ddi/ddi.h> 43 #include <ddi/irq.h> 40 44 #include <errno.h> 41 45 #include <ipc/event.h> 42 #include <log.h> 46 #include <ipc/irq.h> 47 #include <mm/frame.h> /* SIZE2FRAMES */ 43 48 #include <panic.h> 44 49 #include <preemption.h> 45 #include <proc/task.h> 50 #include <proc/thread.h> 51 #include <putchar.h> 46 52 #include <stdatomic.h> 47 53 #include <stdio.h> … … 50 56 #include <synch/mutex.h> 51 57 #include <synch/spinlock.h> 58 #include <synch/waitq.h> 52 59 #include <syscall/copy.h> 53 60 #include <sysinfo/sysinfo.h> 61 #include <typedefs.h> 54 62 55 63 #define KIO_PAGES 8 56 #define KIO_LENGTH (KIO_PAGES * PAGE_SIZE )64 #define KIO_LENGTH (KIO_PAGES * PAGE_SIZE / sizeof(char32_t)) 57 65 58 66 /** Kernel log cyclic buffer */ 59 static char kio[KIO_LENGTH];67 char32_t kio[KIO_LENGTH] __attribute__((aligned(PAGE_SIZE))); 60 68 61 69 /** Kernel log initialized */ … … 68 76 static MUTEX_INITIALIZE(console_mutex, MUTEX_RECURSIVE); 69 77 70 /** Number of characters written to buffer. Periodically overflows. */ 71 static size_t kio_written = 0; 72 73 /** Number of characters written to output devices. Periodically overflows. */ 74 static size_t kio_processed = 0; 75 76 /** Last notification sent to uspace. */ 77 static size_t kio_notified = 0; 78 /** First kernel log characters */ 79 static size_t kio_start = 0; 80 81 /** Number of valid kernel log characters */ 82 static size_t kio_len = 0; 83 84 /** Number of stored (not printed) kernel log characters */ 85 static size_t kio_stored = 0; 86 87 /** Number of stored kernel log characters for uspace */ 88 static size_t kio_uspace = 0; 78 89 79 90 /** Kernel log spinlock */ 80 IRQ_SPINLOCK_INITIALIZE(kio_lock); 81 82 static IRQ_SPINLOCK_INITIALIZE(flush_lock); 83 84 static IRQ_SPINLOCK_INITIALIZE(early_mbstate_lock); 85 static mbstate_t early_mbstate; 91 SPINLOCK_INITIALIZE_NAME(kio_lock, "kio_lock"); 92 93 /** Physical memory area used for kio buffer */ 94 static parea_t kio_parea; 86 95 87 96 static indev_t stdin_sink; … … 95 104 }; 96 105 97 static void stdout_write(outdev_t *, c onst char *, size_t);106 static void stdout_write(outdev_t *, char32_t); 98 107 static void stdout_redraw(outdev_t *); 99 108 static void stdout_scroll_up(outdev_t *); … … 148 157 } 149 158 150 static void stdout_write(outdev_t *dev, c onst char *s, size_t n)159 static void stdout_write(outdev_t *dev, char32_t ch) 151 160 { 152 161 list_foreach(dev->list, link, outdev_t, sink) { 153 162 if ((sink) && (sink->op->write)) 154 sink->op->write(sink, s, n);163 sink->op->write(sink, ch); 155 164 } 156 165 } … … 181 190 182 191 /** Initialize kernel logging facility 192 * 193 * The shared area contains kernel cyclic buffer. Userspace application may 194 * be notified on new data with indication of position and size 195 * of the data within the circular buffer. 196 * 183 197 */ 184 198 void kio_init(void) 185 199 { 200 void *faddr = (void *) KA2PA(kio); 201 202 assert((uintptr_t) faddr % FRAME_SIZE == 0); 203 204 ddi_parea_init(&kio_parea); 205 kio_parea.pbase = (uintptr_t) faddr; 206 kio_parea.frames = SIZE2FRAMES(sizeof(kio)); 207 kio_parea.unpriv = false; 208 kio_parea.mapped = false; 209 ddi_parea_register(&kio_parea); 210 211 sysinfo_set_item_val("kio.faddr", NULL, (sysarg_t) faddr); 212 sysinfo_set_item_val("kio.pages", NULL, KIO_PAGES); 213 186 214 event_set_unmask_callback(EVENT_KIO, kio_update); 187 215 atomic_store(&kio_inited, true); … … 229 257 return; 230 258 231 irq_spinlock_lock(&kio_lock, true); 232 233 if (kio_notified != kio_written) { 234 if (event_notify_1(EVENT_KIO, true, kio_written) == EOK) 235 kio_notified = kio_written; 236 } 237 238 irq_spinlock_unlock(&kio_lock, true); 259 spinlock_lock(&kio_lock); 260 261 if (kio_uspace > 0) { 262 if (event_notify_3(EVENT_KIO, true, kio_start, kio_len, 263 kio_uspace) == EOK) 264 kio_uspace = 0; 265 } 266 267 spinlock_unlock(&kio_lock); 239 268 } 240 269 … … 249 278 return; 250 279 251 irq_spinlock_lock(&kio_lock, true); 252 253 if (!irq_spinlock_trylock(&flush_lock)) { 254 /* Someone is currently flushing. */ 255 irq_spinlock_unlock(&kio_lock, true); 256 return; 257 } 258 259 /* A small-ish local buffer so that we can write to output in chunks. */ 260 char buffer[256]; 280 spinlock_lock(&kio_lock); 261 281 262 282 /* Print characters that weren't printed earlier */ 263 while (kio_written != kio_processed) { 264 size_t offset = kio_processed % KIO_LENGTH; 265 size_t len = min(kio_written - kio_processed, KIO_LENGTH - offset); 266 len = min(len, sizeof(buffer)); 267 268 /* Take out a chunk of the big buffer. */ 269 memcpy(buffer, &kio[offset], len); 270 kio_processed += len; 283 while (kio_stored > 0) { 284 char32_t tmp = kio[(kio_start + kio_len - kio_stored) % KIO_LENGTH]; 285 kio_stored--; 271 286 272 287 /* 273 * We need to give up the spinlock for the physical operation of writing 274 * out the buffer. 288 * We need to give up the spinlock for 289 * the physical operation of writing out 290 * the character. 275 291 */ 276 irq_spinlock_unlock(&kio_lock, true); 277 stdout->op->write(stdout, buffer, len); 278 irq_spinlock_lock(&kio_lock, true); 279 } 280 281 irq_spinlock_unlock(&flush_lock, false); 282 irq_spinlock_unlock(&kio_lock, true); 283 } 284 285 void kio_push_bytes(const char *s, size_t n) 286 { 287 /* Skip the section we know we can't keep. */ 288 if (n > KIO_LENGTH) { 289 size_t lost = n - KIO_LENGTH; 290 kio_written += lost; 291 s += lost; 292 n -= lost; 293 } 294 295 size_t offset = kio_written % KIO_LENGTH; 296 if (offset + n > KIO_LENGTH) { 297 size_t first = KIO_LENGTH - offset; 298 size_t last = n - first; 299 memcpy(kio + offset, s, first); 300 memcpy(kio, s + first, last); 301 } else { 302 memcpy(kio + offset, s, n); 303 } 304 305 kio_written += n; 306 } 307 308 static void early_putstr(const char *s, size_t n) 309 { 310 irq_spinlock_lock(&early_mbstate_lock, true); 311 312 size_t offset = 0; 313 char32_t c; 314 315 while ((c = str_decode_r(s, &offset, n, U_SPECIAL, &early_mbstate))) 316 early_putuchar(c); 317 318 irq_spinlock_unlock(&early_mbstate_lock, true); 319 } 320 321 void putstr(const char *s, size_t n) 292 spinlock_unlock(&kio_lock); 293 stdout->op->write(stdout, tmp); 294 spinlock_lock(&kio_lock); 295 } 296 297 spinlock_unlock(&kio_lock); 298 } 299 300 /** Put a character into the output buffer. 301 * 302 * The caller is required to hold kio_lock 303 */ 304 void kio_push_char(const char32_t ch) 305 { 306 kio[(kio_start + kio_len) % KIO_LENGTH] = ch; 307 if (kio_len < KIO_LENGTH) 308 kio_len++; 309 else 310 kio_start = (kio_start + 1) % KIO_LENGTH; 311 312 if (kio_stored < kio_len) 313 kio_stored++; 314 315 /* The character is stored for uspace */ 316 if (kio_uspace < kio_len) 317 kio_uspace++; 318 } 319 320 void putuchar(const char32_t ch) 322 321 { 323 322 bool ordy = ((stdout) && (stdout->op->write)); 324 323 325 irq_spinlock_lock(&kio_lock, true);326 kio_push_ bytes(s, n);327 irq_spinlock_unlock(&kio_lock, true);324 spinlock_lock(&kio_lock); 325 kio_push_char(ch); 326 spinlock_unlock(&kio_lock); 328 327 329 328 /* Output stored characters */ … … 341 340 * a no-op on certain hardware configurations. 342 341 */ 343 early_put str(s, n);344 } 345 346 /* Force notification when containing anewline */347 if ( memchr(s, '\n', n) != NULL)342 early_putuchar(ch); 343 } 344 345 /* Force notification on newline */ 346 if (ch == '\n') 348 347 kio_update(NULL); 349 }350 351 /** Reads up to `size` characters from kio buffer starting at character `at`.352 *353 * @param size Maximum number of characters that can be stored in buffer.354 * Values greater than KIO_LENGTH are silently treated as KIO_LENGTH355 * for the purposes of calculating the return value.356 * @return Number of characters read. Can be more than `size`.357 * In that case, `size` characters are written to user buffer358 * and the extra amount is the number of characters missed.359 */360 sysarg_t sys_kio_read(uspace_addr_t buf, size_t size, size_t at)361 {362 errno_t rc;363 size_t missed = 0;364 365 irq_spinlock_lock(&kio_lock, true);366 367 if (at == kio_written) {368 irq_spinlock_unlock(&kio_lock, true);369 return 0;370 }371 372 size_t readable_chars = kio_written - at;373 if (readable_chars > KIO_LENGTH) {374 missed = readable_chars - KIO_LENGTH;375 readable_chars = KIO_LENGTH;376 }377 378 size_t actual_read = min(readable_chars, size);379 size_t offset = (kio_written - readable_chars) % KIO_LENGTH;380 381 if (offset + actual_read > KIO_LENGTH) {382 size_t first = KIO_LENGTH - offset;383 size_t last = actual_read - first;384 385 rc = copy_to_uspace(buf, &kio[offset], first);386 if (rc == EOK)387 rc = copy_to_uspace(buf + first, &kio[0], last);388 } else {389 rc = copy_to_uspace(buf, &kio[offset], actual_read);390 }391 392 irq_spinlock_unlock(&kio_lock, true);393 394 if (rc != EOK) {395 log(LF_OTHER, LVL_WARN,396 "[%s(%" PRIu64 ")] Terminating due to invalid memory buffer"397 " in SYS_KIO_READ.\n", TASK->name, TASK->taskid);398 task_kill_self(true);399 }400 401 return actual_read + missed;402 348 } 403 349 -
kernel/generic/src/console/kconsole.c
r61c91532 ra65ccc4 39 39 */ 40 40 41 #include <assert.h> 42 #include <console/kconsole.h> 43 #include <console/console.h> 44 #include <console/chardev.h> 45 #include <console/cmd.h> 46 #include <console/prompt.h> 47 #include <stdio.h> 48 #include <panic.h> 49 #include <typedefs.h> 41 50 #include <adt/list.h> 42 51 #include <arch.h> 43 #include <assert.h> 44 #include <console/chardev.h> 45 #include <console/cmd.h> 46 #include <console/console.h> 47 #include <console/kconsole.h> 48 #include <console/prompt.h> 52 #include <macros.h> 49 53 #include <debug.h> 54 #include <halt.h> 55 #include <str.h> 56 #include <sysinfo/sysinfo.h> 57 #include <symtab.h> 50 58 #include <errno.h> 51 #include <halt.h> 52 #include <macros.h> 53 #include <panic.h> 54 #include <stdio.h> 59 #include <putchar.h> 55 60 #include <stdlib.h> 56 #include <str.h>57 #include <symtab.h>58 #include <sysinfo/sysinfo.h>59 #include <typedefs.h>60 61 61 62 /** Simple kernel console. … … 157 158 158 159 /** Print count times a character */ 159 _NO_TRACE static void print_cc(char ch, size_t count) 160 { 161 // FIXME: only lock once 162 163 for (size_t i = 0; i < count; i++) 164 putstr(&ch, 1); 160 _NO_TRACE static void print_cc(char32_t ch, size_t count) 161 { 162 size_t i; 163 for (i = 0; i < count; i++) 164 putuchar(ch); 165 165 } 166 166 … … 347 347 if (ch == '\n') { 348 348 /* Enter */ 349 put str("\n", 1);349 putuchar(ch); 350 350 break; 351 351 } … … 358 358 if (wstr_remove(current, position - 1)) { 359 359 position--; 360 put str("\b", 1);360 putuchar('\b'); 361 361 printf("%ls ", current + position); 362 362 print_cc('\b', wstr_length(current) - position + 1); … … 368 368 /* Tab completion */ 369 369 370 size_t i = position; 371 while (current[i] && !isspace(current[i])) 372 i++; 373 374 char32_t stash = current[i]; 375 current[i] = 0; 376 printf("%ls", ¤t[position]); 377 current[i] = stash; 378 position = i; 370 /* Move to the end of the word */ 371 for (; (current[position] != 0) && (!isspace(current[position])); 372 position++) 373 putuchar(current[position]); 379 374 380 375 /* … … 435 430 */ 436 431 size_t off = 0; 437 for (size_t i = 0; (ch = str_decode(tmp, &off, STR_NO_LIMIT)); i++) 432 size_t i = 0; 433 while ((ch = str_decode(tmp, &off, STR_NO_LIMIT)) != 0) { 438 434 if (!wstr_linsert(current, ch, position + i, MAX_CMDLINE)) 439 435 break; 436 437 i++; 438 } 440 439 441 440 if (found > 1) { … … 467 466 /* Left */ 468 467 if (position > 0) { 469 put str("\b", 1);468 putuchar('\b'); 470 469 position--; 471 470 } … … 476 475 /* Right */ 477 476 if (position < wstr_length(current)) { 478 p rintf("%lc",current[position]);477 putuchar(current[position]); 479 478 position++; 480 479 } -
kernel/generic/src/log/log.c
r61c91532 ra65ccc4 46 46 #include <print.h> 47 47 #include <printf_core.h> 48 #include <putchar.h> 48 49 #include <stdarg.h> 49 50 #include <stdlib.h> … … 59 60 60 61 /** Cyclic buffer holding the data for kernel log */ 61 staticuint8_t log_buffer[LOG_LENGTH] __attribute__((aligned(PAGE_SIZE)));62 uint8_t log_buffer[LOG_LENGTH] __attribute__((aligned(PAGE_SIZE))); 62 63 63 64 /** Kernel log initialized */ … … 65 66 66 67 /** Position in the cyclic buffer where the first log entry starts */ 67 s tatic size_t log_start = 0;68 size_t log_start = 0; 68 69 69 70 /** Sum of length of all log entries currently stored in the cyclic buffer */ 70 s tatic size_t log_used = 0;71 size_t log_used = 0; 71 72 72 73 /** Log spinlock */ 73 static IRQ_SPINLOCK_INITIALIZE(log_lock);74 SPINLOCK_STATIC_INITIALIZE_NAME(log_lock, "log_lock"); 74 75 75 76 /** Overall count of logged messages, which may overflow as needed */ … … 151 152 { 152 153 console_lock(); 153 irq_spinlock_lock(&log_lock, true);154 irq_spinlock_lock(&kio_lock, true);154 spinlock_lock(&log_lock); 155 spinlock_lock(&kio_lock); 155 156 156 157 log_current_start = (log_start + log_used) % LOG_LENGTH; … … 178 179 log_used += log_current_len; 179 180 180 kio_push_ bytes("\n", 1);181 irq_spinlock_unlock(&kio_lock, true);182 irq_spinlock_unlock(&log_lock, true);181 kio_push_char('\n'); 182 spinlock_unlock(&kio_lock); 183 spinlock_unlock(&log_lock); 183 184 184 185 /* This has to be called after we released the locks above */ … … 194 195 return; 195 196 196 irq_spinlock_lock(&log_lock, true);197 spinlock_lock(&log_lock); 197 198 if (next_for_uspace < log_used) 198 199 event_notify_0(EVENT_KLOG, true); 199 irq_spinlock_unlock(&log_lock, true);200 spinlock_unlock(&log_lock); 200 201 } 201 202 202 203 static int log_printf_str_write(const char *str, size_t size, void *data) 203 204 { 204 kio_push_bytes(str, size); 205 size_t offset = 0; 206 207 while (offset < size) 208 kio_push_char(str_decode(str, &offset, size)); 209 205 210 log_append((const uint8_t *)str, size); 211 206 212 return EOK; 207 213 } … … 301 307 rc = EOK; 302 308 303 irq_spinlock_lock(&log_lock, true);309 spinlock_lock(&log_lock); 304 310 305 311 while (next_for_uspace < log_used) { … … 331 337 } 332 338 333 irq_spinlock_unlock(&log_lock, true);339 spinlock_unlock(&log_lock); 334 340 335 341 if (rc != EOK) { -
kernel/generic/src/printf/vprintf.c
r61c91532 ra65ccc4 37 37 #include <print.h> 38 38 #include <printf_core.h> 39 #include <putchar.h> 39 40 #include <str.h> 40 41 #include <synch/spinlock.h> … … 43 44 static errno_t vprintf_str_write(const char *str, size_t size, void *data) 44 45 { 45 putstr(str, size); 46 size_t offset = 0; 47 48 while (offset < size) 49 putuchar(str_decode(str, &offset, size)); 50 46 51 return EOK; 47 52 } … … 49 54 int puts(const char *str) 50 55 { 51 size_t n = str_size(str); 52 putstr(str, n); 53 return n; 56 size_t offset = 0; 57 size_t chars = 0; 58 char32_t uc; 59 60 console_lock(); 61 62 while ((uc = str_decode(str, &offset, STR_NO_LIMIT)) != 0) { 63 putuchar(uc); 64 chars++; 65 } 66 67 putuchar('\n'); 68 69 console_unlock(); 70 return chars; 54 71 } 55 72 -
kernel/generic/src/syscall/syscall.c
r61c91532 ra65ccc4 137 137 138 138 [SYS_KLOG] = (syshandler_t) sys_klog, 139 [SYS_KIO_READ] = (syshandler_t) sys_kio_read,140 139 }; 141 140 -
kernel/test/print/print4.c
r61c91532 ra65ccc4 50 50 } 51 51 52 TPRINTF("\nExtended ASCII characters (1 60- 255) using printf(\"%%lc\"):\n");52 TPRINTF("\nExtended ASCII characters (128 - 255) using printf(\"%%lc\"):\n"); 53 53 54 for (group = 5; group < 8; group++) {54 for (group = 4; group < 8; group++) { 55 55 TPRINTF("%#x: ", group << 5); 56 56 -
uspace/app/kio/kio.c
r61c91532 ra65ccc4 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2025 Jiří Zárevúcky4 3 * All rights reserved. 5 4 * … … 35 34 */ 36 35 37 #include <_bits/decls.h>38 #include <libarch/config.h>39 36 #include <stdio.h> 40 37 #include <async.h> … … 50 47 #include <adt/prodcons.h> 51 48 #include <tinput.h> 52 #include <uchar.h>53 49 #include <vfs/vfs.h> 54 50 … … 59 55 typedef struct { 60 56 link_t link; 61 size_t bytes;62 char *data;57 size_t length; 58 char32_t *data; 63 59 } item_t; 64 60 65 61 static prodcons_t pc; 62 63 /* Pointer to kio area */ 64 static char32_t *kio = (char32_t *) AS_AREA_ANY; 65 static size_t kio_length; 66 66 67 67 /* Notification mutex */ 68 68 static FIBRIL_MUTEX_INITIALIZE(mtx); 69 69 70 #define READ_BUFFER_SIZE PAGE_SIZE71 72 static size_t current_at;73 static char read_buffer[READ_BUFFER_SIZE];74 75 70 /** Klog producer 76 71 * … … 82 77 * 83 78 */ 84 static void producer(size_t bytes, char*data)85 { 86 item_t *item = malloc(sizeof(item_t));79 static void producer(size_t length, char32_t *data) 80 { 81 item_t *item = (item_t *) malloc(sizeof(item_t)); 87 82 if (item == NULL) 88 83 return; 89 84 90 item->bytes = bytes;91 item->data = malloc(bytes);92 if ( !item->data) {85 size_t sz = sizeof(char32_t) * length; 86 char32_t *buf = (char32_t *) malloc(sz); 87 if (buf == NULL) { 93 88 free(item); 94 89 return; 95 90 } 96 91 97 memcpy( item->data, data, bytes);92 memcpy(buf, data, sz); 98 93 99 94 link_initialize(&item->link); 95 item->length = length; 96 item->data = buf; 100 97 prodcons_produce(&pc, &item->link); 101 98 } … … 123 120 item_t *item = list_get_instance(link, item_t, link); 124 121 125 fwrite(item->data, 1, item->bytes, stdout); 126 127 if (log) { 128 fwrite(item->data, 1, item->bytes, log); 122 for (size_t i = 0; i < item->length; i++) 123 putuchar(item->data[i]); 124 125 if (log != NULL) { 126 for (size_t i = 0; i < item->length; i++) 127 fputuc(item->data[i], log); 128 129 129 fflush(log); 130 130 vfs_sync(fileno(log)); … … 149 149 static void kio_notification_handler(ipc_call_t *call, void *arg) 150 150 { 151 size_t kio_written = (size_t) ipc_get_arg1(call);152 153 151 /* 154 152 * Make sure we process only a single notification 155 153 * at any time to limit the chance of the consumer 156 154 * starving. 155 * 156 * Note: Usually the automatic masking of the kio 157 * notifications on the kernel side does the trick 158 * of limiting the chance of accidentally copying 159 * the same data multiple times. However, due to 160 * the non-blocking architecture of kio notifications, 161 * this possibility cannot be generally avoided. 157 162 */ 158 163 159 164 fibril_mutex_lock(&mtx); 160 165 161 while (current_at != kio_written) { 162 size_t read = kio_read(read_buffer, READ_BUFFER_SIZE, current_at); 163 if (read == 0) 164 break; 165 166 current_at += read; 167 168 if (read > READ_BUFFER_SIZE) { 169 /* We missed some data. */ 170 // TODO: Send a message with the number of lost characters to the consumer. 171 read = READ_BUFFER_SIZE; 172 } 173 174 producer(read, read_buffer); 175 } 166 size_t kio_start = (size_t) ipc_get_arg1(call); 167 size_t kio_len = (size_t) ipc_get_arg2(call); 168 size_t kio_stored = (size_t) ipc_get_arg3(call); 169 170 size_t offset = (kio_start + kio_len - kio_stored) % kio_length; 171 172 /* Copy data from the ring buffer */ 173 if (offset + kio_stored >= kio_length) { 174 size_t split = kio_length - offset; 175 176 producer(split, kio + offset); 177 producer(kio_stored - split, kio); 178 } else 179 producer(kio_stored, kio + offset); 176 180 177 181 async_event_unmask(EVENT_KIO); … … 181 185 int main(int argc, char *argv[]) 182 186 { 187 size_t pages; 188 errno_t rc = sysinfo_get_value("kio.pages", &pages); 189 if (rc != EOK) { 190 fprintf(stderr, "%s: Unable to get number of kio pages\n", 191 NAME); 192 return rc; 193 } 194 195 uintptr_t faddr; 196 rc = sysinfo_get_value("kio.faddr", &faddr); 197 if (rc != EOK) { 198 fprintf(stderr, "%s: Unable to get kio physical address\n", 199 NAME); 200 return rc; 201 } 202 203 size_t size = pages * PAGE_SIZE; 204 kio_length = size / sizeof(char32_t); 205 206 rc = physmem_map(faddr, pages, AS_AREA_READ | AS_AREA_CACHEABLE, 207 (void *) &kio); 208 if (rc != EOK) { 209 fprintf(stderr, "%s: Unable to map kio\n", NAME); 210 return rc; 211 } 212 183 213 prodcons_initialize(&pc); 184 errno_trc = async_event_subscribe(EVENT_KIO, kio_notification_handler, NULL);214 rc = async_event_subscribe(EVENT_KIO, kio_notification_handler, NULL); 185 215 if (rc != EOK) { 186 216 fprintf(stderr, "%s: Unable to register kio notifications\n", -
uspace/app/trace/syscalls.c
r61c91532 ra65ccc4 115 115 [SYS_DEBUG_CONSOLE] = { "debug_console", 0, V_ERRNO }, 116 116 117 [SYS_KLOG] = { "klog", 5, V_ERRNO }, 118 [SYS_KIO_READ] = { "kio_read", 3, V_INTEGER }, 117 [SYS_KLOG] = { "klog", 5, V_ERRNO } 119 118 }; 120 119 -
uspace/lib/c/generic/io/kio.c
r61c91532 ra65ccc4 34 34 */ 35 35 36 #include <abi/syscall.h>37 36 #include <stddef.h> 38 37 #include <libc.h> … … 113 112 } 114 113 115 size_t kio_read(char *buf, size_t n, size_t at)116 {117 return __SYSCALL3(SYS_KIO_READ, (sysarg_t) buf, n, at);118 }119 120 114 /** Print formatted text to kio. 121 115 * -
uspace/lib/c/include/io/kio.h
r61c91532 ra65ccc4 36 36 #define _LIBC_IO_KIO_H_ 37 37 38 #include <stddef.h> 39 #include <stdarg.h> 40 #include <io/verify.h> 38 41 #include <_bits/errno.h> 39 42 #include <_bits/size_t.h> 40 #include <io/verify.h>41 #include <stdarg.h>42 #include <stddef.h>43 #include <uchar.h>44 43 45 44 extern void __kio_init(void); … … 51 50 _HELENOS_PRINTF_ATTRIBUTE(1, 2); 52 51 extern int kio_vprintf(const char *, va_list); 53 54 extern size_t kio_read(char *buf, size_t n, size_t at);55 52 56 53 /*
Note:
See TracChangeset
for help on using the changeset viewer.