cregit-Linux how code gets into the kernel

Release 4.11 drivers/tty/serial/dz.c

/*
 * dz.c: Serial port driver for DECstations equipped
 *       with the DZ chipset.
 *
 * Copyright (C) 1998 Olivier A. D. Lebaillif
 *
 * Email: olivier.lebaillif@ifrsys.com
 *
 * Copyright (C) 2004, 2006, 2007  Maciej W. Rozycki
 *
 * [31-AUG-98] triemer
 * Changed IRQ to use Harald's dec internals interrupts.h
 * removed base_addr code - moving address assignment to setup.c
 * Changed name of dz_init to rs_init to be consistent with tc code
 * [13-NOV-98] triemer fixed code to receive characters
 *    after patches by harald to irq code.
 * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
 *            field from "current" - somewhere between 2.1.121 and 2.1.131
 Qua Jun 27 15:02:26 BRT 2001
 * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups
 *
 * Parts (C) 1999 David Airlie, airlied@linux.ie
 * [07-SEP-99] Bugfixes
 *
 * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk>
 * Converted to new serial core
 */


#undef DEBUG_DZ

#if defined(CONFIG_SERIAL_DZ_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)

#define SUPPORT_SYSRQ
#endif

#include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/module.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>

#include <linux/atomic.h>
#include <asm/bootinfo.h>
#include <asm/io.h>

#include <asm/dec/interrupts.h>
#include <asm/dec/kn01.h>
#include <asm/dec/kn02.h>
#include <asm/dec/machtype.h>
#include <asm/dec/prom.h>
#include <asm/dec/system.h>

#include "dz.h"


MODULE_DESCRIPTION("DECstation DZ serial driver");
MODULE_LICENSE("GPL");



static char dz_name[] __initdata = "DECstation DZ serial driver version ";

static char dz_version[] __initdata = "1.04";


struct dz_port {
	
struct dz_mux		*mux;
	
struct uart_port	port;
	
unsigned int		cflag;
};


struct dz_mux {
	
struct dz_port		dport[DZ_NB_PORT];
	
atomic_t		map_guard;
	
atomic_t		irq_guard;
	
int			initialised;
};


static struct dz_mux dz_mux;


static inline struct dz_port *to_dport(struct uart_port *uport) { return container_of(uport, struct dz_port, port); }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki25100.00%1100.00%
Total25100.00%1100.00%

