// SPDX-License-Identifier: GPL-2.0+ /* ** mux.c: ** serial driver for the Mux console found in some PA-RISC servers. ** ** (c) Copyright 2002 Ryan Bradetich ** (c) Copyright 2002 Hewlett-Packard Company ** ** This Driver currently only supports the console (port 0) on the MUX. ** Additional work will be needed on this driver to enable the full ** functionality of the MUX. **
*/
/** * get_mux_port_count - Get the number of available ports on the Mux. * @dev: The parisc device. * * This function is used to determine the number of ports the Mux * supports. The IODC data reports the number of ports the Mux * can support, but there are cases where not all the Mux ports * are connected. This function can override the IODC and * return the true port count.
*/ staticint __init get_mux_port_count(struct parisc_device *dev)
{ int status;
u8 iodc_data[32]; unsignedlong bytecnt;
/* If this is the built-in Mux for the K-Class (Eole CAP/MUX), * we only need to allocate resources for 1 port since the * other 7 ports are not connected.
*/ if(dev->id.hversion == 0x15) return 1;
status = pdc_iodc_read(&bytecnt, dev->hpa.start, 0, iodc_data, 32);
BUG_ON(status != PDC_OK);
/* Return the number of ports specified in the iodc data. */ return ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8;
}
/** * mux_tx_empty - Check if the transmitter fifo is empty. * @port: Ptr to the uart_port. * * This function test if the transmitter fifo for the port * described by 'port' is empty. If it is empty, this function * should return TIOCSER_TEMT, otherwise return 0.
*/ staticunsignedint mux_tx_empty(struct uart_port *port)
{ return UART_GET_FIFO_CNT(port) ? 0 : TIOCSER_TEMT;
}
/** * mux_set_mctrl - Set the current state of the modem control inputs. * @ports: Ptr to the uart_port. * @mctrl: Modem control bits. * * The Serial MUX does not support CTS, DCD or DSR so this function * is ignored.
*/ staticvoid mux_set_mctrl(struct uart_port *port, unsignedint mctrl)
{
}
/** * mux_get_mctrl - Returns the current state of modem control inputs. * @port: Ptr to the uart_port. * * The Serial MUX does not support CTS, DCD or DSR so these lines are * treated as permanently active.
*/ staticunsignedint mux_get_mctrl(struct uart_port *port)
{ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
}
/** * mux_stop_tx - Stop transmitting characters. * @port: Ptr to the uart_port. * * The Serial MUX does not support this function.
*/ staticvoid mux_stop_tx(struct uart_port *port)
{
}
/** * mux_start_tx - Start transmitting characters. * @port: Ptr to the uart_port. * * The Serial Mux does not support this function.
*/ staticvoid mux_start_tx(struct uart_port *port)
{
}
/** * mux_stop_rx - Stop receiving characters. * @port: Ptr to the uart_port. * * The Serial Mux does not support this function.
*/ staticvoid mux_stop_rx(struct uart_port *port)
{
}
/** * mux_break_ctl - Control the transmitssion of a break signal. * @port: Ptr to the uart_port. * @break_state: Raise/Lower the break signal. * * The Serial Mux does not support this function.
*/ staticvoid mux_break_ctl(struct uart_port *port, int break_state)
{
}
staticvoid mux_tx_done(struct uart_port *port)
{ /* FIXME js: really needs to wait? */ while (UART_GET_FIFO_CNT(port))
udelay(1);
}
/** * mux_write - Write chars to the mux fifo. * @port: Ptr to the uart_port. * * This function writes all the data from the uart buffer to * the mux fifo.
*/ staticvoid mux_write(struct uart_port *port)
{
u8 ch;
/** * mux_read - Read chars from the mux fifo. * @port: Ptr to the uart_port. * * This reads all available data from the mux's fifo and pushes * the data to the tty layer.
*/ staticvoid mux_read(struct uart_port *port)
{ struct tty_port *tport = &port->state->port; int data;
__u32 start_count = port->icount.rx;
while(1) {
data = __raw_readl(port->membase + IO_DATA_REG_OFFSET);
if (MUX_STATUS(data)) continue;
if (MUX_EOFIFO(data)) break;
port->icount.rx++;
if (MUX_BREAK(data)) {
port->icount.brk++; if(uart_handle_break(port)) continue;
}
if (uart_handle_sysrq_char(port, data & 0xffu)) continue;
tty_insert_flip_char(tport, data & 0xFF, TTY_NORMAL);
}
if (start_count != port->icount.rx)
tty_flip_buffer_push(tport);
}
/** * mux_startup - Initialize the port. * @port: Ptr to the uart_port. * * Grab any resources needed for this port and start the * mux timer.
*/ staticint mux_startup(struct uart_port *port)
{
mux_ports[port->line].enabled = 1; return 0;
}
/** * mux_shutdown - Disable the port. * @port: Ptr to the uart_port. * * Release any resources needed for the port.
*/ staticvoid mux_shutdown(struct uart_port *port)
{
mux_ports[port->line].enabled = 0;
}
/** * mux_set_termios - Chane port parameters. * @port: Ptr to the uart_port. * @termios: new termios settings. * @old: old termios settings. * * The Serial Mux does not support this function.
*/ staticvoid
mux_set_termios(struct uart_port *port, struct ktermios *termios, conststruct ktermios *old)
{
}
/** * mux_type - Describe the port. * @port: Ptr to the uart_port. * * Return a pointer to a string constant describing the * specified port.
*/ staticconstchar *mux_type(struct uart_port *port)
{ return"Mux";
}
/** * mux_release_port - Release memory and IO regions. * @port: Ptr to the uart_port. * * Release any memory and IO region resources currently in use by * the port.
*/ staticvoid mux_release_port(struct uart_port *port)
{
}
/** * mux_request_port - Request memory and IO regions. * @port: Ptr to the uart_port. * * Request any memory and IO region resources required by the port. * If any fail, no resources should be registered when this function * returns, and it should return -EBUSY on failure.
*/ staticint mux_request_port(struct uart_port *port)
{ return 0;
}
/** * mux_config_port - Perform port autoconfiguration. * @port: Ptr to the uart_port. * @type: Bitmask of required configurations. * * Perform any autoconfiguration steps for the port. This function is * called if the UPF_BOOT_AUTOCONF flag is specified for the port. * [Note: This is required for now because of a bug in the Serial core. * rmk has already submitted a patch to linus, should be available for * 2.5.47.]
*/ staticvoid mux_config_port(struct uart_port *port, int type)
{
port->type = PORT_MUX;
}
/** * mux_verify_port - Verify the port information. * @port: Ptr to the uart_port. * @ser: Ptr to the serial information. * * Verify the new serial port information contained within serinfo is * suitable for this port type.
*/ staticint mux_verify_port(struct uart_port *port, struct serial_struct *ser)
{ if(port->membase == NULL) return -EINVAL;
return 0;
}
/** * mux_drv_poll - Mux poll function. * @unused: Unused variable * * This function periodically polls the Serial MUX to check for new data.
*/ staticvoid mux_poll(struct timer_list *unused)
{ int i;
for(i = 0; i < port_cnt; ++i) { if(!mux_ports[i].enabled) continue;
/** * mux_probe - Determine if the Serial Mux should claim this device. * @dev: The parisc device. * * Deterimine if the Serial Mux should claim this chip (return 0) * or not (return 1).
*/ staticint __init mux_probe(struct parisc_device *dev)
{ int i, status;
status = uart_add_one_port(&mux_driver, port);
BUG_ON(status);
}
return 0;
}
staticvoid __exit mux_remove(struct parisc_device *dev)
{ int i, j; int port_count = (long)dev_get_drvdata(&dev->dev);
/* Find Port 0 for this card in the mux_ports list. */ for(i = 0; i < port_cnt; ++i) { if(mux_ports[i].port.mapbase == dev->hpa.start + MUX_OFFSET) break;
}
BUG_ON(i + port_count > port_cnt);
/* Release the resources associated with each port on the device. */ for(j = 0; j < port_count; ++j, ++i) { struct uart_port *port = &mux_ports[i].port;
/* Hack. This idea was taken from the 8250_gsc.c on how to properly order * the serial port detection in the proper order. The idea is we always * want the builtin mux to be detected before addin mux cards, so we * specifically probe for the builtin mux cards first. * * This table only contains the parisc_device_id of known builtin mux * devices. All other mux cards will be detected by the generic mux_tbl.
*/ staticconststruct parisc_device_id builtin_mux_tbl[] __initconst = {
{ HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x15, 0x0000D }, /* All K-class */
{ HPHW_A_DIRECT, HVERSION_REV_ANY_ID, 0x44, 0x0000D }, /* E35, E45, and E55 */
{ 0, }
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.