diff -ruN linux-2.4.3/drivers/char/serial.c linux-2.4.3-patched/drivers/char/serial.c --- linux-2.4.3/drivers/char/serial.c Wed Mar 7 05:13:51 2001 +++ linux-2.4.3-patched/drivers/char/serial.c Fri May 18 16:28:30 2001 @@ -1259,7 +1259,7 @@ serial_outp(info, UART_EFR, UART_EFR_ECB); serial_outp(info, UART_IER, 0); serial_outp(info, UART_LCR, 0); - serial_icr_write(info, UART_CSR, 0); /* Reset the UART */ + /* serial_icr_write(info, UART_CSR, 0); */ /* Reset the UART */ serial_outp(info, UART_LCR, 0xBF); serial_outp(info, UART_EFR, UART_EFR_ECB); serial_outp(info, UART_LCR, 0); @@ -1364,9 +1364,12 @@ */ serial_outp(info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ - info->MCR = 0; + if (state->type == PORT_16C950) + info->MCR &= UART_MCR_PRESCALER; + else + info->MCR = 0; if (info->tty->termios->c_cflag & CBAUD) - info->MCR = UART_MCR_DTR | UART_MCR_RTS; + info->MCR |= UART_MCR_DTR | UART_MCR_RTS; #ifdef CONFIG_SERIAL_MANY_PORTS if (info->flags & ASYNC_FOURPORT) { if (state->irq == 0) @@ -2514,6 +2517,41 @@ } #endif +static int get_clock_prescaler(struct async_struct * info, unsigned char *value) +{ + unsigned char cpr; + + if (!(serial_in(info, UART_MCR) & UART_MCR_PRESCALER)) + cpr = 8; + else + cpr = serial_icr_read(info, UART_CPR); + + if (copy_to_user(value,&cpr,sizeof(unsigned char))) + return -EFAULT; + + return 0; +} + +static int set_clock_prescaler(struct async_struct * info, unsigned char *value) +{ + unsigned char cpr; + + if (copy_from_user(&cpr,value,sizeof(unsigned char))) + return -EFAULT; + + if (cpr < 8){ + info->MCR &= ~UART_MCR_PRESCALER; + } + else{ + info->MCR |= UART_MCR_PRESCALER; + } + + serial_out(info, UART_MCR, info->MCR); + serial_icr_write(info, UART_CPR, cpr); + + return 0; +} + static int rs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { @@ -2668,6 +2706,14 @@ if (copy_to_user((void *)arg, &icount, sizeof(icount))) return -EFAULT; return 0; + case TIOCGSERCPR: /* Get serial clock prescaler */ + if (info->state->type == PORT_16C950) + return get_clock_prescaler(info, (unsigned char *) arg); + return -ENXIO; + case TIOCSSERCPR: /* Set serial clock prescaler */ + if (info->state->type == PORT_16C950) + return set_clock_prescaler(info, (unsigned char *) arg); + return -ENXIO; case TIOCSERGWILD: case TIOCSERSWILD: /* "setserial -W" is called in Debian boot */ diff -ruN linux-2.4.3/include/asm-i386/ioctls.h linux-2.4.3-patched/include/asm-i386/ioctls.h --- linux-2.4.3/include/asm-i386/ioctls.h Fri Jul 24 20:10:16 1998 +++ linux-2.4.3-patched/include/asm-i386/ioctls.h Thu May 17 16:34:08 2001 @@ -67,6 +67,8 @@ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ #define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ #define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ +#define TIOCGSERCPR 0x5460 /* Get serial clock prescaler*/ +#define TIOCSSERCPR 0x5461 /* Set serial clock prescaler*/ /* Used for packet mode */ #define TIOCPKT_DATA 0 diff -ruN linux-2.4.3/include/linux/serial_reg.h linux-2.4.3-patched/include/linux/serial_reg.h --- linux-2.4.3/include/linux/serial_reg.h Wed Mar 7 04:28:35 2001 +++ linux-2.4.3-patched/include/linux/serial_reg.h Thu May 17 16:23:32 2001 @@ -121,6 +121,7 @@ /* * These are the definitions for the Modem Control Register */ +#define UART_MCR_PRESCALER 0x80 /* Enable clock prescaler */ #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ #define UART_MCR_OUT2 0x08 /* Out2 complement */ #define UART_MCR_OUT1 0x04 /* Out1 complement */