/* * ------------------------------------------------------------ * dz_in () and dz_out () * * These routines are used to access the registers of the DZ * chip, hiding relocation differences between implementation. * ------------------------------------------------------------ */
static u16 dz_in(struct dz_port *dport, unsigned offset) { void __iomem *addr = dport->port.membase + offset; return readw(addr); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton2781.82%150.00%
Maciej W. Rozycki618.18%150.00%
Total33100.00%2100.00%


static void dz_out(struct dz_port *dport, unsigned offset, u16 value) { void __iomem *addr = dport->port.membase + offset; writew(value, addr); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton2978.38%150.00%
Maciej W. Rozycki821.62%150.00%
Total37100.00%2100.00%

/* * ------------------------------------------------------------ * rs_stop () and rs_start () * * These routines are called before setting or resetting * tty->stopped. They enable or disable transmitter interrupts, * as necessary. * ------------------------------------------------------------ */
static void dz_stop_tx(struct uart_port *uport) { struct dz_port *dport = to_dport(uport); u16 tmp, mask = 1 << dport->port.line; tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ tmp &= ~mask; /* clear the TX flag */ dz_out(dport, DZ_TCR, tmp); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton5593.22%133.33%
Maciej W. Rozycki46.78%266.67%
Total59100.00%3100.00%


static void dz_start_tx(struct uart_port *uport) { struct dz_port *dport = to_dport(uport); u16 tmp, mask = 1 << dport->port.line; tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ tmp |= mask; /* set the TX flag */ dz_out(dport, DZ_TCR, tmp); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton5493.10%133.33%
Maciej W. Rozycki46.90%266.67%
Total58100.00%3100.00%


static void dz_stop_rx(struct uart_port *uport) { struct dz_port *dport = to_dport(uport); dport->cflag &= ~DZ_RXENAB; dz_out(dport, DZ_LPR, dport->cflag); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton3589.74%133.33%
Maciej W. Rozycki410.26%266.67%
Total39100.00%3100.00%

/* * ------------------------------------------------------------ * * Here start the interrupt handling routines. All of the following * subroutines are declared as inline and are folded into * dz_interrupt. They were separated out for readability's sake. * * Note: dz_interrupt() is a "fast" interrupt, which means that it * runs with interrupts turned off. People who may want to modify * dz_interrupt() should try to keep the interrupt handler as fast as * possible. After you are done making modifications, it is not a bad * idea to do: * * make drivers/serial/dz.s * * and look at the resulting assemble code in dz.s. * * ------------------------------------------------------------ */ /* * ------------------------------------------------------------ * receive_char () * * This routine deals with inputs from any lines. * ------------------------------------------------------------ */
static inline void dz_receive_chars(struct dz_mux *mux) { struct uart_port *uport; struct dz_port *dport = &mux->dport[0]; struct uart_icount *icount; int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 }; unsigned char ch, flag; u16 status; int i; while ((status = dz_in(dport, DZ_RBUF)) & DZ_DVAL) { dport = &mux->dport[LINE(status)]; uport = &dport->port; ch = UCHAR(status); /* grab the char */ flag = TTY_NORMAL; icount = &uport->icount; icount->rx++; if (unlikely(status & (DZ_OERR | DZ_FERR | DZ_PERR))) { /* * There is no separate BREAK status bit, so treat * null characters with framing errors as BREAKs; * normally, otherwise. For this move the Framing * Error bit to a simulated BREAK bit. */ if (!ch) { status |= (status & DZ_FERR) >> (ffs(DZ_FERR) - ffs(DZ_BREAK)); status &= ~DZ_FERR; } /* Handle SysRq/SAK & keep track of the statistics. */ if (status & DZ_BREAK) { icount->brk++; if (uart_handle_break(uport)) continue; } else if (status & DZ_FERR) icount->frame++; else if (status & DZ_PERR) icount->parity++; if (status & DZ_OERR) icount->overrun++; status &= uport->read_status_mask; if (status & DZ_BREAK) flag = TTY_BREAK; else if (status & DZ_FERR) flag = TTY_FRAME; else if (status & DZ_PERR) flag = TTY_PARITY; } if (uart_handle_sysrq_char(uport, ch)) continue; uart_insert_char(uport, status, DZ_OERR, ch, flag); lines_rx[LINE(status)] = 1; } for (i = 0; i < DZ_NB_PORT; i++) if (lines_rx[i]) tty_flip_buffer_push(&mux->dport[i].port.state->port); }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki23067.45%337.50%
Andrew Morton9929.03%112.50%
Russell King92.64%112.50%
Jiri Slaby10.29%112.50%
Takashi Iwai10.29%112.50%
Alan Cox10.29%112.50%
Total341100.00%8100.00%

/* * ------------------------------------------------------------ * transmit_char () * * This routine deals with outputs to any lines. * ------------------------------------------------------------ */
static inline void dz_transmit_chars(struct dz_mux *mux) { struct dz_port *dport = &mux->dport[0]; struct circ_buf *xmit; unsigned char tmp; u16 status; status = dz_in(dport, DZ_CSR); dport = &mux->dport[LINE(status)]; xmit = &dport->port.state->xmit; if (dport->port.x_char) { /* XON/XOFF chars */ dz_out(dport, DZ_TDR, dport->port.x_char); dport->port.icount.tx++; dport->port.x_char = 0; return; } /* If nothing to do or stopped or hardware stopped. */ if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { spin_lock(&dport->port.lock); dz_stop_tx(&dport->port); spin_unlock(&dport->port.lock); return; } /* * If something to do... (remember the dz has no output fifo, * so we go one char at a time) :-< */ tmp = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1); dz_out(dport, DZ_TDR, tmp); dport->port.icount.tx++; if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS) uart_write_wakeup(&dport->port); /* Are we are done. */ if (uart_circ_empty(xmit)) { spin_lock(&dport->port.lock); dz_stop_tx(&dport->port); spin_unlock(&dport->port.lock); } }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton16864.12%120.00%
Maciej W. Rozycki9335.50%360.00%
Alan Cox10.38%120.00%
Total262100.00%5100.00%

/* * ------------------------------------------------------------ * check_modem_status() * * DS 3100 & 5100: Only valid for the MODEM line, duh! * DS 5000/200: Valid for the MODEM and PRINTER line. * ------------------------------------------------------------ */
static inline void check_modem_status(struct dz_port *dport) { /* * FIXME: * 1. No status change interrupt; use a timer. * 2. Handle the 3100/5000 as appropriate. --macro */ u16 status; /* If not the modem line just return. */ if (dport->port.line != DZ_MODEM) return; status = dz_in(dport, DZ_MSR); /* it's easy, since DSR2 is the only bit in the register */ if (status) dport->port.icount.dsr++; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton4894.12%133.33%
Maciej W. Rozycki35.88%266.67%
Total51100.00%3100.00%

/* * ------------------------------------------------------------ * dz_interrupt () * * this is the main interrupt routine for the DZ chip. * It deals with the multiple ports. * ------------------------------------------------------------ */
static irqreturn_t dz_interrupt(int irq, void *dev_id) { struct dz_mux *mux = dev_id; struct dz_port *dport = &mux->dport[0]; u16 status; /* get the reason why we just got an irq */ status = dz_in(dport, DZ_CSR); if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE)) dz_receive_chars(mux); if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE)) dz_transmit_chars(mux); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton5153.68%133.33%
Maciej W. Rozycki4446.32%266.67%
Total95100.00%3100.00%

