summaryrefslogtreecommitdiffstats
path: root/drivers/char/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/serial.c')
-rw-r--r--drivers/char/serial.c243
1 files changed, 137 insertions, 106 deletions
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index b5e41a2d2..c25e24057 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -64,7 +64,7 @@
* ever possible.
*/
-#define SERIAL_PARANOIA_CHECK
+#undef SERIAL_PARANOIA_CHECK
#define CONFIG_SERIAL_NOPAUSE_IO
#define SERIAL_DO_RESTART
@@ -156,7 +156,7 @@
#endif
static char *serial_name = "Serial driver";
-static char *serial_version = "4.25";
+static char *serial_version = "4.26";
static DECLARE_TASK_QUEUE(tq_serial);
@@ -852,13 +852,14 @@ static void rs_timer(void)
static unsigned long last_strobe = 0;
struct async_struct *info;
unsigned int i;
+ unsigned long flags;
if ((jiffies - last_strobe) >= RS_STROBE_TIME) {
for (i=1; i < NR_IRQS; i++) {
info = IRQ_ports[i];
if (!info)
continue;
- cli();
+ save_flags(flags); cli();
#ifdef CONFIG_SERIAL_SHARE_IRQ
if (info->next_port) {
do {
@@ -876,7 +877,7 @@ static void rs_timer(void)
} else
#endif /* CONFIG_SERIAL_SHARE_IRQ */
rs_interrupt_single(i, NULL, NULL);
- sti();
+ restore_flags(flags);
}
}
last_strobe = jiffies;
@@ -884,13 +885,13 @@ static void rs_timer(void)
timer_active |= 1 << RS_TIMER;
if (IRQ_ports[0]) {
- cli();
+ save_flags(flags); cli();
#ifdef CONFIG_SERIAL_SHARE_IRQ
rs_interrupt(0, NULL, NULL);
#else
rs_interrupt_single(0, NULL, NULL);
#endif
- sti();
+ restore_flags(flags);
timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2;
}
@@ -1523,12 +1524,13 @@ static int rs_chars_in_buffer(struct tty_struct *tty)
static void rs_flush_buffer(struct tty_struct *tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
-
+ unsigned long flags;
+
if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
return;
- cli();
+ save_flags(flags); cli();
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- sti();
+ restore_flags(flags);
wake_up_interruptible(&tty->write_wait);
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
@@ -1565,6 +1567,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
static void rs_throttle(struct tty_struct * tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
@@ -1581,14 +1584,15 @@ static void rs_throttle(struct tty_struct * tty)
if (tty->termios->c_cflag & CRTSCTS)
info->MCR &= ~UART_MCR_RTS;
- cli();
+ save_flags(flags); cli();
serial_out(info, UART_MCR, info->MCR);
- sti();
+ restore_flags(flags);
}
static void rs_unthrottle(struct tty_struct * tty)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
+ unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
@@ -1607,9 +1611,9 @@ static void rs_unthrottle(struct tty_struct * tty)
}
if (tty->termios->c_cflag & CRTSCTS)
info->MCR |= UART_MCR_RTS;
- cli();
+ save_flags(flags); cli();
serial_out(info, UART_MCR, info->MCR);
- sti();
+ restore_flags(flags);
}
/*
@@ -1678,10 +1682,16 @@ static int set_serial_info(struct async_struct * info,
new_serial.irq = irq_cannonicalize(new_serial.irq);
if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) ||
- (new_serial.type < PORT_UNKNOWN) || (new_serial.type > PORT_MAX)) {
+ (new_serial.type < PORT_UNKNOWN) ||
+ (new_serial.type > PORT_MAX)) {
return -EINVAL;
}
+ if ((new_serial.type != state->type) ||
+ (new_serial.xmit_fifo_size <= 0))
+ new_serial.xmit_fifo_size =
+ uart_config[state->type].dfl_xmit_fifo_size;
+
/* Make sure address is not already in use */
if (new_serial.type) {
for (i = 0 ; i < NR_PORTS; i++)
@@ -1730,9 +1740,6 @@ static int set_serial_info(struct async_struct * info,
check_and_exit:
if (!state->port || !state->type)
return 0;
- if (state->type != old_state.type)
- info->xmit_fifo_size = state->xmit_fifo_size =
- uart_config[state->type].dfl_xmit_fifo_size;
if (state->flags & ASYNC_INITIALIZED) {
if (((old_state.flags & ASYNC_SPD_MASK) !=
(state->flags & ASYNC_SPD_MASK)) ||
@@ -1767,10 +1774,11 @@ static int get_lsr_info(struct async_struct * info, unsigned int *value)
{
unsigned char status;
unsigned int result;
+ unsigned long flags;
- cli();
+ save_flags(flags); cli();
status = serial_in(info, UART_LSR);
- sti();
+ restore_flags(flags);
result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
return put_user(result,value);
}
@@ -1780,11 +1788,12 @@ static int get_modem_info(struct async_struct * info, unsigned int *value)
{
unsigned char control, status;
unsigned int result;
+ unsigned long flags;
control = info->MCR;
- cli();
+ save_flags(flags); cli();
status = serial_in(info, UART_MSR);
- sti();
+ restore_flags(flags);
result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
#ifdef TIOCM_OUT1
@@ -1803,6 +1812,7 @@ static int set_modem_info(struct async_struct * info, unsigned int cmd,
{
int error;
unsigned int arg;
+ unsigned long flags;
error = get_user(arg, value);
if (error)
@@ -1849,9 +1859,9 @@ static int set_modem_info(struct async_struct * info, unsigned int cmd,
default:
return -EINVAL;
}
- cli();
+ save_flags(flags); cli();
serial_out(info, UART_MCR, info->MCR);
- sti();
+ restore_flags(flags);
return 0;
}
@@ -1868,7 +1878,9 @@ static int do_autoconfig(struct async_struct * info)
shutdown(info);
autoconfig(info->state);
- if ((info->state->flags & ASYNC_AUTO_IRQ) && (info->state->port != 0))
+ if ((info->state->flags & ASYNC_AUTO_IRQ) &&
+ (info->state->port != 0) &&
+ (info->state->type != PORT_UNKNOWN))
info->state->irq = detect_uart_irq(info->state);
retval = startup(info);
@@ -2022,7 +2034,8 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct *p_cuser; /* user space */
-
+ unsigned long flags;
+
if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
return -ENODEV;
@@ -2074,18 +2087,18 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
* Caller should use TIOCGICOUNT to see which one it was
*/
case TIOCMIWAIT:
- cli();
+ save_flags(flags); cli();
/* note the counters on entry */
cprev = info->state->icount;
- sti();
+ restore_flags(flags);
while (1) {
interruptible_sleep_on(&info->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
- cli();
+ save_flags(flags); cli();
cnow = info->state->icount; /* atomic copy */
- sti();
+ restore_flags(flags);
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
return -EIO; /* no change => error */
@@ -2106,9 +2119,9 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
* RI where only 0->1 is counted.
*/
case TIOCGICOUNT:
- cli();
+ save_flags(flags); cli();
cnow = info->state->icount;
- sti();
+ restore_flags(flags);
p_cuser = (struct serial_icounter_struct *) arg;
error = put_user(cnow.cts, &p_cuser->cts);
if (error) return error;
@@ -2118,6 +2131,26 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
if (error) return error;
error = put_user(cnow.dcd, &p_cuser->dcd);
if (error) return error;
+ error = put_user(cnow.rx, &p_cuser->rx);
+ if (error) return error;
+ error = put_user(cnow.tx, &p_cuser->tx);
+ if (error) return error;
+ error = put_user(cnow.frame, &p_cuser->frame);
+ if (error) return error;
+ error = put_user(cnow.overrun, &p_cuser->overrun);
+ if (error) return error;
+ error = put_user(cnow.parity, &p_cuser->parity);
+ if (error) return error;
+ error = put_user(cnow.brk, &p_cuser->brk);
+ if (error) return error;
+ error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
+ if (error) return error;
+ return 0;
+
+ case TIOCSERGWILD:
+ case TIOCSERSWILD:
+ /* "setserial -W" is called in Debian boot */
+ printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
return 0;
default:
@@ -2129,7 +2162,8 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
-
+ unsigned long flags;
+
if ( (tty->termios->c_cflag == old_termios->c_cflag)
&& ( RELEVANT_IFLAG(tty->termios->c_iflag)
== RELEVANT_IFLAG(old_termios->c_iflag)))
@@ -2141,9 +2175,9 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
if ((old_termios->c_cflag & CBAUD) &&
!(tty->termios->c_cflag & CBAUD)) {
info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
- cli();
+ save_flags(flags); cli();
serial_out(info, UART_MCR, info->MCR);
- sti();
+ restore_flags(flags);
}
/* Handle transition away from B0 status */
@@ -2154,9 +2188,9 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
!test_bit(TTY_THROTTLED, &tty->flags)) {
info->MCR |= UART_MCR_RTS;
}
- cli();
+ save_flags(flags); cli();
serial_out(info, UART_MCR, info->MCR);
- sti();
+ restore_flags(flags);
}
/* Handle turning off CRTSCTS */
@@ -2306,6 +2340,9 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
if (info->state->type == PORT_UNKNOWN)
return;
+ if (info->xmit_fifo_size == 0)
+ return; /* Just in case.... */
+
orig_jiffies = jiffies;
/*
* Set the check interval to be 1/5 of the estimated time to
@@ -2377,7 +2414,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
struct wait_queue wait = { current, NULL };
struct serial_state *state = info->state;
int retval;
- int do_clocal = 0;
+ int do_clocal = 0, extra_count = 0;
+ unsigned long flags;
/*
* If the device is in the middle of being closed, then block
@@ -2447,19 +2485,21 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready before block: ttys%d, count = %d\n",
state->line, state->count);
#endif
- cli();
- if (!tty_hung_up_p(filp))
+ save_flags(flags); cli();
+ if (!tty_hung_up_p(filp)) {
+ extra_count = 1;
state->count--;
- sti();
+ }
+ restore_flags(flags);
info->blocked_open++;
while (1) {
- cli();
+ save_flags(flags); cli();
if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
(tty->termios->c_cflag & CBAUD))
serial_out(info, UART_MCR,
serial_inp(info, UART_MCR) |
(UART_MCR_DTR | UART_MCR_RTS));
- sti();
+ restore_flags(flags);
current->state = TASK_INTERRUPTIBLE;
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
@@ -2490,7 +2530,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
}
current->state = TASK_RUNNING;
remove_wait_queue(&info->open_wait, &wait);
- if (!tty_hung_up_p(filp))
+ if (extra_count)
state->count++;
info->blocked_open--;
#ifdef SERIAL_DEBUG_OPEN
@@ -2549,12 +2589,15 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
int retval, line;
unsigned long page;
+ MOD_INC_USE_COUNT;
line = MINOR(tty->device) - tty->driver.minor_start;
if ((line < 0) || (line >= NR_PORTS))
return -ENODEV;
retval = get_async_struct(line, &info);
if (retval)
return retval;
+ tty->driver_data = info;
+ info->tty = tty;
if (serial_paranoia_check(info, tty->device, "rs_open"))
return -ENODEV;
@@ -2562,8 +2605,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
info->state->count);
#endif
- tty->driver_data = info;
- info->tty = tty;
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
if (!tmp_buf) {
@@ -2598,7 +2639,6 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
if (retval)
return retval;
- MOD_INC_USE_COUNT;
retval = block_til_ready(tty, filp, info);
if (retval) {
#ifdef SERIAL_DEBUG_OPEN
@@ -2641,6 +2681,7 @@ static inline int line_info(char *buf, struct serial_state *state)
struct async_struct *info = state->info, scr_info;
char stat_buf[30], control, status;
int ret;
+ unsigned long flags;
ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
state->line, uart_config[state->type].name,
@@ -2663,10 +2704,10 @@ static inline int line_info(char *buf, struct serial_state *state)
info->quot = 0;
info->tty = 0;
}
- cli();
+ save_flags(flags); cli();
status = serial_in(info, UART_MSR);
control = info ? info->MCR : serial_in(info, UART_MCR);
- sti();
+ restore_flags(flags);
stat_buf[0] = 0;
stat_buf[1] = 0;
@@ -2713,12 +2754,13 @@ static inline int line_info(char *buf, struct serial_state *state)
int rs_read_proc(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
- int i, len = 0;
+ int i, len = 0, l;
off_t begin = 0;
len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
for (i = 0; i < NR_PORTS && len < 4000; i++) {
- len += line_info(page + len, &rs_table[i]);
+ l = line_info(page + len, &rs_table[i]);
+ len += l;
if (len+begin > off+count)
goto done;
if (len+begin < off) {
@@ -2764,10 +2806,11 @@ static _INLINE_ void show_serial_version(void)
#endif
#ifdef CONFIG_SERIAL_SHARE_IRQ
printk(" SHARE_IRQ");
-#endif
#define SERIAL_OPT
+#endif
#ifdef CONFIG_SERIAL_DETECT_IRQ
printk(" DETECT_IRQ");
+#define SERIAL_OPT
#endif
#ifdef SERIAL_OPT
printk(" enabled\n");
@@ -2788,7 +2831,7 @@ static unsigned detect_uart_irq (struct serial_state * state)
{
int irq;
unsigned long irqs;
- unsigned char save_mcr;
+ unsigned char save_mcr, save_ier;
struct async_struct scr_info; /* serial_{in,out} because HUB6 */
#ifdef CONFIG_SERIAL_MANY_PORTS
@@ -2812,15 +2855,30 @@ static unsigned detect_uart_irq (struct serial_state * state)
/* forget possible initially masked and pending IRQ */
probe_irq_off(probe_irq_on());
save_mcr = serial_inp(&scr_info, UART_MCR);
-
+ save_ier = serial_inp(&scr_info, UART_IER);
serial_outp(&scr_info, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
+
irqs = probe_irq_on();
serial_outp(&scr_info, UART_MCR, 0);
- udelay (1);
+ udelay (10);
+ if (state->flags & ASYNC_FOURPORT) {
+ serial_outp(&scr_info, UART_MCR,
+ UART_MCR_DTR | UART_MCR_RTS);
+ } else {
+ serial_outp(&scr_info, UART_MCR,
+ UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+ }
+ serial_outp(&scr_info, UART_IER, 0x0f); /* enable all intrs */
+ (void)serial_inp(&scr_info, UART_LSR);
+ (void)serial_inp(&scr_info, UART_RX);
+ (void)serial_inp(&scr_info, UART_IIR);
+ (void)serial_inp(&scr_info, UART_MSR);
+ serial_outp(&scr_info, UART_TX, 0xFF);
+ udelay (20);
irq = probe_irq_off(irqs);
serial_outp(&scr_info, UART_MCR, save_mcr);
-
+ serial_outp(&scr_info, UART_IER, save_ier);
#ifdef CONFIG_SERIAL_MANY_PORTS
if (state->flags & ASYNC_FOURPORT)
outb_p(save_ICP, ICP);
@@ -2888,11 +2946,9 @@ static void autoconfig(struct serial_state * state)
if (!(state->flags & ASYNC_SKIP_TEST)) {
scratch = serial_inp(info, UART_MCR);
serial_outp(info, UART_MCR, UART_MCR_LOOP | scratch);
- scratch2 = serial_inp(info, UART_MSR);
serial_outp(info, UART_MCR, UART_MCR_LOOP | 0x0A);
status1 = serial_inp(info, UART_MSR) & 0xF0;
serial_outp(info, UART_MCR, scratch);
- serial_outp(info, UART_MSR, scratch2);
if (status1 != 0x90) {
restore_flags(flags);
return;
@@ -3105,12 +3161,9 @@ __initfunc(int rs_init(void))
state->icount.frame = state->icount.parity = 0;
state->icount.overrun = state->icount.brk = 0;
state->irq = irq_cannonicalize(state->irq);
- if (check_region(state->port,8)) {
- state->type = PORT_UNKNOWN;
+ if (check_region(state->port,8))
continue;
- }
- if ( (state->type == PORT_UNKNOWN)
- && (state->flags & ASYNC_BOOT_AUTOCONF))
+ if (state->flags & ASYNC_BOOT_AUTOCONF)
autoconfig(state);
}
/*
@@ -3252,13 +3305,13 @@ void cleanup_module(void)
/*
* Wait for transmitter & holding register to empty
*/
-static inline void wait_for_xmitr(struct async_struct *info)
+static inline void wait_for_xmitr(struct serial_state *ser)
{
int lsr;
unsigned int tmout = 1000000;
do {
- lsr = serial_inp(info, UART_LSR);
+ lsr = inb(ser->port + UART_LSR);
if (--tmout == 0) break;
} while ((lsr & BOTH_EMPTY) != BOTH_EMPTY);
}
@@ -3273,36 +3326,28 @@ static void serial_console_write(struct console *co, const char *s,
struct serial_state *ser;
int ier;
unsigned i;
- struct async_struct scr_info; /* serial_{in,out} because HUB6 */
ser = rs_table + co->index;
- scr_info.magic = SERIAL_MAGIC;
- scr_info.port = ser->port;
- scr_info.flags = ser->flags;
-#ifdef CONFIG_HUB6
- scr_info.hub6 = state->hub6;
-#endif
-
/*
* First save the IER then disable the interrupts
*/
- ier = serial_inp(&scr_info, UART_IER);
- serial_outp(&scr_info, UART_IER, 0x00);
+ ier = inb(ser->port + UART_IER);
+ outb(0x00, ser->port + UART_IER);
/*
* Now, do each character
*/
for (i = 0; i < count; i++, s++) {
- wait_for_xmitr(&scr_info);
+ wait_for_xmitr(ser);
/*
* Send the character out.
* If a LF, also do CR...
*/
- serial_outp(&scr_info, UART_TX, *s);
+ outb(*s, ser->port + UART_TX);
if (*s == 10) {
- wait_for_xmitr(&scr_info);
- serial_outp(&scr_info, UART_TX, 13);
+ wait_for_xmitr(ser);
+ outb(13, ser->port + UART_TX);
}
}
@@ -3310,8 +3355,8 @@ static void serial_console_write(struct console *co, const char *s,
* Finally, Wait for transmitter & holding register to empty
* and restore the IER
*/
- wait_for_xmitr(&scr_info);
- serial_outp(&scr_info, UART_IER, ier);
+ wait_for_xmitr(ser);
+ outb(ier, ser->port + UART_IER);
}
/*
@@ -3323,33 +3368,26 @@ static int serial_console_wait_key(struct console *co)
int ier;
int lsr;
int c;
- struct async_struct scr_info; /* serial_{in,out} because HUB6 */
ser = rs_table + co->index;
- scr_info.magic = SERIAL_MAGIC;
- scr_info.port = ser->port;
- scr_info.flags = ser->flags;
-#ifdef CONFIG_HUB6
- scr_info.hub6 = state->hub6;
-#endif
/*
* First save the IER then disable the interrupts so
* that the real driver for the port does not get the
* character.
*/
- ier = serial_inp(&scr_info, UART_IER);
- serial_outp(&scr_info, UART_IER, 0x00);
+ ier = inb(ser->port + UART_IER);
+ outb(0x00, ser->port + UART_IER);
do {
- lsr = serial_inp(&scr_info, UART_LSR);
+ lsr = inb(ser->port + UART_LSR);
} while (!(lsr & UART_LSR_DR));
- c = serial_inp(&scr_info, UART_RX);
+ c = inb(ser->port + UART_RX);
/*
* Restore the interrupts
*/
- serial_outp(&scr_info, UART_IER, ier);
+ outb(ier, ser->port + UART_IER);
return c;
}
@@ -3375,7 +3413,6 @@ __initfunc(static int serial_console_setup(struct console *co, char *options))
int cflag = CREAD | HUPCL | CLOCAL;
int quot = 0;
char *s;
- struct async_struct scr_info; /* serial_{in,out} because HUB6 */
if (options) {
baud = simple_strtoul(options, NULL, 10);
@@ -3439,12 +3476,6 @@ __initfunc(static int serial_console_setup(struct console *co, char *options))
* Divisor, bytesize and parity
*/
ser = rs_table + co->index;
- scr_info.magic = SERIAL_MAGIC;
- scr_info.port = ser->port;
- scr_info.flags = ser->flags;
-#ifdef CONFIG_HUB6
- scr_info.hub6 = state->hub6;
-#endif
quot = ser->baud_base / baud;
cval = cflag & (CSIZE | CSTOPB);
#if defined(__powerpc__) || defined(__alpha__)
@@ -3461,17 +3492,17 @@ __initfunc(static int serial_console_setup(struct console *co, char *options))
* Disable UART interrupts, set DTR and RTS high
* and set speed.
*/
- serial_outp(&scr_info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
- serial_outp(&scr_info, UART_DLL, quot & 0xff); /* LS of divisor */
- serial_outp(&scr_info, UART_DLM, quot >> 8); /* MS of divisor */
- serial_outp(&scr_info, UART_LCR, cval); /* reset DLAB */
- serial_outp(&scr_info, UART_IER, 0);
- serial_outp(&scr_info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
+ outb(cval | UART_LCR_DLAB, ser->port + UART_LCR); /* set DLAB */
+ outb(quot & 0xff, ser->port + UART_DLL); /* LS of divisor */
+ outb(quot >> 8, ser->port + UART_DLM); /* MS of divisor */
+ outb(cval, ser->port + UART_LCR); /* reset DLAB */
+ outb(0, ser->port + UART_IER);
+ outb(UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR);
/*
* If we read 0xff from the LSR, there is no UART here.
*/
- if (serial_inp(&scr_info, UART_LSR) == 0xff)
+ if (inb(ser->port + UART_LSR) == 0xff)
return -1;
return 0;
}