summaryrefslogtreecommitdiffstats
path: root/c/src/libchip/serial/ns16550.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/libchip/serial/ns16550.c')
-rw-r--r--c/src/libchip/serial/ns16550.c659
1 files changed, 0 insertions, 659 deletions
diff --git a/c/src/libchip/serial/ns16550.c b/c/src/libchip/serial/ns16550.c
deleted file mode 100644
index 6f8c3f759f..0000000000
--- a/c/src/libchip/serial/ns16550.c
+++ /dev/null
@@ -1,659 +0,0 @@
-/*
- * This file contains the TTY driver for the National Semiconductor NS16550.
- *
- * This part is widely cloned and second sourced. It is found in a number
- * of "Super IO" controllers.
- *
- * 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 <rtems/libio.h>
-#include <stdlib.h>
-#include <ringbuf.h>
-
-#include <libchip/serial.h>
-#include "ns16550_p.h"
-#include "sersupp.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 = {
- libchip_serial_default_probe, /* deviceProbe */
- ns16550_open, /* deviceFirstOpen */
- NULL, /* deviceLastClose */
- NULL, /* deviceRead */
- ns16550_write_support_int, /* deviceWrite */
- ns16550_initialize_interrupts, /* deviceInitialize */
- ns16550_write_polled, /* deviceWritePolled */
- ns16550_set_attributes, /* deviceSetAttributes */
- TRUE /* deviceOutputUsesInterrupts */
-};
-
-console_fns ns16550_fns_polled = {
- libchip_serial_default_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 */
- ns16550_set_attributes, /* deviceSetAttributes */
- FALSE /* deviceOutputUsesInterrupts */
-};
-
-extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
-
-/*
- * ns16550_init
- */
-
-NS16550_STATIC void ns16550_init(int minor)
-{
- unsigned32 pNS16550;
- unsigned8 ucTrash;
- unsigned8 ucDataByte;
- unsigned32 ulBaudDivisor;
- ns16550_context *pns16550Context;
- setRegister_f setReg;
- getRegister_f getReg;
-
- pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context));
-
- Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context;
- pns16550Context->ucModemCtrl=SP_MODEM_IRQ;
-
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
- setReg = Console_Port_Tbl[minor].setRegister;
- getReg = Console_Port_Tbl[minor].getRegister;
-
- /* Clear the divisor latch, clear all interrupt enables,
- * and reset and
- * disable the FIFO's.
- */
-
- (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0);
- ns16550_enable_interrupts(minor, NS16550_DISABLE_ALL_INTR);
-
- /* Set the divisor latch and set the baud rate. */
-
- ulBaudDivisor=NS16550_Baud((unsigned32)Console_Port_Tbl[minor].pDeviceParams);
- ucDataByte = SP_LINE_DLAB;
- (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
-
- /* XXX */
- (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
- (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (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;
- (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
-
- /* Enable and reset transmit and receive FIFOs. TJA */
- ucDataByte = SP_FIFO_ENABLE;
- (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
-
- ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST;
- (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
-
- ns16550_enable_interrupts(minor, NS16550_DISABLE_ALL_INTR);
-
- /* Set data terminal ready. */
- /* And open interrupt tristate line */
- (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);
-
- ucTrash = (*getReg)(pNS16550, NS16550_LINE_STATUS );
- ucTrash = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER );
-}
-
-/*
- * ns16550_open
- */
-
-NS16550_STATIC int ns16550_open(
- int major,
- int minor,
- void * arg
-)
-{
- /*
- * Assert DTR
- */
-
- if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_DTRCTS) {
- ns16550_assert_DTR(minor);
- }
-
- return(RTEMS_SUCCESSFUL);
-}
-
-/*
- * ns16550_close
- */
-
-NS16550_STATIC int ns16550_close(
- int major,
- int minor,
- void * arg
-)
-{
- /*
- * Negate DTR
- */
- if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_DTRCTS) {
- ns16550_negate_DTR(minor);
- }
-
- return(RTEMS_SUCCESSFUL);
-}
-
-/*
- * ns16550_write_polled
- */
-
-NS16550_STATIC void ns16550_write_polled(
- int minor,
- char cChar
-)
-{
- unsigned32 pNS16550;
- unsigned char ucLineStatus;
- int iTimeout;
- getRegister_f getReg;
- setRegister_f setReg;
-
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
- getReg = Console_Port_Tbl[minor].getRegister;
- setReg = Console_Port_Tbl[minor].setRegister;
-
- /*
- * wait for transmitter holding register to be empty
- */
- iTimeout=1000;
- ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
- while ((ucLineStatus & SP_LSR_THOLD) == 0) {
- /*
- * Yield while we wait
- */
-#if 0
- if(_System_state_Is_up(_System_state_Get())) {
- rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
- }
-#endif
- ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
- if(!--iTimeout) {
- break;
- }
- }
-
- /*
- * transmit character
- */
- (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, cChar);
-}
-
-/*
- * These routines provide control of the RTS and DTR lines
- */
-
-/*
- * ns16550_assert_RTS
- */
-
-NS16550_STATIC int ns16550_assert_RTS(int minor)
-{
- unsigned32 pNS16550;
- unsigned32 Irql;
- ns16550_context *pns16550Context;
- setRegister_f setReg;
-
- pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
-
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
- setReg = Console_Port_Tbl[minor].setRegister;
-
- /*
- * Assert RTS
- */
- rtems_interrupt_disable(Irql);
- pns16550Context->ucModemCtrl|=SP_MODEM_RTS;
- (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
- rtems_interrupt_enable(Irql);
- return 0;
-}
-
-/*
- * ns16550_negate_RTS
- */
-
-NS16550_STATIC int ns16550_negate_RTS(int minor)
-{
- unsigned32 pNS16550;
- unsigned32 Irql;
- ns16550_context *pns16550Context;
- setRegister_f setReg;
-
- pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
-
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
- setReg = Console_Port_Tbl[minor].setRegister;
-
- /*
- * Negate RTS
- */
- rtems_interrupt_disable(Irql);
- pns16550Context->ucModemCtrl&=~SP_MODEM_RTS;
- (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
- rtems_interrupt_enable(Irql);
- return 0;
-}
-
-/*
- * These flow control routines utilise a connection from the local DTR
- * line to the remote CTS line
- */
-
-/*
- * ns16550_assert_DTR
- */
-
-NS16550_STATIC int ns16550_assert_DTR(int minor)
-{
- unsigned32 pNS16550;
- unsigned32 Irql;
- ns16550_context *pns16550Context;
- setRegister_f setReg;
-
- pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
-
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
- setReg = Console_Port_Tbl[minor].setRegister;
-
- /*
- * Assert DTR
- */
- rtems_interrupt_disable(Irql);
- pns16550Context->ucModemCtrl|=SP_MODEM_DTR;
- (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);
- rtems_interrupt_enable(Irql);
- return 0;
-}
-
-/*
- * ns16550_negate_DTR
- */
-
-NS16550_STATIC int ns16550_negate_DTR(int minor)
-{
- unsigned32 pNS16550;
- unsigned32 Irql;
- ns16550_context *pns16550Context;
- setRegister_f setReg;
-
- pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
-
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
- setReg = Console_Port_Tbl[minor].setRegister;
-
- /*
- * Negate DTR
- */
- rtems_interrupt_disable(Irql);
- pns16550Context->ucModemCtrl&=~SP_MODEM_DTR;
- (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);
- rtems_interrupt_enable(Irql);
- return 0;
-}
-
-/*
- * ns16550_set_attributes
- *
- * This function sets the channel to reflect the requested termios
- * port settings.
- */
-
-NS16550_STATIC int ns16550_set_attributes(
- int minor,
- const struct termios *t
-)
-{
- unsigned32 pNS16550;
- unsigned32 ulBaudDivisor;
- unsigned8 ucLineControl;
- unsigned32 baud_requested;
- setRegister_f setReg;
- getRegister_f getReg;
- unsigned32 Irql;
-
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
- setReg = Console_Port_Tbl[minor].setRegister;
- getReg = Console_Port_Tbl[minor].getRegister;
-
- /*
- * Calculate the baud rate divisor
- */
-
- baud_requested = t->c_cflag & CBAUD;
- if (!baud_requested)
- baud_requested = B9600; /* default to 9600 baud */
-
- ulBaudDivisor = termios_baud_to_number(baud_requested);
-
- ucLineControl = 0;
-
- /*
- * Parity
- */
-
- if (t->c_cflag & PARENB) {
- ucLineControl |= SP_LINE_PAR;
- if (!(t->c_cflag & PARODD))
- ucLineControl |= SP_LINE_ODD;
- }
-
- /*
- * Character Size
- */
-
- if (t->c_cflag & CSIZE) {
- switch (t->c_cflag & CSIZE) {
- case CS5: ucLineControl |= FIVE_BITS; break;
- case CS6: ucLineControl |= SIX_BITS; break;
- case CS7: ucLineControl |= SEVEN_BITS; break;
- case CS8: ucLineControl |= EIGHT_BITS; break;
- }
- } else {
- ucLineControl |= EIGHT_BITS; /* default to 9600,8,N,1 */
- }
-
- /*
- * Stop Bits
- */
-
- if (t->c_cflag & CSTOPB) {
- ucLineControl |= SP_LINE_STOP; /* 2 stop bits */
- } else {
- ; /* 1 stop bit */
- }
-
- /*
- * Now actually set the chip
- */
-
- rtems_interrupt_disable(Irql);
-
- /*
- * Set the baud rate
- */
-
- (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB);
- /* XXX are these registers right? */
- (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
- (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);
-
- /*
- * Now write the line control
- */
- (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
-
- rtems_interrupt_enable(Irql);
-
-}
-
-/*
- * ns16550_process
- *
- * This routine is the console interrupt handler for A port.
- */
-
-NS16550_STATIC void ns16550_process(
- int minor
-)
-{
- unsigned32 pNS16550;
- volatile unsigned8 ucLineStatus;
- volatile unsigned8 ucInterruptId;
- unsigned char cChar;
- getRegister_f getReg;
- setRegister_f setReg;
-
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
- getReg = Console_Port_Tbl[minor].getRegister;
- setReg = Console_Port_Tbl[minor].setRegister;
-
- do {
- /*
- * Deal with any received characters
- */
- while(TRUE) {
- ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
- if(~ucLineStatus & SP_LSR_RDY) {
- break;
- }
- cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
- rtems_termios_enqueue_raw_characters(
- Console_Port_Data[minor].termios_data,
- &cChar,
- 1
- );
- }
-
- /*
- * TX all the characters we can
- */
-
- while(TRUE) {
- ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
- if(~ucLineStatus & SP_LSR_THOLD) {
- /*
- * We'll get another interrupt when
- * the transmitter holding reg. becomes
- * free again
- */
- break;
- }
-
-#if 0
- /* XXX flow control not completely supported in libchip */
-
- if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) {
- ns16550_negate_RTS(minor);
- }
-#endif
-
- rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1);
- if (rtems_termios_is_more_to_tx( Console_Port_Data[minor].termios_data )) {
- if (Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) {
- ns16550_negate_RTS(minor);
- }
- Console_Port_Data[minor].bActive = FALSE;
- ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
- break;
- }
-
- ucInterruptId = (*getReg)(pNS16550, NS16550_INTERRUPT_ID);
- }
- } while((ucInterruptId&0xf)!=0x1);
-}
-
-/*
- * ns16550_isr
- */
-
-NS16550_STATIC rtems_isr ns16550_isr(
- rtems_vector_number vector
-)
-{
- int minor;
-
- for(minor=0;minor<Console_Port_Count;minor++) {
- if(Console_Port_Tbl[minor].ulIntVector == vector &&
- Console_Port_Tbl[minor].deviceType == SERIAL_NS16550 ) {
- ns16550_process(minor);
- }
- }
-}
-
-/*
- * ns16550_enable_interrupts
- *
- * This routine initializes the port to have the specified interrupts masked.
- */
-
-NS16550_STATIC void ns16550_enable_interrupts(
- int minor,
- int mask
-)
-{
- unsigned32 pNS16550;
- setRegister_f setReg;
-
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
- setReg = Console_Port_Tbl[minor].setRegister;
-
- (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask);
-}
-
-/*
- * ns16550_initialize_interrupts
- *
- * This routine initializes the port to operate in interrupt driver mode.
- */
-
-NS16550_STATIC void ns16550_initialize_interrupts(int minor)
-{
- ns16550_init(minor);
-
- Console_Port_Data[minor].bActive = FALSE;
-
- set_vector(ns16550_isr, Console_Port_Tbl[minor].ulIntVector, 1);
-
- ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);
-}
-
-/*
- * ns16550_write_support_int
- *
- * Console Termios output entry point.
- */
-
-NS16550_STATIC int ns16550_write_support_int(
- int minor,
- const char *buf,
- int len
-)
-{
- unsigned32 Irql;
- unsigned32 pNS16550;
- setRegister_f setReg;
-
- setReg = Console_Port_Tbl[minor].setRegister;
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
-
- /*
- * We are using interrupt driven output and termios only sends us
- * one character at a time.
- */
-
- if ( !len )
- return 0;
-
- if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) {
- ns16550_assert_RTS(minor);
- }
-
- rtems_interrupt_disable(Irql);
- if ( Console_Port_Data[minor].bActive == FALSE) {
- Console_Port_Data[minor].bActive = TRUE;
- ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);
- }
- (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, *buf);
- rtems_interrupt_enable(Irql);
-
- return 1;
-}
-
-/*
- * ns16550_write_support_polled
- *
- * Console Termios output entry point.
- *
- */
-
-NS16550_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.
- */
-
-NS16550_STATIC int ns16550_inbyte_nonblocking_polled(
- int minor
-)
-{
- unsigned32 pNS16550;
- unsigned char ucLineStatus;
- char cChar;
- getRegister_f getReg;
-
- pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
- getReg = Console_Port_Tbl[minor].getRegister;
-
- ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
- if(ucLineStatus & SP_LSR_RDY) {
- cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
- return (int)cChar;
- } else {
- return -1;
- }
-}