/* * ------------------------------------------------------------------- * Here ends the DZ interrupt routines. * ------------------------------------------------------------------- */
static unsigned int dz_get_mctrl(struct uart_port *uport) { /* * FIXME: Handle the 3100/5000 as appropriate. --macro */ struct dz_port *dport = to_dport(uport); unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; if (dport->port.line == DZ_MODEM) { if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR) mctrl &= ~TIOCM_DSR; } return mctrl; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton6093.75%133.33%
Maciej W. Rozycki46.25%266.67%
Total64100.00%3100.00%


static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) { /* * FIXME: Handle the 3100/5000 as appropriate. --macro */ struct dz_port *dport = to_dport(uport); u16 tmp; if (dport->port.line == DZ_MODEM) { tmp = dz_in(dport, DZ_TCR); if (mctrl & TIOCM_DTR) tmp &= ~DZ_MODEM_DTR; else tmp |= DZ_MODEM_DTR; dz_out(dport, DZ_TCR, tmp); } }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton7093.33%125.00%
Maciej W. Rozycki56.67%375.00%
Total75100.00%4100.00%

/* * ------------------------------------------------------------------- * startup () * * various initialization tasks * ------------------------------------------------------------------- */
static int dz_startup(struct uart_port *uport) { struct dz_port *dport = to_dport(uport); struct dz_mux *mux = dport->mux; unsigned long flags; int irq_guard; int ret; u16 tmp; irq_guard = atomic_add_return(1, &mux->irq_guard); if (irq_guard != 1) return 0; ret = request_irq(dport->port.irq, dz_interrupt, IRQF_SHARED, "dz", mux); if (ret) { atomic_add(-1, &mux->irq_guard); printk(KERN_ERR "dz: Cannot get IRQ %d!\n", dport->port.irq); return ret; } spin_lock_irqsave(&dport->port.lock, flags); /* Enable interrupts. */ tmp = dz_in(dport, DZ_CSR); tmp |= DZ_RIE | DZ_TIE; dz_out(dport, DZ_CSR, tmp); spin_unlock_irqrestore(&dport->port.lock, flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki9556.89%375.00%
Andrew Morton7243.11%125.00%
Total167100.00%4100.00%

/* * ------------------------------------------------------------------- * shutdown () * * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. * ------------------------------------------------------------------- */
static void dz_shutdown(struct uart_port *uport) { struct dz_port *dport = to_dport(uport); struct dz_mux *mux = dport->mux; unsigned long flags; int irq_guard; u16 tmp; spin_lock_irqsave(&dport->port.lock, flags); dz_stop_tx(&dport->port); spin_unlock_irqrestore(&dport->port.lock, flags); irq_guard = atomic_add_return(-1, &mux->irq_guard); if (!irq_guard) { /* Disable interrupts. */ tmp = dz_in(dport, DZ_CSR); tmp &= ~(DZ_RIE | DZ_TIE); dz_out(dport, DZ_CSR, tmp); free_irq(dport->port.irq, mux); } }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki11789.31%375.00%
Andrew Morton1410.69%125.00%
Total131100.00%4100.00%

/* * ------------------------------------------------------------------- * dz_tx_empty() -- get the transmitter empty status * * Purpose: Let user call ioctl() to get info when the UART physically * is emptied. On bus types like RS485, the transmitter must * release the bus after transmitting. This must be done when * the transmit shift register is empty, not be done when the * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. * ------------------------------------------------------------------- */
static unsigned int dz_tx_empty(struct uart_port *uport) { struct dz_port *dport = to_dport(uport); unsigned short tmp, mask = 1 << dport->port.line; tmp = dz_in(dport, DZ_TCR); tmp &= mask; return tmp ? 0 : TIOCSER_TEMT; }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki4071.43%375.00%
Andrew Morton1628.57%125.00%
Total56100.00%4100.00%


static void dz_break_ctl(struct uart_port *uport, int break_state) { /* * FIXME: Can't access BREAK bits in TDR easily; * reuse the code for polled TX. --macro */ struct dz_port *dport = to_dport(uport); unsigned long flags; unsigned short tmp, mask = 1 << dport->port.line; spin_lock_irqsave(&uport->lock, flags); tmp = dz_in(dport, DZ_TCR); if (break_state) tmp |= mask; else tmp &= ~mask; dz_out(dport, DZ_TCR, tmp); spin_unlock_irqrestore(&uport->lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton8892.63%133.33%
Maciej W. Rozycki77.37%266.67%
Total95100.00%3100.00%


static int dz_encode_baud_rate(unsigned int baud) { switch (baud) { case 50: return DZ_B50; case 75: return DZ_B75; case 110: return DZ_B110; case 134: return DZ_B134; case 150: return DZ_B150; case 300: return DZ_B300; case 600: return DZ_B600; case 1200: return DZ_B1200; case 1800: return DZ_B1800; case 2000: return DZ_B2000; case 2400: return DZ_B2400; case 3600: return DZ_B3600; case 4800: return DZ_B4800; case 7200: return DZ_B7200; case 9600: return DZ_B9600; default: return -1; } }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki111100.00%1100.00%
Total111100.00%1100.00%


static void dz_reset(struct dz_port *dport) { struct dz_mux *mux = dport->mux; if (mux->initialised) return; dz_out(dport, DZ_CSR, DZ_CLR); while (dz_in(dport, DZ_CSR) & DZ_CLR); iob(); /* Enable scanning. */ dz_out(dport, DZ_CSR, DZ_MSE); mux->initialised = 1; }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki67100.00%1100.00%
Total67100.00%1100.00%


static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, struct ktermios *old_termios) { struct dz_port *dport = to_dport(uport); unsigned long flags; unsigned int cflag, baud; int bflag; cflag = dport->port.line; switch (termios->c_cflag & CSIZE) { case CS5: cflag |= DZ_CS5; break; case CS6: cflag |= DZ_CS6; break; case CS7: cflag |= DZ_CS7; break; case CS8: default: cflag |= DZ_CS8; } if (termios->c_cflag & CSTOPB) cflag |= DZ_CSTOPB; if (termios->c_cflag & PARENB) cflag |= DZ_PARENB; if (termios->c_cflag & PARODD) cflag |= DZ_PARODD; baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600); bflag = dz_encode_baud_rate(baud); if (bflag < 0) { /* Try to keep unchanged. */ baud = uart_get_baud_rate(uport, old_termios, NULL, 50, 9600); bflag = dz_encode_baud_rate(baud); if (bflag < 0) { /* Resort to 9600. */ baud = 9600; bflag = DZ_B9600; } tty_termios_encode_baud_rate(termios, baud, baud); } cflag |= bflag; if (termios->c_cflag & CREAD) cflag |= DZ_RXENAB; spin_lock_irqsave(&dport->port.lock, flags); uart_update_timeout(uport, termios->c_cflag, baud); dz_out(dport, DZ_LPR, cflag); dport->cflag = cflag; /* setup accept flag */ dport->port.read_status_mask = DZ_OERR; if (termios->c_iflag & INPCK) dport->port.read_status_mask |= DZ_FERR | DZ_PERR; if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) dport->port.read_status_mask |= DZ_BREAK; /* characters to ignore */ uport->ignore_status_mask = 0; if ((termios->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) dport->port.ignore_status_mask |= DZ_OERR; if (termios->c_iflag & IGNPAR) dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR; if (termios->c_iflag & IGNBRK) dport->port.ignore_status_mask |= DZ_BREAK; spin_unlock_irqrestore(&dport->port.lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton25264.12%116.67%
Maciej W. Rozycki13734.86%350.00%
Peter Hurley20.51%116.67%
Alan Cox20.51%116.67%
Total393100.00%6100.00%

/* * Hack alert! * Required solely so that the initial PROM-based console * works undisturbed in parallel with this one. */
static void dz_pm(struct uart_port *uport, unsigned int state, unsigned int oldstate) { struct dz_port *dport = to_dport(uport); unsigned long flags; spin_lock_irqsave(&dport->port.lock, flags); if (state < 3) dz_start_tx(&dport->port); else dz_stop_tx(&dport->port); spin_unlock_irqrestore(&dport->port.lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki80100.00%1100.00%
Total80100.00%1100.00%


static const char *dz_type(struct uart_port *uport) { return "DZ"; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton1593.75%150.00%
Maciej W. Rozycki16.25%150.00%
Total16100.00%2100.00%


static void dz_release_port(struct uart_port *uport) { struct dz_mux *mux = to_dport(uport)->mux; int map_guard; iounmap(uport->membase); uport->membase = NULL; map_guard = atomic_add_return(-1, &mux->map_guard); if (!map_guard) release_mem_region(uport->mapbase, dec_kn_slot_size); }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki5481.82%150.00%
Andrew Morton1218.18%150.00%
Total66100.00%2100.00%


static int dz_map_port(struct uart_port *uport) { if (!uport->membase) uport->membase = ioremap_nocache(uport->mapbase, dec_kn_slot_size); if (!uport->membase) { printk(KERN_ERR "dz: Cannot map MMIO\n"); return -ENOMEM; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki3973.58%150.00%
Andrew Morton1426.42%150.00%
Total53100.00%2100.00%


static int dz_request_port(struct uart_port *uport) { struct dz_mux *mux = to_dport(uport)->mux; int map_guard; int ret; map_guard = atomic_add_return(1, &mux->map_guard); if (map_guard == 1) { if (!request_mem_region(uport->mapbase, dec_kn_slot_size, "dz")) { atomic_add(-1, &mux->map_guard); printk(KERN_ERR "dz: Unable to reserve MMIO resource\n"); return -EBUSY; } } ret = dz_map_port(uport); if (ret) { map_guard = atomic_add_return(-1, &mux->map_guard); if (!map_guard) release_mem_region(uport->mapbase, dec_kn_slot_size); return ret; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki12493.94%150.00%
Andrew Morton86.06%150.00%
Total132100.00%2100.00%


static void dz_config_port(struct uart_port *uport, int flags) { struct dz_port *dport = to_dport(uport); if (flags & UART_CONFIG_TYPE) { if (dz_request_port(uport)) return; uport->type = PORT_DZ; dz_reset(dport); } }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki51100.00%1100.00%
Total51100.00%1100.00%

/* * Verify the new serial_struct (for TIOCSSERIAL). */
static int dz_verify_port(struct uart_port *uport, struct serial_struct *ser) { int ret = 0; if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ) ret = -EINVAL; if (ser->irq != uport->irq) ret = -EINVAL; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton4068.97%150.00%
Maciej W. Rozycki1831.03%150.00%
Total58100.00%2100.00%

static const struct uart_ops dz_ops = { .tx_empty = dz_tx_empty, .get_mctrl = dz_get_mctrl, .set_mctrl = dz_set_mctrl, .stop_tx = dz_stop_tx, .start_tx = dz_start_tx, .stop_rx = dz_stop_rx, .break_ctl = dz_break_ctl, .startup = dz_startup, .shutdown = dz_shutdown, .set_termios = dz_set_termios, .pm = dz_pm, .type = dz_type, .release_port = dz_release_port, .request_port = dz_request_port, .config_port = dz_config_port, .verify_port = dz_verify_port, };
static void __init dz_init_ports(void) { static int first = 1; unsigned long base; int line; if (!first) return; first = 0; if (mips_machtype == MACH_DS23100 || mips_machtype == MACH_DS5100) base = dec_kn_slot_base + KN01_DZ11; else base = dec_kn_slot_base + KN02_DZ11; for (line = 0; line < DZ_NB_PORT; line++) { struct dz_port *dport = &dz_mux.dport[line]; struct uart_port *uport = &dport->port; dport->mux = &dz_mux; uport->irq = dec_interrupt[DEC_IRQ_DZ11]; uport->fifosize = 1; uport->iotype = UPIO_MEM; uport->flags = UPF_BOOT_AUTOCONF; uport->ops = &dz_ops; uport->line = line; uport->mapbase = base; } }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton9263.01%133.33%
Maciej W. Rozycki5034.25%133.33%
Ralf Bächle42.74%133.33%
Total146100.00%3100.00%

#ifdef CONFIG_SERIAL_DZ_CONSOLE /* * ------------------------------------------------------------------- * dz_console_putchar() -- transmit a character * * Polled transmission. This is tricky. We need to mask transmit * interrupts so that they do not interfere, enable the transmitter * for the line requested and then wait till the transmit scanner * requests data for this line. But it may request data for another * line first, in which case we have to disable its transmitter and * repeat waiting till our line pops up. Only then the character may * be transmitted. Finally, the state of the transmitter mask is * restored. Welcome to the world of PDP-11! * ------------------------------------------------------------------- */
static void dz_console_putchar(struct uart_port *uport, int ch) { struct dz_port *dport = to_dport(uport); unsigned long flags; unsigned short csr, tcr, trdy, mask; int loops = 10000; spin_lock_irqsave(&dport->port.lock, flags); csr = dz_in(dport, DZ_CSR); dz_out(dport, DZ_CSR, csr & ~DZ_TIE); tcr = dz_in(dport, DZ_TCR); tcr |= 1 << dport->port.line; mask = tcr; dz_out(dport, DZ_TCR, mask); iob(); spin_unlock_irqrestore(&dport->port.lock, flags); do { trdy = dz_in(dport, DZ_CSR); if (!(trdy & DZ_TRDY)) continue; trdy = (trdy & DZ_TLINE) >> 8; if (trdy == dport->port.line) break; mask &= ~(1 << trdy); dz_out(dport, DZ_TCR, mask); iob(); udelay(2); } while (--loops); if (loops) /* Cannot send otherwise. */ dz_out(dport, DZ_TDR, ch); dz_out(dport, DZ_TCR, tcr); dz_out(dport, DZ_CSR, csr); }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki16370.87%342.86%
Andrew Morton5523.91%114.29%
Russell King104.35%114.29%
Martin Michlmayr10.43%114.29%
Roel Kluin10.43%114.29%
Total230100.00%7100.00%

/* * ------------------------------------------------------------------- * dz_console_print () * * dz_console_print is registered for printk. * The console must be locked when we get here. * ------------------------------------------------------------------- */
static void dz_console_print(struct console *co, const char *str, unsigned int count) { struct dz_port *dport = &dz_mux.dport[co->index]; #ifdef DEBUG_DZ prom_printf((char *) str); #endif uart_console_write(&dport->port, str, count, dz_console_putchar); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton4876.19%125.00%
Russell King812.70%125.00%
Maciej W. Rozycki711.11%250.00%
Total63100.00%4100.00%


static int __init dz_console_setup(struct console *co, char *options) { struct dz_port *dport = &dz_mux.dport[co->index]; struct uart_port *uport = &dport->port; int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n'; int ret; ret = dz_map_port(uport); if (ret) return ret; spin_lock_init(&dport->port.lock); /* For dz_pm(). */ dz_reset(dport); dz_pm(uport, 0, -1); if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); return uart_set_options(&dport->port, co, baud, parity, bits, flow); }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton8458.33%125.00%
Maciej W. Rozycki6041.67%375.00%
Total144100.00%4100.00%

static struct uart_driver dz_reg; static struct console dz_console = { .name = "ttyS", .write = dz_console_print, .device = uart_console_device, .setup = dz_console_setup, .flags = CON_PRINTBUFFER, .index = -1, .data = &dz_reg, };
static int __init dz_serial_console_init(void) { if (!IOASIC) { dz_init_ports(); register_console(&dz_console); return 0; } else return -ENXIO; }

Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki1854.55%266.67%
Andrew Morton1545.45%133.33%
Total33100.00%3100.00%

console_initcall(dz_serial_console_init); #define SERIAL_DZ_CONSOLE &dz_console #else #define SERIAL_DZ_CONSOLE NULL #endif /* CONFIG_SERIAL_DZ_CONSOLE */ static struct uart_driver dz_reg = { .owner = THIS_MODULE, .driver_name = "serial", .dev_name = "ttyS", .major = TTY_MAJOR, .minor = 64, .nr = DZ_NB_PORT, .cons = SERIAL_DZ_CONSOLE, };
static int __init dz_init(void) { int ret, i; if (IOASIC) return -ENXIO; printk("%s%s\n", dz_name, dz_version); dz_init_ports(); ret = uart_register_driver(&dz_reg); if (ret) return ret; for (i = 0; i < DZ_NB_PORT; i++) uart_add_one_port(&dz_reg, &dz_mux.dport[i].port); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Andrew Morton5567.90%125.00%
Maciej W. Rozycki2632.10%375.00%
Total81100.00%4100.00%

module_init(dz_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
Maciej W. Rozycki182749.38%1142.31%
Andrew Morton181949.16%13.85%
Russell King300.81%27.69%
Ralf Bächle90.24%27.69%
Alan Cox40.11%27.69%
Jiri Slaby40.11%27.69%
Peter Hurley20.05%13.85%
Martin Michlmayr10.03%13.85%
Roel Kluin10.03%13.85%
Arun Sharma10.03%13.85%
Bhumika Goyal10.03%13.85%
Takashi Iwai10.03%13.85%
Total3700100.00%26100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.