From 198d851c7703b7983571aec61a0bbeeb96244371 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 15 Jul 1998 23:20:33 +0000 Subject: Switched from driver's own buffering to using termios. This eliminated the need for the ringbuffer manipulation in this driver. It should also allow the removal of mc68681_flush. This greatly simplified the interrupt processing. Reworked Interrupt Mask Register handling. Added imr field to the device context. This handling makes sure that the IMR accurately reflects the state of the port in use and its mate. This required the reworking of the mc68681_enable_interrupts() routine to allow for the specification of which interrupt sources were being enabled/disabled. Reworked initialization to reset using port address rather than chip base address. Basically we were always resetting port 0. Added deviceType field which allows for multiple chips of the same class to have the same vector number. --- c/src/lib/libchip/serial/mc68681.c | 214 ++++++++++++++++--------------------- c/src/libchip/serial/mc68681.c | 214 ++++++++++++++++--------------------- 2 files changed, 186 insertions(+), 242 deletions(-) diff --git a/c/src/lib/libchip/serial/mc68681.c b/c/src/lib/libchip/serial/mc68681.c index 9793015c6d..19e9509a79 100644 --- a/c/src/lib/libchip/serial/mc68681.c +++ b/c/src/lib/libchip/serial/mc68681.c @@ -35,7 +35,7 @@ console_fns mc68681_fns = { libchip_serial_default_probe, /* deviceProbe */ mc68681_open, /* deviceFirstOpen */ - mc68681_flush, /* deviceLastClose */ + NULL, /* deviceLastClose */ NULL, /* deviceRead */ mc68681_write_support_int, /* deviceWrite */ mc68681_initialize_interrupts, /* deviceInitialize */ @@ -293,6 +293,7 @@ MC68681_STATIC void mc68681_initialize_context( if ( Console_Port_Tbl[port].ulCtrlPort1 == pMC68681 && Console_Port_Tbl[port].ulCtrlPort2 != pMC68681_port ) { pmc68681Context->mate = port; + pmc68681Context->imr = 0; break; } } @@ -328,23 +329,23 @@ MC68681_STATIC void mc68681_init(int minor) * Reset everything and leave this port disabled. */ - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX ); - (*setReg)( pMC68681, MC68681_MODE_REG_1A, 0x00 ); - (*setReg)( pMC68681, MC68681_MODE_REG_2A, 0x02 ); + (*setReg)( pMC68681_port, MC68681_MODE_REG_1A, 0x00 ); + (*setReg)( pMC68681_port, MC68681_MODE_REG_2A, 0x02 ); /* * Disable interrupts on RX and TX for this port */ - (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr(minor, 0)); + mc68681_enable_interrupts( minor, MC68681_IMR_DISABLE_ALL ); } /* @@ -498,7 +499,8 @@ MC68681_STATIC rtems_isr mc68681_isr( int minor; for(minor=0 ; minor>= 4; - ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); - if(!(ucLineStatus & (MC68681_TX_EMPTY|MC68681_TX_READY))) { - /* - * We'll get another interrupt when the TX can take another character. - */ - break; - } - - Ring_buffer_Remove_character( &Console_Port_Data[minor].TxBuffer, cChar); - /* - * transmit character - */ - (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar); + if(ucLineStatus & MC68681_IR_TX_READY) { + mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL_EXCEPT_TX); + rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1); } } @@ -848,49 +790,79 @@ MC68681_STATIC unsigned int mc68681_build_imr( ) { int mate; + int is_a; unsigned int mask; unsigned int mate_mask; unsigned int pMC68681; unsigned int pMC68681_port; mc68681_context *pmc68681Context; + mc68681_context *mateContext; pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext; mate = pmc68681Context->mate; + mask = 0; mate_mask = 0; + is_a = (pMC68681 == pMC68681_port); + /* - * Decide if the other port on this DUART is using interrupts + * If there is a mate for this port, get its IMR mask. */ if ( mate != -1 ) { - if ( Console_Port_Tbl[mate].pDeviceFns->deviceOutputUsesInterrupts ) - mate_mask = 0x03; + mateContext = Console_Port_Data[mate].pDeviceContext; + + if (mateContext) + mate_mask = mateContext->imr; + } - /* - * If equal, then minor is A so the mate must be B - */ + /* + * Calculate this port's IMR mask and save it in the context area. + */ - if ( pMC68681 == pMC68681_port ) - mate_mask <<= 4; - } + if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts ) + mask = enable_flag; + + pmc68681Context->imr = mask; /* - * Add in minor's mask + * Now return the full IMR value */ - mask = 0; - if ( enable_flag ) { - if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts ) { - if ( pMC68681 == pMC68681_port ) - mask = 0x03; - else - mask = 0x30; - } - } + if (is_a) + return (mate_mask << 4) | mask; + + return (mask << 4) | mate_mask; +} + +/* + * mc68681_enable_interrupts + * + * This function initializes the hardware for this port to use interrupts. + */ + +MC68681_STATIC void mc68681_enable_interrupts( + int minor, + int imr_mask +) +{ + unsigned32 pMC68681; + setRegister_f setReg; + + pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; + setReg = Console_Port_Tbl[minor].setRegister; + + /* + * Enable interrupts on RX and TX -- not break + */ - return mask | mate_mask; + (*setReg)( + pMC68681, + MC68681_INTERRUPT_MASK_REG, + mc68681_build_imr(minor, imr_mask) + ); } diff --git a/c/src/libchip/serial/mc68681.c b/c/src/libchip/serial/mc68681.c index 9793015c6d..19e9509a79 100644 --- a/c/src/libchip/serial/mc68681.c +++ b/c/src/libchip/serial/mc68681.c @@ -35,7 +35,7 @@ console_fns mc68681_fns = { libchip_serial_default_probe, /* deviceProbe */ mc68681_open, /* deviceFirstOpen */ - mc68681_flush, /* deviceLastClose */ + NULL, /* deviceLastClose */ NULL, /* deviceRead */ mc68681_write_support_int, /* deviceWrite */ mc68681_initialize_interrupts, /* deviceInitialize */ @@ -293,6 +293,7 @@ MC68681_STATIC void mc68681_initialize_context( if ( Console_Port_Tbl[port].ulCtrlPort1 == pMC68681 && Console_Port_Tbl[port].ulCtrlPort2 != pMC68681_port ) { pmc68681Context->mate = port; + pmc68681Context->imr = 0; break; } } @@ -328,23 +329,23 @@ MC68681_STATIC void mc68681_init(int minor) * Reset everything and leave this port disabled. */ - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX ); - (*setReg)( pMC68681, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX ); + (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX ); - (*setReg)( pMC68681, MC68681_MODE_REG_1A, 0x00 ); - (*setReg)( pMC68681, MC68681_MODE_REG_2A, 0x02 ); + (*setReg)( pMC68681_port, MC68681_MODE_REG_1A, 0x00 ); + (*setReg)( pMC68681_port, MC68681_MODE_REG_2A, 0x02 ); /* * Disable interrupts on RX and TX for this port */ - (*setReg)( pMC68681, MC68681_INTERRUPT_MASK_REG, mc68681_build_imr(minor, 0)); + mc68681_enable_interrupts( minor, MC68681_IMR_DISABLE_ALL ); } /* @@ -498,7 +499,8 @@ MC68681_STATIC rtems_isr mc68681_isr( int minor; for(minor=0 ; minor>= 4; - ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS); - if(!(ucLineStatus & (MC68681_TX_EMPTY|MC68681_TX_READY))) { - /* - * We'll get another interrupt when the TX can take another character. - */ - break; - } - - Ring_buffer_Remove_character( &Console_Port_Data[minor].TxBuffer, cChar); - /* - * transmit character - */ - (*setReg)(pMC68681_port, MC68681_TX_BUFFER, cChar); + if(ucLineStatus & MC68681_IR_TX_READY) { + mc68681_enable_interrupts(minor, MC68681_IMR_ENABLE_ALL_EXCEPT_TX); + rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1); } } @@ -848,49 +790,79 @@ MC68681_STATIC unsigned int mc68681_build_imr( ) { int mate; + int is_a; unsigned int mask; unsigned int mate_mask; unsigned int pMC68681; unsigned int pMC68681_port; mc68681_context *pmc68681Context; + mc68681_context *mateContext; pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2; pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext; mate = pmc68681Context->mate; + mask = 0; mate_mask = 0; + is_a = (pMC68681 == pMC68681_port); + /* - * Decide if the other port on this DUART is using interrupts + * If there is a mate for this port, get its IMR mask. */ if ( mate != -1 ) { - if ( Console_Port_Tbl[mate].pDeviceFns->deviceOutputUsesInterrupts ) - mate_mask = 0x03; + mateContext = Console_Port_Data[mate].pDeviceContext; + + if (mateContext) + mate_mask = mateContext->imr; + } - /* - * If equal, then minor is A so the mate must be B - */ + /* + * Calculate this port's IMR mask and save it in the context area. + */ - if ( pMC68681 == pMC68681_port ) - mate_mask <<= 4; - } + if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts ) + mask = enable_flag; + + pmc68681Context->imr = mask; /* - * Add in minor's mask + * Now return the full IMR value */ - mask = 0; - if ( enable_flag ) { - if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts ) { - if ( pMC68681 == pMC68681_port ) - mask = 0x03; - else - mask = 0x30; - } - } + if (is_a) + return (mate_mask << 4) | mask; + + return (mask << 4) | mate_mask; +} + +/* + * mc68681_enable_interrupts + * + * This function initializes the hardware for this port to use interrupts. + */ + +MC68681_STATIC void mc68681_enable_interrupts( + int minor, + int imr_mask +) +{ + unsigned32 pMC68681; + setRegister_f setReg; + + pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1; + setReg = Console_Port_Tbl[minor].setRegister; + + /* + * Enable interrupts on RX and TX -- not break + */ - return mask | mate_mask; + (*setReg)( + pMC68681, + MC68681_INTERRUPT_MASK_REG, + mc68681_build_imr(minor, imr_mask) + ); } -- cgit v1.2.3