forked from Imagelibrary/rtems
Include required header files. Removed support for old PowerPC exception handling. Various fixes for interrupt related routines. Added support for BSPs with IRQ extension API.
This commit is contained in:
@@ -20,16 +20,33 @@
|
|||||||
* This driver uses the termios pseudo driver.
|
* This driver uses the termios pseudo driver.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
#include <rtems/libio.h>
|
#include <rtems/libio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <rtems/ringbuf.h>
|
#include <rtems/ringbuf.h>
|
||||||
|
#include <rtems/bspIo.h>
|
||||||
|
|
||||||
#include <libchip/serial.h>
|
#include <libchip/serial.h>
|
||||||
#include <libchip/sersupp.h>
|
#include <libchip/sersupp.h>
|
||||||
#include <rtems/bspIo.h>
|
|
||||||
|
#include <bsp/irq.h>
|
||||||
|
|
||||||
#include "ns16550_p.h"
|
#include "ns16550_p.h"
|
||||||
|
|
||||||
|
#ifdef BSP_FEATURE_IRQ_EXTENSION
|
||||||
|
/* Nothing to do */
|
||||||
|
#elif defined BSP_FEATURE_IRQ_LEGACY
|
||||||
|
/* Nothing to do */
|
||||||
|
#elif defined __PPC__
|
||||||
|
#define BSP_FEATURE_IRQ_LEGACY
|
||||||
|
#ifdef BSP_SHARED_HANDLER_SUPPORT
|
||||||
|
#define BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#warning No interrupt support available
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flow control is only supported when using interrupts
|
* Flow control is only supported when using interrupts
|
||||||
*/
|
*/
|
||||||
@@ -68,14 +85,6 @@ console_fns ns16550_fns_polled = {
|
|||||||
false /* deviceOutputUsesInterrupts */
|
false /* deviceOutputUsesInterrupts */
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__PPC__)
|
|
||||||
#ifdef _OLD_EXCEPTIONS
|
|
||||||
extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
|
|
||||||
#else
|
|
||||||
#include <bsp/irq.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ns16550_init
|
* ns16550_init
|
||||||
*/
|
*/
|
||||||
@@ -92,6 +101,11 @@ NS16550_STATIC void ns16550_init(int minor)
|
|||||||
|
|
||||||
pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context));
|
pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context));
|
||||||
|
|
||||||
|
if (pns16550Context == NULL) {
|
||||||
|
printk( "%s: Error: Not enough memory\n", __func__);
|
||||||
|
rtems_fatal_error_occurred( 0xdeadbeef);
|
||||||
|
}
|
||||||
|
|
||||||
Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context;
|
Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context;
|
||||||
pns16550Context->ucModemCtrl=SP_MODEM_IRQ;
|
pns16550Context->ucModemCtrl=SP_MODEM_IRQ;
|
||||||
|
|
||||||
@@ -117,8 +131,8 @@ NS16550_STATIC void ns16550_init(int minor)
|
|||||||
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
|
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
|
||||||
|
|
||||||
/* XXX */
|
/* XXX */
|
||||||
(*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
|
(*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, (uint8_t) (ulBaudDivisor & 0xffU));
|
||||||
(*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);
|
(*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (uint8_t) ((ulBaudDivisor >> 8) & 0xffU));
|
||||||
|
|
||||||
/* Clear the divisor latch and set the character size to eight bits */
|
/* Clear the divisor latch and set the character size to eight bits */
|
||||||
/* with one stop bit and no parity checking. */
|
/* with one stop bit and no parity checking. */
|
||||||
@@ -441,10 +455,11 @@ NS16550_STATIC int ns16550_set_attributes(
|
|||||||
* This routine is the console interrupt handler for A port.
|
* This routine is the console interrupt handler for A port.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NS16550_STATIC void ns16550_process(
|
NS16550_STATIC void ns16550_process( int minor)
|
||||||
int minor
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
|
console_tbl *c = &Console_Port_Tbl [minor];
|
||||||
|
console_data *d = &Console_Port_Data [minor];
|
||||||
|
|
||||||
uint32_t pNS16550;
|
uint32_t pNS16550;
|
||||||
volatile uint8_t ucLineStatus;
|
volatile uint8_t ucLineStatus;
|
||||||
volatile uint8_t ucInterruptId;
|
volatile uint8_t ucInterruptId;
|
||||||
@@ -452,22 +467,22 @@ NS16550_STATIC void ns16550_process(
|
|||||||
getRegister_f getReg;
|
getRegister_f getReg;
|
||||||
setRegister_f setReg;
|
setRegister_f setReg;
|
||||||
|
|
||||||
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
|
pNS16550 = c->ulCtrlPort1;
|
||||||
getReg = Console_Port_Tbl[minor].getRegister;
|
getReg = c->getRegister;
|
||||||
setReg = Console_Port_Tbl[minor].setRegister;
|
setReg = c->setRegister;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/*
|
/*
|
||||||
* Deal with any received characters
|
* Deal with any received characters
|
||||||
*/
|
*/
|
||||||
while(true) {
|
while (true) {
|
||||||
ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
|
ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
|
||||||
if(~ucLineStatus & SP_LSR_RDY) {
|
if (~ucLineStatus & SP_LSR_RDY) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
|
cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
|
||||||
rtems_termios_enqueue_raw_characters(
|
rtems_termios_enqueue_raw_characters(
|
||||||
Console_Port_Data[minor].termios_data,
|
d->termios_data,
|
||||||
&cChar,
|
&cChar,
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
@@ -477,9 +492,9 @@ NS16550_STATIC void ns16550_process(
|
|||||||
* TX all the characters we can
|
* TX all the characters we can
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while(true) {
|
while (true) {
|
||||||
ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
|
ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
|
||||||
if(~ucLineStatus & SP_LSR_THOLD) {
|
if (~ucLineStatus & SP_LSR_THOLD) {
|
||||||
/*
|
/*
|
||||||
* We'll get another interrupt when
|
* We'll get another interrupt when
|
||||||
* the transmitter holding reg. becomes
|
* the transmitter holding reg. becomes
|
||||||
@@ -488,71 +503,20 @@ NS16550_STATIC void ns16550_process(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
if (rtems_termios_dequeue_characters( d->termios_data, 1) == 0) {
|
||||||
/* XXX flow control not completely supported in libchip */
|
if (c->pDeviceFlow != &ns16550_flow_RTSCTS) {
|
||||||
|
|
||||||
if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) {
|
|
||||||
ns16550_negate_RTS(minor);
|
ns16550_negate_RTS(minor);
|
||||||
}
|
}
|
||||||
#endif
|
d->bActive = false;
|
||||||
|
|
||||||
rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1);
|
|
||||||
if (rtems_termios_dequeue_characters(
|
|
||||||
Console_Port_Data[minor].termios_data, 1)) {
|
|
||||||
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);
|
ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ucInterruptId = (*getReg)(pNS16550, NS16550_INTERRUPT_ID);
|
ucInterruptId = (*getReg)(pNS16550, NS16550_INTERRUPT_ID);
|
||||||
}
|
|
||||||
} while((ucInterruptId&0xf)!=0x1);
|
} while((ucInterruptId&0xf)!=0x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__PPC__)
|
|
||||||
#ifdef _OLD_EXCEPTIONS
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
NS16550_STATIC rtems_isr ns16550_isr(
|
|
||||||
void *entry
|
|
||||||
)
|
|
||||||
{
|
|
||||||
console_tbl *ptr = entry;
|
|
||||||
int minor;
|
|
||||||
|
|
||||||
for(minor=0;minor<Console_Port_Count;minor++) {
|
|
||||||
if( &Console_Port_Tbl[minor] == ptr ) {
|
|
||||||
ns16550_process(minor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ns16550_enable_interrupts
|
* ns16550_enable_interrupts
|
||||||
*
|
*
|
||||||
@@ -573,68 +537,88 @@ NS16550_STATIC void ns16550_enable_interrupts(
|
|||||||
(*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask);
|
(*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BSP_FEATURE_IRQ_EXTENSION
|
||||||
|
NS16550_STATIC void ns16550_isr( rtems_vector_number vector, void *arg)
|
||||||
|
{
|
||||||
|
int minor = (int) arg;
|
||||||
|
|
||||||
|
ns16550_process( minor);
|
||||||
|
}
|
||||||
|
#elif defined BSP_FEATURE_IRQ_LEGACY
|
||||||
|
NS16550_STATIC rtems_isr ns16550_isr( void *arg)
|
||||||
|
{
|
||||||
|
int minor = (int) arg;
|
||||||
|
|
||||||
|
ns16550_process( minor);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ns16550_initialize_interrupts
|
* ns16550_initialize_interrupts
|
||||||
*
|
*
|
||||||
* This routine initializes the port to operate in interrupt driver mode.
|
* This routine initializes the port to operate in interrupt driver mode.
|
||||||
*/
|
*/
|
||||||
|
NS16550_STATIC void ns16550_initialize_interrupts( int minor)
|
||||||
#if defined(__PPC__)
|
|
||||||
#ifdef _OLD_EXCEPTIONS
|
|
||||||
NS16550_STATIC void ns16550_initialize_interrupts(int minor)
|
|
||||||
{
|
{
|
||||||
ns16550_init(minor);
|
console_tbl *c = &Console_Port_Tbl [minor];
|
||||||
|
console_data *d = &Console_Port_Data [minor];
|
||||||
|
|
||||||
Console_Port_Data[minor].bActive = FALSE;
|
ns16550_init( minor);
|
||||||
|
|
||||||
set_vector(ns16550_isr, Console_Port_Tbl[minor].ulIntVector, 1);
|
d->bActive = false;
|
||||||
|
|
||||||
ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);
|
#ifdef BSP_FEATURE_IRQ_EXTENSION
|
||||||
}
|
{
|
||||||
#else
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
sc = rtems_interrupt_handler_install(
|
||||||
NS16550_STATIC void ns16550_initialize_interrupts(int minor)
|
c->ulIntVector,
|
||||||
{
|
"NS16550",
|
||||||
#ifdef BSP_SHARED_HANDLER_SUPPORT
|
RTEMS_INTERRUPT_SHARED,
|
||||||
rtems_irq_connect_data IrqData = {0,
|
|
||||||
ns16550_isr,
|
ns16550_isr,
|
||||||
&Console_Port_Data[minor],
|
(void *) minor
|
||||||
NULL,
|
);
|
||||||
NULL,
|
if (sc != RTEMS_SUCCESSFUL) {
|
||||||
NULL,
|
/* FIXME */
|
||||||
NULL
|
printk( "%s: Error: Install interrupt handler\n", __func__);
|
||||||
};
|
rtems_fatal_error_occurred( 0xdeadbeef);
|
||||||
#else
|
|
||||||
rtems_irq_connect_data IrqData = {0,
|
|
||||||
ns16550_isr,
|
|
||||||
&Console_Port_Data[minor],
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ns16550_init(minor);
|
|
||||||
|
|
||||||
Console_Port_Data[minor].bActive = FALSE;
|
|
||||||
|
|
||||||
IrqData.name = (rtems_irq_number)(Console_Port_Tbl[minor].ulIntVector );
|
|
||||||
|
|
||||||
#ifdef BSP_SHARED_HANDLER_SUPPORT
|
|
||||||
if (!BSP_install_rtems_shared_irq_handler (&IrqData)) {
|
|
||||||
#else
|
|
||||||
if (!BSP_install_rtems_irq_handler(&IrqData)) {
|
|
||||||
#endif
|
|
||||||
printk("Error installing interrupt handler!\n");
|
|
||||||
rtems_fatal_error_occurred(1);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#elif defined BSP_FEATURE_IRQ_LEGACY
|
||||||
|
{
|
||||||
|
int rv = 0;
|
||||||
|
#ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
|
||||||
|
rtems_irq_connect_data cd = {
|
||||||
|
c->ulIntVector,
|
||||||
|
ns16550_isr,
|
||||||
|
(void *) minor
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
rv = BSP_install_rtems_shared_irq_handler( &cd);
|
||||||
|
#else
|
||||||
|
rtems_irq_connect_data cd = {
|
||||||
|
c->ulIntVector,
|
||||||
|
ns16550_isr,
|
||||||
|
(void *) minor
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
rv = BSP_install_rtems_irq_handler( &cd);
|
||||||
|
#endif
|
||||||
|
if (rv == 0) {
|
||||||
|
/* FIXME */
|
||||||
|
printk( "%s: Error: Install interrupt handler\n", __func__);
|
||||||
|
rtems_fatal_error_occurred( 0xdeadbeef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);
|
ns16550_enable_interrupts( minor, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ns16550_write_support_int
|
* ns16550_write_support_int
|
||||||
*
|
*
|
||||||
@@ -667,8 +651,8 @@ NS16550_STATIC int ns16550_write_support_int(
|
|||||||
}
|
}
|
||||||
|
|
||||||
rtems_interrupt_disable(Irql);
|
rtems_interrupt_disable(Irql);
|
||||||
if ( Console_Port_Data[minor].bActive == FALSE) {
|
if ( Console_Port_Data[minor].bActive == false) {
|
||||||
Console_Port_Data[minor].bActive = TRUE;
|
Console_Port_Data[minor].bActive = true;
|
||||||
ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);
|
ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);
|
||||||
}
|
}
|
||||||
(*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, *buf);
|
(*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, *buf);
|
||||||
|
|||||||
@@ -27,9 +27,7 @@ extern "C" {
|
|||||||
* will show up in the symbol table.
|
* will show up in the symbol table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NS16550_STATIC
|
#define NS16550_STATIC static
|
||||||
|
|
||||||
/* #define NS16550_STATIC static */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define serial port read registers structure.
|
* Define serial port read registers structure.
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#ifndef __LIBCHIP_SERIAL_h
|
#ifndef __LIBCHIP_SERIAL_h
|
||||||
#define __LIBCHIP_SERIAL_h
|
#define __LIBCHIP_SERIAL_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user