diff options
Diffstat (limited to 'c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.c')
-rw-r--r-- | c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.c | 632 |
1 files changed, 0 insertions, 632 deletions
diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.c b/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.c deleted file mode 100644 index 30c10f73b2..0000000000 --- a/c/src/lib/libbsp/powerpc/ppcn_60x/console/ns16550.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * This file contains the TTY driver for the NS16550 - * - * COPYRIGHT (c) 1998 by Radstone Technology - * - * - * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY - * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK - * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. - * - * You are hereby granted permission to use, copy, modify, and distribute - * this file, provided that this notice, plus the above copyright notice - * and disclaimer, appears in all copies. Radstone Technology will provide - * no support for this code. - * - * This driver uses the termios pseudo driver. - */ - -#include <rtems.h> -#include <bsp.h> -#include <rtems/libio.h> -#include <stdlib.h> - -#include "console.h" -#include "ns16550_p.h" - -/* - * Flow control is only supported when using interrupts - */ -console_flow ns16550_flow_RTSCTS = -{ - ns16550_negate_RTS, /* deviceStopRemoteTx */ - ns16550_assert_RTS /* deviceStartRemoteTx */ -}; - -console_flow ns16550_flow_DTRCTS = -{ - ns16550_negate_DTR, /* deviceStopRemoteTx */ - ns16550_assert_DTR /* deviceStartRemoteTx */ -}; - -console_fns ns16550_fns = -{ - ns16550_probe, /* deviceProbe */ - ns16550_open, /* deviceFirstOpen */ - ns16550_flush, /* deviceLastClose */ - NULL, /* deviceRead */ - ns16550_write_support_int, /* deviceWrite */ - ns16550_initialize_interrupts, /* deviceInitialize */ - ns16550_write_polled, /* deviceWritePolled */ - FALSE, /* deviceOutputUsesInterrupts */ -}; - -console_fns ns16550_fns_polled = -{ - ns16550_probe, /* deviceProbe */ - ns16550_open, /* deviceFirstOpen */ - ns16550_close, /* deviceLastClose */ - ns16550_inbyte_nonblocking_polled, /* deviceRead */ - ns16550_write_support_polled, /* deviceWrite */ - ns16550_init, /* deviceInitialize */ - ns16550_write_polled, /* deviceWritePolled */ - FALSE, /* deviceOutputUsesInterrupts */ -}; - -/* - * Console Device Driver Entry Points - */ -static boolean ns16550_probe(int minor) -{ - /* - * If the configuration dependant probe has located the device then - * assume it is there - */ - return(TRUE); -} - -static void ns16550_init(int minor) -{ - PSP_READ_REGISTERS pNS16550Read; - PSP_WRITE_REGISTERS pNS16550Write; - unsigned8 ucTrash; - unsigned8 ucDataByte; - unsigned32 ulBaudDivisor; - ns16550_context *pns16550Context; - - pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context)); - - Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context; - pns16550Context->ucModemCtrl=SP_MODEM_IRQ; - - pNS16550Read=(PSP_READ_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - pNS16550Write=(PSP_WRITE_REGISTERS)pNS16550Read; - - /* Clear the divisor latch, clear all interrupt enables, - * and reset and - * disable the FIFO's. - */ - - outport_byte(&pNS16550Write->LineControl, 0x0); - outport_byte(&pNS16550Write->InterruptEnable, 0x0); - - /* Set the divisor latch and set the baud rate. */ - - ulBaudDivisor=NS16550_Baud( - (unsigned32)Console_Port_Tbl[minor].pDeviceParams); - ucDataByte = SP_LINE_DLAB; - outport_byte(&pNS16550Write->LineControl, ucDataByte); - outport_byte(&pNS16550Write->TransmitBuffer, ulBaudDivisor&0xff); - outport_byte(&pNS16550Write->InterruptEnable, (ulBaudDivisor>>8)&0xff); - - /* Clear the divisor latch and set the character size to eight bits */ - /* with one stop bit and no parity checking. */ - - ucDataByte = EIGHT_BITS; - outport_byte(&pNS16550Write->LineControl, ucDataByte); - - /* Enable and reset transmit and receive FIFOs. TJA */ - ucDataByte = SP_FIFO_ENABLE; - outport_byte(&pNS16550Write->FifoControl, ucDataByte); - - ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST; - outport_byte(&pNS16550Write->FifoControl, ucDataByte); - - /* - * Disable interrupts - */ - ucDataByte = 0; - outport_byte(&pNS16550Write->InterruptEnable, ucDataByte); - - /* Set data terminal ready. */ - /* And open interrupt tristate line */ - - outport_byte(&pNS16550Write->ModemControl, - pns16550Context->ucModemCtrl); - - inport_byte(&pNS16550Read->LineStatus, ucTrash); - inport_byte(&pNS16550Read->ReceiveBuffer, ucTrash); -} - -static int ns16550_open( - int major, - int minor, - void * arg -) -{ - PSP_WRITE_REGISTERS pNS16550Write; - - pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - - /* - * Assert DTR - */ - if(Console_Port_Tbl[minor].pDeviceFlow - !=&ns16550_flow_DTRCTS) - { - ns16550_assert_DTR(minor); - } - - return(RTEMS_SUCCESSFUL); -} - -static int ns16550_close( - int major, - int minor, - void * arg -) -{ - PSP_WRITE_REGISTERS pNS16550Write; - - pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - - /* - * Negate DTR - */ - if(Console_Port_Tbl[minor].pDeviceFlow - !=&ns16550_flow_DTRCTS) - { - ns16550_negate_DTR(minor); - } - - return(RTEMS_SUCCESSFUL); -} - -/* - * ns16550_write_polled - */ -static void ns16550_write_polled( - int minor, - char cChar -) -{ - PSP_READ_REGISTERS pNS16550Read; - PSP_WRITE_REGISTERS pNS16550Write; - unsigned char ucLineStatus; - int iTimeout; - - pNS16550Read=(PSP_READ_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - pNS16550Write=(PSP_WRITE_REGISTERS)pNS16550Read; - - /* - * wait for transmitter holding register to be empty - */ - iTimeout=1000; - inport_byte(&pNS16550Read->LineStatus, ucLineStatus); - while ((ucLineStatus & SP_LSR_THOLD) == 0) - { - /* - * Yield while we wait - */ - if(_System_state_Is_up(_System_state_Get())) - { - rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); - } - inport_byte(&pNS16550Read->LineStatus, ucLineStatus); - if(!--iTimeout) - { - break; - } - } - - /* - * transmit character - */ - outport_byte(&pNS16550Write->TransmitBuffer, cChar); -} - -/* - * These routines provide control of the RTS and DTR lines - */ -/* - * ns16550_assert_RTS - */ -static void ns16550_assert_RTS(int minor) -{ - PSP_WRITE_REGISTERS pNS16550Write; - unsigned32 Irql; - ns16550_context *pns16550Context; - - pns16550Context=(ns16550_context *) - Console_Port_Data[minor].pDeviceContext; - - pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - - /* - * Assert RTS - */ - rtems_interrupt_disable(Irql); - pns16550Context->ucModemCtrl|=SP_MODEM_RTS; - outport_byte(&pNS16550Write->ModemControl, - pns16550Context->ucModemCtrl); - rtems_interrupt_enable(Irql); -} - -/* - * ns16550_negate_RTS - */ -static void ns16550_negate_RTS(int minor) -{ - PSP_WRITE_REGISTERS pNS16550Write; - unsigned32 Irql; - ns16550_context *pns16550Context; - - pns16550Context=(ns16550_context *) - Console_Port_Data[minor].pDeviceContext; - - pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - - /* - * Negate RTS - */ - rtems_interrupt_disable(Irql); - pns16550Context->ucModemCtrl&=~SP_MODEM_RTS; - outport_byte(&pNS16550Write->ModemControl, - pns16550Context->ucModemCtrl); - rtems_interrupt_enable(Irql); -} - -/* - * These flow control routines utilise a connection from the local DTR - * line to the remote CTS line - */ -/* - * ns16550_assert_DTR - */ -static void ns16550_assert_DTR(int minor) -{ - PSP_WRITE_REGISTERS pNS16550Write; - unsigned32 Irql; - ns16550_context *pns16550Context; - - pns16550Context=(ns16550_context *) - Console_Port_Data[minor].pDeviceContext; - - pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - - /* - * Assert DTR - */ - rtems_interrupt_disable(Irql); - pns16550Context->ucModemCtrl|=SP_MODEM_DTR; - outport_byte(&pNS16550Write->ModemControl, - pns16550Context->ucModemCtrl); - rtems_interrupt_enable(Irql); -} - -/* - * ns16550_negate_DTR - */ -static void ns16550_negate_DTR(int minor) -{ - PSP_WRITE_REGISTERS pNS16550Write; - unsigned32 Irql; - ns16550_context *pns16550Context; - - pns16550Context=(ns16550_context *) - Console_Port_Data[minor].pDeviceContext; - - pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - - /* - * Negate DTR - */ - rtems_interrupt_disable(Irql); - pns16550Context->ucModemCtrl&=~SP_MODEM_DTR; - outport_byte(&pNS16550Write->ModemControl, - pns16550Context->ucModemCtrl); - rtems_interrupt_enable(Irql); -} - -/* - * ns16550_isr - * - * This routine is the console interrupt handler for COM1 and COM2 - * - * Input parameters: - * vector - vector number - * - * Output parameters: NONE - * - * Return values: NONE - */ - -static void ns16550_process( - int minor -) -{ - PSP_READ_REGISTERS pNS16550Read; - PSP_WRITE_REGISTERS pNS16550Write; - volatile unsigned8 ucLineStatus, ucInterruptId; - char cChar; - - pNS16550Read=(PSP_READ_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - pNS16550Write=(PSP_WRITE_REGISTERS)pNS16550Read; - - do - { - /* - * Deal with any received characters - */ - while(TRUE) - { - inport_byte(&pNS16550Read->LineStatus, ucLineStatus); - if(~ucLineStatus & SP_LSR_RDY) - { - break; - } - inport_byte(&pNS16550Read->ReceiveBuffer, cChar); - rtems_termios_enqueue_raw_characters( - Console_Port_Data[minor].termios_data, - &cChar, 1 ); - } - - while(TRUE) - { - if(Ring_buffer_Is_empty( - &Console_Port_Data[minor].TxBuffer)) - { - Console_Port_Data[minor].bActive=FALSE; - if(Console_Port_Tbl[minor].pDeviceFlow - !=&ns16550_flow_RTSCTS) - { - ns16550_negate_RTS(minor); - } - /* - * There is no data to transmit - */ - break; - } - - inport_byte(&pNS16550Read->LineStatus, ucLineStatus); - if(~ucLineStatus & SP_LSR_THOLD) - { - /* - * We'll get another interrupt when - * the transmitter holding reg. becomes - * free again - */ - break; - } - - Ring_buffer_Remove_character( - &Console_Port_Data[minor].TxBuffer, - cChar); - /* - * transmit character - */ - outport_byte(&pNS16550Write->TransmitBuffer, cChar); - } - - inport_byte(&pNS16550Read->InterruptId, ucInterruptId); - } - while((ucInterruptId&0xf)!=0x1); -} - -static rtems_isr ns16550_isr( - rtems_vector_number vector -) -{ - int minor; - - for(minor=0;minor<Console_Port_Count;minor++) - { - if(vector==Console_Port_Tbl[minor].ulIntVector) - { - ns16550_process(minor); - } - } -} - -/* - * ns16550_flush - */ -static int ns16550_flush(int major, int minor, void *arg) -{ - while(!Ring_buffer_Is_empty(&Console_Port_Data[minor].TxBuffer)) - { - /* - * Yield while we wait - */ - if(_System_state_Is_up(_System_state_Get())) - { - rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); - } - } - - ns16550_close(major, minor, arg); - - return(RTEMS_SUCCESSFUL); -} - -/* - * ns16550_initialize_interrupts - * - * This routine initializes the console's receive and transmit - * ring buffers and loads the appropriate vectors to handle the interrupts. - * - * Input parameters: NONE - * - * Output parameters: NONE - * - * Return values: NONE - */ - -static void ns16550_enable_interrupts( - int minor -) -{ - PSP_WRITE_REGISTERS pNS16550Write; - unsigned8 ucDataByte; - - pNS16550Write=(PSP_WRITE_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - - /* - * Enable interrupts - */ - ucDataByte = SP_INT_RX_ENABLE | SP_INT_TX_ENABLE; - outport_byte(&pNS16550Write->InterruptEnable, ucDataByte); - -} - -static void ns16550_initialize_interrupts(int minor) -{ - ns16550_init(minor); - - Ring_buffer_Initialize(&Console_Port_Data[minor].TxBuffer); - - Console_Port_Data[minor].bActive = FALSE; - - set_vector(ns16550_isr, - Console_Port_Tbl[minor].ulIntVector, - 1); - - ns16550_enable_interrupts(minor); -} - -/* - * ns16550_write_support_int - * - * Console Termios output entry point. - * - */ -static int ns16550_write_support_int( - int minor, - const char *buf, - int len) -{ - int i; - unsigned32 Irql; - - for(i=0; i<len;) - { - if(Ring_buffer_Is_full(&Console_Port_Data[minor].TxBuffer)) - { - if(!Console_Port_Data[minor].bActive) - { - /* - * Wake up the device - */ - rtems_interrupt_disable(Irql); - Console_Port_Data[minor].bActive = TRUE; - if(Console_Port_Tbl[minor].pDeviceFlow - !=&ns16550_flow_RTSCTS) - { - ns16550_assert_RTS(minor); - } - ns16550_process(minor); - rtems_interrupt_enable(Irql); - } - else - { - /* - * Yield - */ - rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); - } - - /* - * Wait for ring buffer to empty - */ - continue; - } - else - { - Ring_buffer_Add_character( - &Console_Port_Data[minor].TxBuffer, - buf[i]); - i++; - } - } - - /* - * Ensure that characters are on the way - */ - if(!Console_Port_Data[minor].bActive) - { - /* - * Wake up the device - */ - rtems_interrupt_disable(Irql); - Console_Port_Data[minor].bActive = TRUE; - if(Console_Port_Tbl[minor].pDeviceFlow - !=&ns16550_flow_RTSCTS) - { - ns16550_assert_RTS(minor); - } - ns16550_process(minor); - rtems_interrupt_enable(Irql); - } - - return (len); -} - -/* - * ns16550_write_support_polled - * - * Console Termios output entry point. - * - */ -static int ns16550_write_support_polled( - int minor, - const char *buf, - int len) -{ - int nwrite = 0; - - /* - * poll each byte in the string out of the port. - */ - while (nwrite < len) - { - /* - * transmit character - */ - ns16550_write_polled(minor, *buf++); - nwrite++; - } - - /* - * return the number of bytes written. - */ - return nwrite; -} - -/* - * ns16550_inbyte_nonblocking_polled - * - * Console Termios polling input entry point. - */ - -static int ns16550_inbyte_nonblocking_polled( - int minor -) -{ - PSP_READ_REGISTERS pNS16550Read; - unsigned char ucLineStatus; - char cChar; - - pNS16550Read=(PSP_READ_REGISTERS)Console_Port_Tbl[minor].ulCtrlPort1; - - inport_byte(&pNS16550Read->LineStatus, ucLineStatus); - if(ucLineStatus & SP_LSR_RDY) - { - inport_byte(&pNS16550Read->ReceiveBuffer, cChar); - return((int)cChar); - } - else - { - return(-1); - } -} |