Changeset 8a9bdc5 in rtems
- Timestamp:
- 10/07/14 09:37:55 (9 years ago)
- Branches:
- 4.11, 5, master
- Children:
- 77dd9a4
- Parents:
- 2fd3e65f
- git-author:
- Sebastian Huber <sebastian.huber@…> (10/07/14 09:37:55)
- git-committer:
- Sebastian Huber <sebastian.huber@…> (10/07/14 14:35:20)
- Location:
- c/src/libchip/serial
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/libchip/serial/ns16550-context.c
r2fd3e65f r8a9bdc5 99 99 } 100 100 101 static void ns16550_clear_and_set_interrupts( 102 ns16550_context *ctx, 103 uint8_t clear, 104 uint8_t set 105 ) 106 { 107 rtems_interrupt_lock_context lock_context; 108 ns16550_get_reg get_reg = ctx->get_reg; 109 ns16550_set_reg set_reg = ctx->set_reg; 110 uintptr_t port = ctx->port; 111 uint8_t val; 112 113 rtems_termios_device_lock_acquire(&ctx->base, &lock_context); 114 val = (*get_reg)(port, NS16550_INTERRUPT_ENABLE); 115 val &= ~clear; 116 val |= set; 117 (*set_reg)(port, NS16550_INTERRUPT_ENABLE, val); 118 rtems_termios_device_lock_release(&ctx->base, &lock_context); 119 } 120 101 121 /* 102 122 * ns16550_probe … … 180 200 return out; 181 201 } 182 183 #if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)184 202 185 203 /** … … 226 244 } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0); 227 245 } 228 #endif 246 247 static void ns16550_isr_task(void *arg) 248 { 249 rtems_termios_tty *tty = arg; 250 ns16550_context *ctx = rtems_termios_get_device_context(tty); 251 uint8_t status = (*ctx->get_reg)(ctx->port, NS16550_LINE_STATUS); 252 253 if ((status & SP_LSR_RDY) != 0) { 254 ns16550_clear_and_set_interrupts(ctx, SP_INT_RX_ENABLE, 0); 255 rtems_termios_rxirq_occured(tty); 256 } 257 258 if (ctx->out_total > 0 && (status & SP_LSR_THOLD) != 0) { 259 size_t current = ctx->out_current; 260 261 ctx->out_buf += current; 262 ctx->out_remaining -= current; 263 264 if (ctx->out_remaining > 0) { 265 ctx->out_current = 266 ns16550_write_to_fifo(ctx, ctx->out_buf, ctx->out_remaining); 267 } else { 268 size_t done = ctx->out_total; 269 270 ctx->out_total = 0; 271 ns16550_clear_and_set_interrupts(ctx, SP_INT_TX_ENABLE, 0); 272 rtems_termios_dequeue_characters(tty, done); 273 } 274 } 275 } 276 277 static int ns16550_read_task(rtems_termios_device_context *base) 278 { 279 ns16550_context *ctx = (ns16550_context *) base; 280 uint32_t port = ctx->port; 281 ns16550_get_reg get = ctx->get_reg; 282 char buf[SP_FIFO_SIZE]; 283 int i; 284 285 for (i = 0; i < SP_FIFO_SIZE; ++i) { 286 if ((get(port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) { 287 buf[i] = (char) get(port, NS16550_RECEIVE_BUFFER); 288 } else { 289 break; 290 } 291 } 292 293 rtems_termios_enqueue_raw_characters(ctx->tty, buf, i); 294 ns16550_clear_and_set_interrupts(ctx, 0, SP_INT_RX_ENABLE); 295 296 return -1; 297 } 229 298 230 299 /* … … 235 304 static void ns16550_initialize_interrupts( 236 305 struct rtems_termios_tty *tty, 237 ns16550_context *ctx 306 ns16550_context *ctx, 307 void (*isr)(void *) 238 308 ) 239 309 { … … 245 315 "NS16550", 246 316 RTEMS_INTERRUPT_SHARED, 247 ns16550_isr,317 isr, 248 318 tty 249 319 ); … … 260 330 rtems_irq_connect_data cd = { 261 331 ctx->irq, 262 ns16550_isr,332 isr, 263 333 tty, 264 334 NULL, … … 271 341 rtems_irq_connect_data cd = { 272 342 ctx->irq, 273 ns16550_isr,343 isr, 274 344 tty, 275 345 NULL, … … 301 371 ns16550_context *ctx = (ns16550_context *) base; 302 372 373 ctx->tty = tty; 374 303 375 /* Set initial baud */ 304 376 rtems_termios_set_initial_baud(tty, ctx->initial_baud); 305 377 306 378 if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) { 307 ns16550_initialize_interrupts(tty, ctx); 379 ns16550_initialize_interrupts(tty, ctx, ns16550_isr); 380 ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); 381 } else if (tty->handler.mode == TERMIOS_TASK_DRIVEN) { 382 ns16550_initialize_interrupts(tty, ctx, ns16550_isr_task); 308 383 ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); 309 384 } … … 314 389 static void ns16550_cleanup_interrupts( 315 390 struct rtems_termios_tty *tty, 316 ns16550_context *ctx 391 ns16550_context *ctx, 392 void (*isr)(void *) 317 393 ) 318 394 { … … 321 397 sc = rtems_interrupt_handler_remove( 322 398 ctx->irq, 323 ns16550_isr,399 isr, 324 400 tty 325 401 ); … … 333 409 rtems_irq_connect_data cd = { 334 410 .name = ctx->irq, 335 .hdl = ns16550_isr,411 .hdl = isr, 336 412 .handle = tty 337 413 }; … … 360 436 361 437 if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) { 362 ns16550_cleanup_interrupts(tty, ctx); 438 ns16550_cleanup_interrupts(tty, ctx, ns16550_isr); 439 } else if (tty->handler.mode == TERMIOS_TASK_DRIVEN) { 440 ns16550_cleanup_interrupts(tty, ctx, ns16550_isr_task); 363 441 } 364 442 } … … 612 690 } else { 613 691 ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); 692 } 693 } 694 695 static void ns16550_write_support_task( 696 rtems_termios_device_context *base, 697 const char *buf, 698 size_t len 699 ) 700 { 701 ns16550_context *ctx = (ns16550_context *) base; 702 703 ctx->out_total = len; 704 705 if (len > 0) { 706 ctx->out_remaining = len; 707 ctx->out_buf = buf; 708 ctx->out_current = ns16550_write_to_fifo(ctx, buf, len); 709 710 ns16550_clear_and_set_interrupts(ctx, 0, SP_INT_TX_ENABLE); 614 711 } 615 712 } … … 695 792 .mode = TERMIOS_POLLED 696 793 }; 794 795 const rtems_termios_device_handler ns16550_handler_task = { 796 .first_open = ns16550_open, 797 .last_close = ns16550_close, 798 .poll_read = ns16550_read_task, 799 .write = ns16550_write_support_task, 800 .set_attributes = ns16550_set_attributes, 801 .mode = TERMIOS_TASK_DRIVEN 802 }; -
c/src/libchip/serial/ns16550.h
r2fd3e65f r8a9bdc5 75 75 size_t out_current; 76 76 const char *out_buf; 77 rtems_termios_tty *tty; 77 78 } ns16550_context; 78 79 79 80 extern const rtems_termios_device_handler ns16550_handler_interrupt; 80 81 extern const rtems_termios_device_handler ns16550_handler_polled; 82 extern const rtems_termios_device_handler ns16550_handler_task; 81 83 82 84 extern const rtems_termios_device_flow ns16550_flow_rtscts;
Note: See TracChangeset
for help on using the changeset viewer.