forked from Imagelibrary/rtems
2011-10-18 Jennifer Averett <Jennifer.Averett@OARcorp.com>
PR 1917/bsps * libchip/serial/mc68681.c, libchip/serial/ns16550.c, libchip/serial/serial.h, libchip/serial/z85c30.c: Modifications to add dynamic tables for libchip serial drivers.
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
2011-10-18 Jennifer Averett <Jennifer.Averett@OARcorp.com>
|
||||
|
||||
PR 1917/bsps
|
||||
* libchip/serial/mc68681.c, libchip/serial/ns16550.c,
|
||||
libchip/serial/serial.h, libchip/serial/z85c30.c: Modifications to
|
||||
add dynamic tables for libchip serial drivers.
|
||||
|
||||
2011-10-17 Ralf Corsépius <ralf.corsepius@rtems.org>
|
||||
|
||||
* libchip/rtc/icm7170.c (icm7170_get_time): Remove unused var setReg.
|
||||
|
||||
@@ -99,9 +99,9 @@ MC68681_STATIC int mc68681_set_attributes(
|
||||
setRegister_f setReg;
|
||||
rtems_interrupt_level Irql;
|
||||
|
||||
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Set the baud rate
|
||||
@@ -195,14 +195,14 @@ MC68681_STATIC void mc68681_initialize_context(
|
||||
unsigned int pMC68681;
|
||||
unsigned int pMC68681_port;
|
||||
|
||||
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
|
||||
pmc68681Context->mate = -1;
|
||||
|
||||
for (port=0 ; port<Console_Port_Count ; port++ ) {
|
||||
if ( Console_Port_Tbl[port].ulCtrlPort1 == pMC68681 &&
|
||||
Console_Port_Tbl[port].ulCtrlPort2 != pMC68681_port ) {
|
||||
if ( Console_Port_Tbl[port]->ulCtrlPort1 == pMC68681 &&
|
||||
Console_Port_Tbl[port]->ulCtrlPort2 != pMC68681_port ) {
|
||||
pmc68681Context->mate = port;
|
||||
pmc68681Context->imr = 0;
|
||||
break;
|
||||
@@ -230,9 +230,9 @@ MC68681_STATIC void mc68681_init(int minor)
|
||||
|
||||
mc68681_initialize_context( minor, pmc68681Context );
|
||||
|
||||
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Reset everything and leave this port disabled.
|
||||
@@ -282,10 +282,10 @@ MC68681_STATIC int mc68681_open(
|
||||
unsigned int status;
|
||||
|
||||
|
||||
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
vector = Console_Port_Tbl[minor].ulIntVector;
|
||||
pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
vector = Console_Port_Tbl[minor]->ulIntVector;
|
||||
|
||||
/* XXX default baud rate should be from configuration table */
|
||||
|
||||
@@ -332,9 +332,9 @@ MC68681_STATIC int mc68681_close(
|
||||
uint32_t pMC68681_port;
|
||||
setRegister_f setReg;
|
||||
|
||||
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Disable interrupts from this channel and then disable it totally.
|
||||
@@ -365,9 +365,9 @@ MC68681_STATIC void mc68681_write_polled(
|
||||
getRegister_f getReg;
|
||||
setRegister_f setReg;
|
||||
|
||||
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
getReg = Console_Port_Tbl[minor].getRegister;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* wait for transmitter holding register to be empty
|
||||
@@ -415,8 +415,8 @@ MC68681_STATIC rtems_isr mc68681_isr(
|
||||
int minor;
|
||||
|
||||
for(minor=0 ; minor<Console_Port_Count ; minor++) {
|
||||
if(Console_Port_Tbl[minor].ulIntVector == vector &&
|
||||
Console_Port_Tbl[minor].deviceType == SERIAL_MC68681 ) {
|
||||
if(Console_Port_Tbl[minor]->ulIntVector == vector &&
|
||||
Console_Port_Tbl[minor]->deviceType == SERIAL_MC68681 ) {
|
||||
mc68681_process(minor);
|
||||
}
|
||||
}
|
||||
@@ -435,7 +435,7 @@ MC68681_STATIC void mc68681_initialize_interrupts(int minor)
|
||||
|
||||
Console_Port_Data[minor].bActive = FALSE;
|
||||
|
||||
set_vector(mc68681_isr, Console_Port_Tbl[minor].ulIntVector, 1);
|
||||
set_vector(mc68681_isr, Console_Port_Tbl[minor]->ulIntVector, 1);
|
||||
|
||||
mc68681_enable_interrupts(minor,MC68681_IMR_ENABLE_ALL_EXCEPT_TX);
|
||||
}
|
||||
@@ -456,8 +456,8 @@ MC68681_STATIC ssize_t mc68681_write_support_int(
|
||||
uint32_t pMC68681_port;
|
||||
setRegister_f setReg;
|
||||
|
||||
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* We are using interrupt driven output and termios only sends us
|
||||
@@ -529,8 +529,8 @@ MC68681_STATIC int mc68681_inbyte_nonblocking_polled(
|
||||
unsigned char cChar;
|
||||
getRegister_f getReg;
|
||||
|
||||
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
getReg = Console_Port_Tbl[minor].getRegister;
|
||||
pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
||||
|
||||
ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);
|
||||
if(ucLineStatus & MC68681_RX_READY) {
|
||||
@@ -564,14 +564,14 @@ MC68681_STATIC int mc68681_baud_rate(
|
||||
acr_bit = 0;
|
||||
status = 0;
|
||||
|
||||
if (Console_Port_Tbl[minor].ulDataPort & MC68681_DATA_BAUD_RATE_SET_2)
|
||||
if (Console_Port_Tbl[minor]->ulDataPort & MC68681_DATA_BAUD_RATE_SET_2)
|
||||
{
|
||||
acr_bit = 1;
|
||||
}
|
||||
|
||||
is_extended = 0;
|
||||
|
||||
switch (Console_Port_Tbl[minor].ulDataPort & MC68681_XBRG_MASK) {
|
||||
switch (Console_Port_Tbl[minor]->ulDataPort & MC68681_XBRG_MASK) {
|
||||
case MC68681_XBRG_IGNORED:
|
||||
*command = 0x00;
|
||||
break;
|
||||
@@ -591,7 +591,7 @@ MC68681_STATIC int mc68681_baud_rate(
|
||||
baud_requested = rtems_termios_baud_to_index( baud_requested );
|
||||
|
||||
baud_tbl = (mc68681_baud_table_t *)
|
||||
((uintptr_t)Console_Port_Tbl[minor].ulClock);
|
||||
((uintptr_t)Console_Port_Tbl[minor]->ulClock);
|
||||
if (!baud_tbl)
|
||||
rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS);
|
||||
|
||||
@@ -630,10 +630,10 @@ MC68681_STATIC void mc68681_process(
|
||||
getRegister_f getReg;
|
||||
setRegister_f setReg;
|
||||
|
||||
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
getReg = Console_Port_Tbl[minor].getRegister;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/* Get ISR at the beginning of the IT routine */
|
||||
ucISRStatus = (*getReg)(pMC68681, MC68681_INTERRUPT_STATUS_REG);
|
||||
@@ -710,8 +710,8 @@ MC68681_STATIC unsigned int mc68681_build_imr(
|
||||
mc68681_context *pmc68681Context;
|
||||
mc68681_context *mateContext;
|
||||
|
||||
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
pMC68681_port = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
pmc68681Context = (mc68681_context *) Console_Port_Data[minor].pDeviceContext;
|
||||
mate = pmc68681Context->mate;
|
||||
|
||||
@@ -735,7 +735,7 @@ MC68681_STATIC unsigned int mc68681_build_imr(
|
||||
* Calculate this port's IMR mask and save it in the context area.
|
||||
*/
|
||||
|
||||
if ( Console_Port_Tbl[minor].pDeviceFns->deviceOutputUsesInterrupts )
|
||||
if ( Console_Port_Tbl[minor]->pDeviceFns->deviceOutputUsesInterrupts )
|
||||
mask = enable_flag;
|
||||
|
||||
pmc68681Context->imr = mask;
|
||||
@@ -764,8 +764,8 @@ MC68681_STATIC void mc68681_enable_interrupts(
|
||||
uint32_t pMC68681;
|
||||
setRegister_f setReg;
|
||||
|
||||
pMC68681 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pMC68681 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Enable interrupts on RX and TX -- not break
|
||||
|
||||
@@ -113,9 +113,9 @@ NS16550_STATIC void ns16550_init(int minor)
|
||||
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;
|
||||
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
|
||||
@@ -128,8 +128,8 @@ NS16550_STATIC void ns16550_init(int minor)
|
||||
/* Set the divisor latch and set the baud rate. */
|
||||
|
||||
ulBaudDivisor = NS16550_Baud(
|
||||
(uint32_t) Console_Port_Tbl[minor].ulClock,
|
||||
(uint32_t) ((uintptr_t)Console_Port_Tbl[minor].pDeviceParams)
|
||||
(uint32_t) Console_Port_Tbl[minor]->ulClock,
|
||||
(uint32_t) ((uintptr_t)Console_Port_Tbl[minor]->pDeviceParams)
|
||||
);
|
||||
ucDataByte = SP_LINE_DLAB;
|
||||
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
|
||||
@@ -172,7 +172,7 @@ NS16550_STATIC int ns16550_open(
|
||||
{
|
||||
rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
|
||||
struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
|
||||
console_tbl *c = &Console_Port_Tbl [minor];
|
||||
console_tbl *c = Console_Port_Tbl [minor];
|
||||
console_data *d = &Console_Port_Data [minor];
|
||||
|
||||
d->termios_data = tty;
|
||||
@@ -226,7 +226,7 @@ NS16550_STATIC int ns16550_close(
|
||||
*/
|
||||
NS16550_STATIC void ns16550_write_polled(int minor, char out)
|
||||
{
|
||||
console_tbl *c = &Console_Port_Tbl [minor];
|
||||
console_tbl *c = Console_Port_Tbl [minor];
|
||||
uintptr_t port = c->ulCtrlPort1;
|
||||
getRegister_f get = c->getRegister;
|
||||
setRegister_f set = c->setRegister;
|
||||
@@ -283,8 +283,8 @@ NS16550_STATIC int ns16550_assert_RTS(int minor)
|
||||
|
||||
pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
|
||||
|
||||
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Assert RTS
|
||||
@@ -309,8 +309,8 @@ NS16550_STATIC int ns16550_negate_RTS(int minor)
|
||||
|
||||
pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
|
||||
|
||||
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Negate RTS
|
||||
@@ -340,8 +340,8 @@ NS16550_STATIC int ns16550_assert_DTR(int minor)
|
||||
|
||||
pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
|
||||
|
||||
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Assert DTR
|
||||
@@ -366,8 +366,8 @@ NS16550_STATIC int ns16550_negate_DTR(int minor)
|
||||
|
||||
pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
|
||||
|
||||
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Negate DTR
|
||||
@@ -399,9 +399,9 @@ NS16550_STATIC int ns16550_set_attributes(
|
||||
getRegister_f getReg;
|
||||
uint32_t Irql;
|
||||
|
||||
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
getReg = Console_Port_Tbl[minor].getRegister;
|
||||
pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
||||
|
||||
/*
|
||||
* Calculate the baud rate divisor
|
||||
@@ -412,7 +412,7 @@ NS16550_STATIC int ns16550_set_attributes(
|
||||
baud_requested = B9600; /* default to 9600 baud */
|
||||
|
||||
ulBaudDivisor = NS16550_Baud(
|
||||
(uint32_t) Console_Port_Tbl[minor].ulClock,
|
||||
(uint32_t) Console_Port_Tbl[minor]->ulClock,
|
||||
rtems_termios_baud_to_number(baud_requested)
|
||||
);
|
||||
|
||||
@@ -485,7 +485,7 @@ NS16550_STATIC int ns16550_set_attributes(
|
||||
*/
|
||||
NS16550_STATIC void ns16550_process( int minor)
|
||||
{
|
||||
console_tbl *c = &Console_Port_Tbl [minor];
|
||||
console_tbl *c = Console_Port_Tbl [minor];
|
||||
console_data *d = &Console_Port_Data [minor];
|
||||
ns16550_context *ctx = d->pDeviceContext;
|
||||
uint32_t port = c->ulCtrlPort1;
|
||||
@@ -544,7 +544,7 @@ NS16550_STATIC ssize_t ns16550_write_support_int(
|
||||
size_t len
|
||||
)
|
||||
{
|
||||
console_tbl *c = &Console_Port_Tbl [minor];
|
||||
console_tbl *c = Console_Port_Tbl [minor];
|
||||
console_data *d = &Console_Port_Data [minor];
|
||||
ns16550_context *ctx = d->pDeviceContext;
|
||||
uint32_t port = c->ulCtrlPort1;
|
||||
@@ -578,8 +578,8 @@ NS16550_STATIC void ns16550_enable_interrupts(
|
||||
uint32_t pNS16550;
|
||||
setRegister_f setReg;
|
||||
|
||||
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
(*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask);
|
||||
}
|
||||
@@ -736,8 +736,8 @@ NS16550_STATIC int ns16550_inbyte_nonblocking_polled(
|
||||
char cChar;
|
||||
getRegister_f getReg;
|
||||
|
||||
pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
getReg = Console_Port_Tbl[minor].getRegister;
|
||||
pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
||||
|
||||
ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
|
||||
if(ucLineStatus & SP_LSR_RDY) {
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief The generic libchip serial driver interface
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file contains the TTY driver table definition
|
||||
*
|
||||
@@ -28,11 +35,46 @@ extern "C" {
|
||||
* Types for get and set register routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef getRegister_f
|
||||
*
|
||||
* This type function provides a hook for the bsp specific method
|
||||
* that gets register data from the given port and register.
|
||||
*/
|
||||
typedef uint8_t (*getRegister_f)(uintptr_t port, uint8_t reg);
|
||||
|
||||
/**
|
||||
* @typedef setData_f
|
||||
*
|
||||
* This type function provides a hook for the bsp specific method
|
||||
* that sets register data from the given port and register to the
|
||||
* given value.
|
||||
*/
|
||||
typedef void (*setRegister_f)(uintptr_t port, uint8_t reg, uint8_t value);
|
||||
|
||||
/**
|
||||
* @typedef getData_f
|
||||
*
|
||||
* This type function provides a hook for the bsp specific method
|
||||
* that gets data from the specified port.
|
||||
*/
|
||||
typedef uint8_t (*getData_f)(uintptr_t port);
|
||||
|
||||
/**
|
||||
* @typedef setData_f
|
||||
*
|
||||
* This type function provides a hook for the bsp specific method
|
||||
* that writes value to the specified port.
|
||||
*/
|
||||
typedef void (*setData_f)(uintptr_t port, uint8_t value);
|
||||
|
||||
/**
|
||||
* @typedef _console_fns
|
||||
*
|
||||
* This type definition provides a structure of functions each
|
||||
* methood provides an interfce to the serial por to do a specific
|
||||
* function.
|
||||
*/
|
||||
typedef struct _console_fns {
|
||||
bool (*deviceProbe)(int minor);
|
||||
int (*deviceFirstOpen)(int major, int minor, void *arg);
|
||||
@@ -45,11 +87,22 @@ typedef struct _console_fns {
|
||||
bool deviceOutputUsesInterrupts;
|
||||
} console_fns;
|
||||
|
||||
/**
|
||||
* @typedef _console_flow
|
||||
*
|
||||
* This type definition provides a structure of functions
|
||||
* that provide flow control for the transmit buffer.
|
||||
*/
|
||||
typedef struct _console_flow {
|
||||
int (*deviceStopRemoteTx)(int minor);
|
||||
int (*deviceStartRemoteTx)(int minor);
|
||||
} console_flow;
|
||||
|
||||
|
||||
/**
|
||||
* This type defination provides an enumerated type of all
|
||||
* supported libchip console drivers.
|
||||
*/
|
||||
typedef enum {
|
||||
SERIAL_MC68681, /* Motorola MC68681 or Exar 88681 */
|
||||
SERIAL_NS16550, /* National Semiconductor NS16550 */
|
||||
@@ -57,100 +110,114 @@ typedef enum {
|
||||
SERIAL_CUSTOM /* BSP specific driver */
|
||||
} console_devs;
|
||||
|
||||
/*
|
||||
* Each field is interpreted thus:
|
||||
*
|
||||
* sDeviceName This is the name of the device.
|
||||
*
|
||||
* deviceType This indicates the chip type. It is especially important when
|
||||
* multiple devices share the same interrupt vector and must be
|
||||
* distinguished.
|
||||
*
|
||||
* pDeviceFns This is a pointer to the set of driver routines to use.
|
||||
*
|
||||
* pDeviceFlow This is a pointer to the set of flow control routines to
|
||||
* use. Serial device drivers will typically supply RTSCTS
|
||||
* and DTRCTS handshake routines for DCE to DCE communication,
|
||||
* however for DCE to DTE communication, no such routines
|
||||
* should be necessary as RTS will be driven automatically
|
||||
* when the transmitter is active.
|
||||
*
|
||||
* ulMargin The high water mark in the input buffer is set to the buffer
|
||||
* size less ulMargin. Once this level is reached, the driver's
|
||||
* flow control routine used to stop the remote transmitter will
|
||||
* be called. This figure should be greater than or equal to
|
||||
* the number of stages of FIFO between the transmitter and
|
||||
* receiver.
|
||||
*
|
||||
* NOTE: At the current time, this parameter is hard coded
|
||||
* in termios and this number is ignored.
|
||||
*
|
||||
* ulHysteresis After the high water mark specified by ulMargin has been
|
||||
* reached, the driver's routine to re-start the remote
|
||||
* transmitter will be called once the level in the input
|
||||
* buffer has fallen by ulHysteresis bytes.
|
||||
*
|
||||
* NOTE: At the current time, this parameter is hard coded
|
||||
* in termios and this number is ignored.
|
||||
*
|
||||
* pDeviceParams This contains either device specific data or a pointer to a
|
||||
* device specific structure containing additional information
|
||||
* not provided in this table.
|
||||
*
|
||||
* ulCtrlPort1 This is the primary control port number for the device. This
|
||||
* may be used to specify different instances of the same device
|
||||
* type.
|
||||
*
|
||||
* ulCtrlPort2 This is the secondary control port number, of use when a given
|
||||
* device has more than one available channel.
|
||||
*
|
||||
* ulDataPort This is the port number for the data port of the device
|
||||
*
|
||||
* getRegister This is the routine used to read register values.
|
||||
*
|
||||
* setRegister This is the routine used to write register values.
|
||||
*
|
||||
* getData This is the routine used to read the data register (RX).
|
||||
*
|
||||
* setData This is the routine used to write the data register (TX).
|
||||
*
|
||||
* ulClock This is the baud rate clock speed.
|
||||
*
|
||||
* ulIntVector This encodes the interrupt vector of the device.
|
||||
/**
|
||||
* This type defination provides an structure that is used to
|
||||
* uniquely identify a specific serial port.
|
||||
*/
|
||||
|
||||
typedef struct _console_tbl {
|
||||
/** This is the name of the device. */
|
||||
char *sDeviceName;
|
||||
/** This indicates the chip type. It is especially important when
|
||||
* multiple devices share the same interrupt vector and must be
|
||||
* distinguished.
|
||||
*/
|
||||
console_devs deviceType;
|
||||
/** pDeviceFns This is a pointer to the set of driver routines to use. */
|
||||
console_fns *pDeviceFns;
|
||||
/** This value is passed to the serial device driver for use. In termios
|
||||
* itself the number is ignored.
|
||||
*/
|
||||
bool (*deviceProbe)(int minor);
|
||||
/** This is a pointer to the set of flow control routines to
|
||||
* use. Serial device drivers will typically supply RTSCTS
|
||||
* and DTRCTS handshake routines for DCE to DCE communication,
|
||||
* however for DCE to DTE communication, no such routines
|
||||
* should be necessary as RTS will be driven automatically
|
||||
* when the transmitter is active.
|
||||
*/
|
||||
console_flow *pDeviceFlow;
|
||||
/** The high water mark in the input buffer is set to the buffer
|
||||
* size less ulMargin. Once this level is reached, the driver's
|
||||
* flow control routine used to stop the remote transmitter will
|
||||
* be called. This figure should be greater than or equal to
|
||||
* the number of stages of FIFO between the transmitter and
|
||||
* receiver.
|
||||
*
|
||||
* @note At the current time, this parameter is hard coded
|
||||
* in termios and this number is ignored.
|
||||
*/
|
||||
uint32_t ulMargin;
|
||||
/** After the high water mark specified by ulMargin has been
|
||||
* reached, the driver's routine to re-start the remote
|
||||
* transmitter will be called once the level in the input
|
||||
* buffer has fallen by ulHysteresis bytes.
|
||||
*
|
||||
* @note At the current time, this parameter is hard coded in termios.
|
||||
*/
|
||||
uint32_t ulHysteresis;
|
||||
/** This contains either device specific data or a pointer to a
|
||||
* device specific structure containing additional information
|
||||
* not provided in this table.
|
||||
*/
|
||||
void *pDeviceParams;
|
||||
/** This is the primary control port number for the device. This
|
||||
* may be used to specify different instances of the same device type.
|
||||
*/
|
||||
uint32_t ulCtrlPort1;
|
||||
/** This is the secondary control port number, of use when a given
|
||||
* device has more than one available channel.
|
||||
*/
|
||||
uint32_t ulCtrlPort2;
|
||||
/** This is the port number for the data port of the device */
|
||||
uint32_t ulDataPort;
|
||||
/** This is the routine used to read register values. */
|
||||
getRegister_f getRegister;
|
||||
/** This is the routine used to write register values. */
|
||||
setRegister_f setRegister;
|
||||
/** This is the routine used to read the data register (RX). */
|
||||
getData_f getData;
|
||||
/* This is the routine used to write the data register (TX). */
|
||||
setData_f setData;
|
||||
/** This is the baud rate clock speed.*/
|
||||
uint32_t ulClock;
|
||||
/** This encodes the interrupt vector of the device. */
|
||||
unsigned int ulIntVector;
|
||||
} console_tbl;
|
||||
|
||||
/**
|
||||
* This type defination provides data for the console port.
|
||||
*/
|
||||
typedef struct _console_data {
|
||||
void *termios_data;
|
||||
volatile bool bActive;
|
||||
/*
|
||||
* This field may be used for any purpose required by the driver
|
||||
*/
|
||||
/** This field may be used for any purpose required by the driver */
|
||||
void *pDeviceContext;
|
||||
} console_data;
|
||||
|
||||
extern console_tbl Console_Port_Tbl[];
|
||||
extern console_data Console_Port_Data[];
|
||||
extern unsigned long Console_Port_Count;
|
||||
/**
|
||||
* This is a dynamically sized set of tables containing the serial
|
||||
* port information.
|
||||
*/
|
||||
extern console_tbl **Console_Port_Tbl;
|
||||
/**
|
||||
* This is the number of serial ports defined in the Console_Port_Tbl.
|
||||
*/
|
||||
extern unsigned long Console_Port_Count;
|
||||
|
||||
/**
|
||||
* The statically configured serial port information tables which
|
||||
* are used to initially populate the dynamic tables.
|
||||
*/
|
||||
extern console_tbl Console_Configuration_Ports[];
|
||||
/**
|
||||
* The number of serial ports defined in Console_Configuration_Ports
|
||||
* */
|
||||
extern unsigned long Console_Configuration_Count;
|
||||
|
||||
/**
|
||||
* This is an array of per port information.
|
||||
*/
|
||||
extern console_data *Console_Port_Data;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -96,8 +96,8 @@ Z85C30_STATIC void z85c30_initialize_port(
|
||||
uintptr_t ulBaudDivisor;
|
||||
setRegister_f setReg;
|
||||
|
||||
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Using register 4
|
||||
@@ -137,8 +137,8 @@ Z85C30_STATIC void z85c30_initialize_port(
|
||||
);
|
||||
|
||||
ulBaudDivisor = Z85C30_Baud(
|
||||
(uint32_t) Console_Port_Tbl[minor].ulClock,
|
||||
(uint32_t) ((uintptr_t)Console_Port_Tbl[minor].pDeviceParams)
|
||||
(uint32_t) Console_Port_Tbl[minor]->ulClock,
|
||||
(uint32_t) ((uintptr_t)Console_Port_Tbl[minor]->pDeviceParams)
|
||||
);
|
||||
|
||||
/*
|
||||
@@ -219,7 +219,7 @@ Z85C30_STATIC int z85c30_open(
|
||||
* Assert DTR
|
||||
*/
|
||||
|
||||
if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_DTRCTS) {
|
||||
if (Console_Port_Tbl[minor]->pDeviceFlow !=&z85c30_flow_DTRCTS) {
|
||||
z85c30_assert_DTR(minor);
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ Z85C30_STATIC int z85c30_close(
|
||||
* Negate DTR
|
||||
*/
|
||||
|
||||
if (Console_Port_Tbl[minor].pDeviceFlow !=&z85c30_flow_DTRCTS) {
|
||||
if (Console_Port_Tbl[minor]->pDeviceFlow !=&z85c30_flow_DTRCTS) {
|
||||
z85c30_negate_DTR(minor);
|
||||
}
|
||||
|
||||
@@ -258,8 +258,9 @@ Z85C30_STATIC void z85c30_init(int minor)
|
||||
setRegister_f setReg;
|
||||
getRegister_f getReg;
|
||||
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
getReg = Console_Port_Tbl[minor].getRegister;
|
||||
ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
||||
|
||||
pz85c30Context = (z85c30_context *)malloc(sizeof(z85c30_context));
|
||||
|
||||
@@ -267,8 +268,8 @@ Z85C30_STATIC void z85c30_init(int minor)
|
||||
|
||||
pz85c30Context->ucModemCtrl = SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN;
|
||||
|
||||
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
if ( ulCtrlPort == Console_Port_Tbl[minor].ulCtrlPort2 ) {
|
||||
ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
if ( ulCtrlPort == Console_Port_Tbl[minor]->ulCtrlPort2 ) {
|
||||
/*
|
||||
* This is channel A
|
||||
*/
|
||||
@@ -306,7 +307,7 @@ Z85C30_STATIC int z85c30_assert_RTS(int minor)
|
||||
z85c30_context *pz85c30Context;
|
||||
setRegister_f setReg;
|
||||
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
|
||||
|
||||
@@ -317,7 +318,7 @@ Z85C30_STATIC int z85c30_assert_RTS(int minor)
|
||||
rtems_interrupt_disable(Irql);
|
||||
pz85c30Context->ucModemCtrl|=SCC_WR5_RTS;
|
||||
(*setReg)(
|
||||
Console_Port_Tbl[minor].ulCtrlPort1,
|
||||
Console_Port_Tbl[minor]->ulCtrlPort1,
|
||||
SCC_WR0_SEL_WR5,
|
||||
pz85c30Context->ucModemCtrl
|
||||
);
|
||||
@@ -335,7 +336,7 @@ Z85C30_STATIC int z85c30_negate_RTS(int minor)
|
||||
z85c30_context *pz85c30Context;
|
||||
setRegister_f setReg;
|
||||
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
|
||||
|
||||
@@ -346,7 +347,7 @@ Z85C30_STATIC int z85c30_negate_RTS(int minor)
|
||||
rtems_interrupt_disable(Irql);
|
||||
pz85c30Context->ucModemCtrl&=~SCC_WR5_RTS;
|
||||
(*setReg)(
|
||||
Console_Port_Tbl[minor].ulCtrlPort1,
|
||||
Console_Port_Tbl[minor]->ulCtrlPort1,
|
||||
SCC_WR0_SEL_WR5,
|
||||
pz85c30Context->ucModemCtrl
|
||||
);
|
||||
@@ -369,7 +370,7 @@ Z85C30_STATIC int z85c30_assert_DTR(int minor)
|
||||
z85c30_context *pz85c30Context;
|
||||
setRegister_f setReg;
|
||||
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
|
||||
|
||||
@@ -380,7 +381,7 @@ Z85C30_STATIC int z85c30_assert_DTR(int minor)
|
||||
rtems_interrupt_disable(Irql);
|
||||
pz85c30Context->ucModemCtrl|=SCC_WR5_DTR;
|
||||
(*setReg)(
|
||||
Console_Port_Tbl[minor].ulCtrlPort1,
|
||||
Console_Port_Tbl[minor]->ulCtrlPort1,
|
||||
SCC_WR0_SEL_WR5,
|
||||
pz85c30Context->ucModemCtrl
|
||||
);
|
||||
@@ -398,7 +399,7 @@ Z85C30_STATIC int z85c30_negate_DTR(int minor)
|
||||
z85c30_context *pz85c30Context;
|
||||
setRegister_f setReg;
|
||||
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
|
||||
|
||||
@@ -409,7 +410,7 @@ Z85C30_STATIC int z85c30_negate_DTR(int minor)
|
||||
rtems_interrupt_disable(Irql);
|
||||
pz85c30Context->ucModemCtrl&=~SCC_WR5_DTR;
|
||||
(*setReg)(
|
||||
Console_Port_Tbl[minor].ulCtrlPort1,
|
||||
Console_Port_Tbl[minor]->ulCtrlPort1,
|
||||
SCC_WR0_SEL_WR5,
|
||||
pz85c30Context->ucModemCtrl
|
||||
);
|
||||
@@ -438,8 +439,8 @@ Z85C30_STATIC int z85c30_set_attributes(
|
||||
setRegister_f setReg;
|
||||
rtems_interrupt_level Irql;
|
||||
|
||||
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Calculate the baud rate divisor
|
||||
@@ -450,7 +451,7 @@ Z85C30_STATIC int z85c30_set_attributes(
|
||||
baud_requested = B9600; /* default to 9600 baud */
|
||||
|
||||
ulBaudDivisor = Z85C30_Baud(
|
||||
(uint32_t) Console_Port_Tbl[minor].ulClock,
|
||||
(uint32_t) Console_Port_Tbl[minor]->ulClock,
|
||||
(uint32_t) rtems_termios_baud_to_number( baud_requested )
|
||||
);
|
||||
|
||||
@@ -540,9 +541,9 @@ Z85C30_STATIC void z85c30_process(
|
||||
setRegister_f setReg;
|
||||
getRegister_f getReg;
|
||||
|
||||
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
getReg = Console_Port_Tbl[minor].getRegister;
|
||||
ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
||||
|
||||
/*
|
||||
* Deal with any received characters
|
||||
@@ -604,7 +605,7 @@ Z85C30_STATIC void z85c30_process(
|
||||
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 != &z85c30_flow_RTSCTS) {
|
||||
if (Console_Port_Tbl[minor]->pDeviceFlow != &z85c30_flow_RTSCTS) {
|
||||
z85c30_negate_RTS(minor);
|
||||
}
|
||||
Console_Port_Data[minor].bActive = FALSE;
|
||||
@@ -646,10 +647,10 @@ Z85C30_STATIC rtems_isr z85c30_isr(
|
||||
getRegister_f getReg;
|
||||
|
||||
for (minor=0;minor<Console_Port_Count;minor++) {
|
||||
if(Console_Port_Tbl[minor].ulIntVector == vector &&
|
||||
Console_Port_Tbl[minor].deviceType == SERIAL_Z85C30 ) {
|
||||
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
getReg = Console_Port_Tbl[minor].getRegister;
|
||||
if(Console_Port_Tbl[minor]->ulIntVector == vector &&
|
||||
Console_Port_Tbl[minor]->deviceType == SERIAL_Z85C30 ) {
|
||||
ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
||||
do {
|
||||
ucIntPend = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD3);
|
||||
|
||||
@@ -657,7 +658,7 @@ Z85C30_STATIC rtems_isr z85c30_isr(
|
||||
* If this is channel A select channel A status
|
||||
*/
|
||||
|
||||
if (ulCtrlPort == Console_Port_Tbl[minor].ulCtrlPort1) {
|
||||
if (ulCtrlPort == Console_Port_Tbl[minor]->ulCtrlPort1) {
|
||||
ucIntPendPort = ucIntPend >> 3;
|
||||
ucIntPendPort &= 7;
|
||||
} else {
|
||||
@@ -686,8 +687,8 @@ Z85C30_STATIC void z85c30_enable_interrupts(
|
||||
uint32_t ulCtrlPort;
|
||||
setRegister_f setReg;
|
||||
|
||||
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
(*setReg)(ulCtrlPort, SCC_WR0_SEL_WR1, interrupt_mask);
|
||||
}
|
||||
@@ -706,9 +707,9 @@ Z85C30_STATIC void z85c30_initialize_interrupts(
|
||||
uint32_t ulCtrlPort2;
|
||||
setRegister_f setReg;
|
||||
|
||||
ulCtrlPort1 = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
ulCtrlPort2 = Console_Port_Tbl[minor].ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
ulCtrlPort1 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
ulCtrlPort2 = Console_Port_Tbl[minor]->ulCtrlPort2;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
|
||||
z85c30_init(minor);
|
||||
@@ -717,11 +718,11 @@ Z85C30_STATIC void z85c30_initialize_interrupts(
|
||||
|
||||
z85c30_initialize_port( minor );
|
||||
|
||||
if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
|
||||
if (Console_Port_Tbl[minor]->pDeviceFlow != &z85c30_flow_RTSCTS) {
|
||||
z85c30_negate_RTS(minor);
|
||||
}
|
||||
|
||||
set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);
|
||||
set_vector(z85c30_isr, Console_Port_Tbl[minor]->ulIntVector, 1);
|
||||
|
||||
z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
|
||||
|
||||
@@ -751,8 +752,8 @@ Z85C30_STATIC ssize_t z85c30_write_support_int(
|
||||
uint32_t ulCtrlPort;
|
||||
setRegister_f setReg;
|
||||
|
||||
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* We are using interrupt driven output and termios only sends us
|
||||
@@ -766,7 +767,7 @@ Z85C30_STATIC ssize_t z85c30_write_support_int(
|
||||
* Put the character out and enable interrupts if necessary.
|
||||
*/
|
||||
|
||||
if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
|
||||
if (Console_Port_Tbl[minor]->pDeviceFlow != &z85c30_flow_RTSCTS) {
|
||||
z85c30_assert_RTS(minor);
|
||||
}
|
||||
rtems_interrupt_disable(Irql);
|
||||
@@ -794,8 +795,8 @@ Z85C30_STATIC int z85c30_inbyte_nonblocking_polled(
|
||||
uint32_t ulCtrlPort;
|
||||
getRegister_f getReg;
|
||||
|
||||
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
getReg = Console_Port_Tbl[minor].getRegister;
|
||||
ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
||||
|
||||
/*
|
||||
* return -1 if a character is not available.
|
||||
@@ -856,9 +857,9 @@ Z85C30_STATIC void z85c30_write_polled(
|
||||
getRegister_f getReg;
|
||||
setRegister_f setReg;
|
||||
|
||||
ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
|
||||
getReg = Console_Port_Tbl[minor].getRegister;
|
||||
setReg = Console_Port_Tbl[minor].setRegister;
|
||||
ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
|
||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
||||
|
||||
/*
|
||||
* Wait for the Transmit buffer to indicate that it is empty.
|
||||
|
||||
Reference in New Issue
Block a user