From b3fd16416cc283f2c8340ac7cb06270cf51adb5f Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 21 Aug 1998 15:32:19 +0000 Subject: Fix from Eric Norum : "Thomas Doerfler" wrote: > > While implementing/testing the console/termios support for > PPC403 in RTEMS-4.0.0-beta3, I am stuck at a certain location in > termios.c: > > During "rtems_termios_initialize", the main control data structure > "*tty" is allocated using malloc(). (Note, that malloc does not > clear the allocated memory and my BSP does not clear memory during > startup). Furtheron, a lot of fields of that structure are > initialized, but the field "rawOutBufState" is not, and therefore > keeps an arbitrary contents. > > When "osend()" is called the first time(with the serial device > driver working in interrupt mode), termios gets stuck and will not > call the device drivers output function. > > My questions now are: > > - anybody already experienced this bug? > - is it a bug at all or did I do anything fundamentally wrong? > - is there already a common bugfix for that? > > I don't like poking around in other people code, as long as I am > not absolutely sure, what I do... Yes, there's a bug there. I thought that Joel had patched this already, but here's a patch to fix this. This patch also addresses a concern that many others have raised regarding enabling and disabling of transmitter interrupts. First, here's the example I've been using of a simple UART-style interrupt-driven driver: =============================================================== void device_write_routine (int minor, char *buf, int count) { UART->control_register &= ~UART_TRANSMITTER_READY; UART->output_register = *buf; UART->control_register |= UART_TRANSMIT_INTERRUPT_ENABLE; } void device_transmit_interrupt_routine (int vector) { UART->control_register &= ~UART_TRANSMIT_INTERRUPT_ENABLE; rtems_termios_dequeue_characters (device_ttyp, 1); } ============================================================== Several people have expressed their concern about the disable/enable of transmitter interrupts for every character. On some machines this disable/enable is an expensive operation. With the attached patch applied you can write the two routines as: ============================================================== void device_write_routine (int minor, char *buf, int count) { code_to_clear_transmitter_ready_status (); if (device_ttyp->rawOutBufState == rob_idle) code_to_enable_transmitter_interrupts (); code_to_send_one_character_to_transmitter (*buf); } void device_transmit_interrupt_routine (int vector) { rtems_termios_dequeue_characters (device_ttyp, 1); if (device_ttyp->rawOutBufState == rob_idle) code_to_disable_transmitter_interrupts (); } =============================================================== --- c/src/exec/libcsupport/src/termios.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'c/src/exec/libcsupport') diff --git a/c/src/exec/libcsupport/src/termios.c b/c/src/exec/libcsupport/src/termios.c index e7fcf8ee30..f6b5652e57 100644 --- a/c/src/exec/libcsupport/src/termios.c +++ b/c/src/exec/libcsupport/src/termios.c @@ -213,7 +213,6 @@ rtems_termios_open ( } tty->forw = ttyHead; ttyHead = tty; - tty->back = NULL; if (ttyTail == NULL) ttyTail = tty; @@ -247,9 +246,6 @@ rtems_termios_open ( &tty->rawOutBufSemaphore); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); - tty->rawOutBufHead = 0; - tty->rawOutBufTail = 0; - tty->refcount = 0; tty->rawOutBufState = rob_idle; /* @@ -265,16 +261,8 @@ rtems_termios_open ( &tty->rawInBufSemaphore); if (sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (sc); - tty->rawInBufHead = 0; - tty->rawInBufTail = 0; } - /* - * Initialize variables - */ - tty->column = 0; - tty->cindex = tty->ccount = 0; - /* * Set default parameters */ @@ -481,9 +469,9 @@ osend (const char *buf, int len, struct rtems_termios_tty *tty) tty->rawOutBuf[tty->rawOutBufHead] = *buf++; tty->rawOutBufHead = newHead; if (tty->rawOutBufState == rob_idle) { - tty->rawOutBufState = rob_busy; (*tty->device.write)(tty->minor, (char *)&tty->rawOutBuf[tty->rawOutBufTail], 1); + tty->rawOutBufState = rob_busy; } rtems_interrupt_enable (level); len--; @@ -935,12 +923,12 @@ rtems_termios_dequeue_characters (void *ttyp, int len) /* * Buffer not empty, start tranmitter */ - tty->rawOutBufState = rob_busy; if (newTail > tty->rawOutBufHead) nToSend = RAW_OUTPUT_BUFFER_SIZE - newTail; else nToSend = tty->rawOutBufHead - newTail; (*tty->device.write)(tty->minor, (char *)&tty->rawOutBuf[newTail], nToSend); + tty->rawOutBufState = rob_busy; } tty->rawOutBufTail = newTail; } -- cgit v1.2.3