/* Reading and writing Zilog8530 registers. The delays are to make this *driverworkontheIP22whichneedsasettlingdelayaftereachchip *registeraccess,othermachineshandlethisinhardwareviaauxiliary *flip-flopswhichimplementthesettletimewedoinsoftware. * *TheportlockmustbeheldandlocalIRQsmustbedisabled *when{read,write}_zsregisinvoked.
*/ staticunsignedchar read_zsreg(struct zilog_channel *channel, unsignedchar reg)
{ unsignedchar retval;
/* This function must only be called when the TX is not busy. The UART *portlockmustbeheldandlocalinterruptsdisabled.
*/ staticvoid __load_zsregs(struct zilog_channel *channel, unsignedchar *regs)
{ int i;
/* Let pending transmits finish. */ for (i = 0; i < 1000; i++) { unsignedchar stat = read_zsreg(channel, R1); if (stat & ALL_SNT) break;
udelay(100);
}
/* Don't mess with the interrupt vector (R2, unused by us) and *masterinterruptcontrol(R9).Wemakesurethisissetup *properlyatprobetimethennevertouchitagain.
*/
/* Handle the null char got when BREAK is removed. */ if (!ch)
r1 |= up->tty_break;
/* A real serial line, record the character and status. */
flag = TTY_NORMAL;
up->port.icount.rx++; if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | Rx_SYS | Rx_BRK)) {
up->tty_break = 0;
if (r1 & (Rx_SYS | Rx_BRK)) {
up->port.icount.brk++; if (r1 & Rx_SYS) continue;
r1 &= ~(PAR_ERR | CRC_ERR);
} elseif (r1 & PAR_ERR)
up->port.icount.parity++; elseif (r1 & CRC_ERR)
up->port.icount.frame++; if (r1 & Rx_OVR)
up->port.icount.overrun++;
r1 &= up->port.read_status_mask; if (r1 & Rx_BRK)
flag = TTY_BREAK; elseif (r1 & PAR_ERR)
flag = TTY_PARITY; elseif (r1 & CRC_ERR)
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch)) continue;
if (up->curregs[R15] & BRKIE) { if ((status & BRK_ABRT) && !(up->prev_status & BRK_ABRT)) { if (uart_handle_break(&up->port))
up->tty_break = Rx_SYS; else
up->tty_break = Rx_BRK;
}
}
if (ZS_WANTS_MODEM_STATUS(up)) { if (status & SYNC)
up->port.icount.dsr++;
/* The Zilog just gives us an interrupt when DCD/CTS/etc. change. *Butitdoesnottelluswhichbithaschanged,wehavetokeep *trackofthisourselves.
*/ if ((status ^ up->prev_status) ^ DCD)
uart_handle_dcd_change(&up->port,
(status & DCD)); if ((status ^ up->prev_status) ^ CTS)
uart_handle_cts_change(&up->port,
(status & CTS));
if (ZS_IS_CONS(up)) { unsignedchar status = readb(&channel->control);
ZSDELAY();
/* TX still busy? Just wait for the next TX done interrupt. * *Itcanoccurbecauseofhowwedoserialconsolewrites.Itwould *benicetotransmitconsolewritesjustlikewenormallywouldfor *aTTYline.(ie.bufferedandTXinterruptdriven).Thatisnot *easybecauseconsolewritescannotsleep.Onesolutionmightbe *topollonenoughport->xmitspacebecomingfree.-DaveM
*/ if (!(status & Tx_BUF_EMP)) return;
}
up->flags &= ~IP22ZILOG_FLAG_TX_ACTIVE;
if (ZS_REGS_HELD(up)) {
__load_zsregs(channel, up->curregs);
up->flags &= ~IP22ZILOG_FLAG_REGS_HELD;
}
if (ZS_TX_STOPPED(up)) {
up->flags &= ~IP22ZILOG_FLAG_TX_STOPPED; goto ack_tx_int;
}
if (up->port.x_char) {
up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;
writeb(up->port.x_char, &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
if (r3 & CHBRxIP)
push = ip22zilog_receive_chars(up, channel); if (r3 & CHBEXT)
ip22zilog_status_handle(up, channel); if (r3 & CHBTxIP)
ip22zilog_transmit_chars(up, channel);
}
uart_port_unlock(&up->port);
if (push)
tty_flip_buffer_push(&up->port.state->port);
return IRQ_HANDLED;
}
/* A convenient way to quickly get R0 status. The caller must _not_ hold the *portlock,itisacquiredhere.
*/ static __inline__ unsignedchar ip22zilog_read_channel_status(struct uart_port *port)
{ struct zilog_channel *channel; unsignedchar status;
channel = ZILOG_CHANNEL_FROM_PORT(port);
status = readb(&channel->control);
ZSDELAY();
return status;
}
/* The port lock is not held. */ staticunsignedint ip22zilog_tx_empty(struct uart_port *port)
{ unsignedlong flags; unsignedchar status; unsignedint ret;
uart_port_lock_irqsave(port, &flags);
status = ip22zilog_read_channel_status(port);
uart_port_unlock_irqrestore(port, flags);
if (status & Tx_BUF_EMP)
ret = TIOCSER_TEMT; else
ret = 0;
return ret;
}
/* The port lock is held and interrupts are disabled. */ staticunsignedint ip22zilog_get_mctrl(struct uart_port *port)
{ unsignedchar status; unsignedint ret;
status = ip22zilog_read_channel_status(port);
ret = 0; if (status & DCD)
ret |= TIOCM_CAR; if (status & SYNC)
ret |= TIOCM_DSR; if (status & CTS)
ret |= TIOCM_CTS;
return ret;
}
/* The port lock is held and interrupts are disabled. */ staticvoid ip22zilog_set_mctrl(struct uart_port *port, unsignedint mctrl)
{ struct uart_ip22zilog_port *up =
container_of(port, struct uart_ip22zilog_port, port); struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); unsignedchar set_bits, clear_bits;
/* NOTE: Not subject to 'transmitter active' rule. */
up->curregs[R5] |= set_bits;
up->curregs[R5] &= ~clear_bits;
write_zsreg(channel, R5, up->curregs[R5]);
}
/* The port lock is held and interrupts are disabled. */ staticvoid ip22zilog_stop_tx(struct uart_port *port)
{ struct uart_ip22zilog_port *up =
container_of(port, struct uart_ip22zilog_port, port);
up->flags |= IP22ZILOG_FLAG_TX_STOPPED;
}
/* The port lock is held and interrupts are disabled. */ staticvoid ip22zilog_start_tx(struct uart_port *port)
{ struct uart_ip22zilog_port *up =
container_of(port, struct uart_ip22zilog_port, port); struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); unsignedchar status;
/* TX busy? Just wait for the TX done interrupt. */ if (!(status & Tx_BUF_EMP)) return;
/* Send the first character to jump-start the TX done *IRQsendingengine.
*/ if (port->x_char) {
writeb(port->x_char, &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
if (!uart_fifo_get(port, &c)) return;
writeb(c, &channel->data);
ZSDELAY();
ZS_WSYNC(channel);
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(&up->port);
}
}
/* The port lock is held and interrupts are disabled. */ staticvoid ip22zilog_stop_rx(struct uart_port *port)
{ struct uart_ip22zilog_port *up = UART_ZILOG(port); struct zilog_channel *channel;
/* NOTE: Not subject to 'transmitter active' rule. */
write_zsreg(channel, R5, up->curregs[R5]);
}
uart_port_unlock_irqrestore(port, flags);
}
staticvoid __ip22zilog_reset(struct uart_ip22zilog_port *up)
{ struct zilog_channel *channel; int i;
if (up->flags & IP22ZILOG_FLAG_RESET_DONE) return;
/* Let pending transmits finish. */
channel = ZILOG_CHANNEL_FROM_PORT(&up->port); for (i = 0; i < 1000; i++) { unsignedchar stat = read_zsreg(channel, R1); if (stat & ALL_SNT) break;
udelay(100);
}
up = &ip22zilog_port_table[CHANNEL_A];
channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
/* Disable all interrupts and BRK assertion. */
up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK);
up->curregs[R5] &= ~SND_BRK;
ip22zilog_maybe_update_regs(up, channel);
uart_port_unlock_irqrestore(port, flags);
}
/* Shared by TTY driver and serial console setup. The port lock is held *andlocalinterruptsaredisabled.
*/ staticvoid
ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsignedint cflag, unsignedint iflag, int brg)
{
/* We do not request/release mappings of the registers here, this *happensatearlyserialprobetime.
*/ staticvoid ip22zilog_release_port(struct uart_port *port)
{
}
/* These do not need to do anything interesting either. */ staticvoid ip22zilog_config_port(struct uart_port *port, int flags)
{
}
/* We do not support letting the user mess with the divisor, IRQ, etc. */ staticint ip22zilog_verify_port(struct uart_port *port, struct serial_struct *ser)
{ return -EINVAL;
}
/* This is a timed polling loop so do not switch the explicit *udelaywithZSDELAYasthatisaNOPonsomeplatforms.-DaveM
*/ do { unsignedchar val = readb(&channel->control); if (val & Tx_BUF_EMP) {
ZSDELAY(); break;
}
udelay(5);
} while (--loops);
/* David wrote it but I'm to blame for the bugs ... */
MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
MODULE_DESCRIPTION("SGI Zilog serial port driver");
MODULE_LICENSE("GPL");
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-09-27)
¤
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.