X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fmxser.c;h=147c1ba2efe8f6b432c1b8d2929e7b118c3492da;hb=87fc8d1bb10cd459024a742c6a10961fefcef18f;hp=65ff46a57fe2621bb95cb98f2c469270a4c0300a;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 65ff46a57..147c1ba2e 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -35,6 +35,8 @@ * Added support for: C102, CI-132, CI-134, CP-132, CP-114, CT-114 cards * by Damian Wrobel * + * Added support for serial card CP104 + * by James Nelson Provident Solutions */ #include @@ -99,10 +101,6 @@ #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - /* * Define the Moxa PCI vendor and device IDs. */ @@ -116,6 +114,9 @@ #ifndef PCI_DEVICE_ID_C104 #define PCI_DEVICE_ID_C104 0x1040 #endif +#ifndef PCI_DEVICE_ID_CP104 +#define PCI_DEVICE_ID_CP104 0x1041 +#endif #ifndef PCI_DEVICE_ID_CP132 #define PCI_DEVICE_ID_CP132 0x1320 #endif @@ -139,6 +140,7 @@ enum { MXSER_BOARD_CI104J, MXSER_BOARD_C168_PCI, MXSER_BOARD_C104_PCI, + MXSER_BOARD_CP104_PCI, MXSER_BOARD_C102_ISA, MXSER_BOARD_CI132, MXSER_BOARD_CI134, @@ -154,6 +156,7 @@ static char *mxser_brdname[] = "CI-104J series", "C168H/PCI series", "C104H/PCI series", + "CP104/PCI series", "C102 series", "CI-132 series", "CI-134 series", @@ -169,6 +172,7 @@ static int mxser_numports[] = 4, 8, 4, + 4, 2, 2, 4, @@ -190,11 +194,14 @@ static int mxser_numports[] = #define MOXA_GET_CUMAJOR (MOXA + 64) #define MOXA_GETMSTATUS (MOXA + 65) +#ifdef CONFIG_PCI static struct pci_device_id mxser_pcibrds[] = { { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_C168_PCI }, { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_C104_PCI }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + MXSER_BOARD_CP104_PCI }, { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP132_PCI }, { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, @@ -204,6 +211,7 @@ static struct pci_device_id mxser_pcibrds[] = { { 0 } }; MODULE_DEVICE_TABLE(pci, mxser_pcibrds); +#endif /* CONFIG_PCI */ static int ioaddr[MXSER_BOARDS]; static int ttymajor = MXSERMAJOR; @@ -320,7 +328,6 @@ struct mxser_hwconf mxsercfg[MXSER_BOARDS]; static void mxser_getcfg(int board, struct mxser_hwconf *hwconf); static int mxser_get_ISA_conf(int, struct mxser_hwconf *); -static int mxser_get_PCI_conf(struct pci_dev *, int, struct mxser_hwconf *); static void mxser_do_softint(void *); static int mxser_open(struct tty_struct *, struct file *); static void mxser_close(struct tty_struct *, struct file *); @@ -338,17 +345,17 @@ static void mxser_set_termios(struct tty_struct *, struct termios *); static void mxser_stop(struct tty_struct *); static void mxser_start(struct tty_struct *); static void mxser_hangup(struct tty_struct *); -static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *); static inline void mxser_receive_chars(struct mxser_struct *, int *); static inline void mxser_transmit_chars(struct mxser_struct *); static inline void mxser_check_modem_status(struct mxser_struct *, int); +static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *); static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *); static int mxser_startup(struct mxser_struct *); static void mxser_shutdown(struct mxser_struct *); static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios); -static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct *); -static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct *); -static int mxser_get_lsr_info(struct mxser_struct *, unsigned int *); +static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct __user *); +static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct __user *); +static int mxser_get_lsr_info(struct mxser_struct *, unsigned int __user *); static void mxser_send_break(struct mxser_struct *, int); static int mxser_tiocmget(struct tty_struct *, struct file *); static int mxser_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int); @@ -451,6 +458,7 @@ static void mxser_getcfg(int board, struct mxser_hwconf *hwconf) mxsercfg[board] = *hwconf; } +#ifdef CONFIG_PCI static int mxser_get_PCI_conf(struct pci_dev *pdev, int board_type, struct mxser_hwconf *hwconf) { int i; @@ -475,6 +483,7 @@ static int mxser_get_PCI_conf(struct pci_dev *pdev, int board_type, struct mxser } return (0); } +#endif /* CONFIG_PCI */ static struct tty_operations mxser_ops = { .open = mxser_open, @@ -604,7 +613,6 @@ static int __init mxser_module_init(void) { struct pci_dev *pdev = NULL; int n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1; - int index = 0; for (b = 0; b < n; b++) { while ((pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev))) { @@ -666,9 +674,7 @@ static void mxser_do_softint(void *private_) tty = info->tty; if (tty) { if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); + tty_wakeup(tty); wake_up_interruptible(&tty->write_wait); } if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) { @@ -805,11 +811,11 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) mxser_shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); + tty_ldisc_flush(tty); + tty->closing = 0; info->event = 0; - info->tty = 0; + info->tty = NULL; if (info->blocked_open) { if (info->close_delay) { set_current_state(TASK_INTERRUPTIBLE); @@ -837,7 +843,7 @@ static int mxser_write(struct tty_struct *tty, int from_user, if (from_user) { down(&mxvar_tmp_buf_sem); while (1) { - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); if (c <= 0) break; @@ -850,7 +856,7 @@ static int mxser_write(struct tty_struct *tty, int from_user, } cli(); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1); @@ -865,7 +871,7 @@ static int mxser_write(struct tty_struct *tty, int from_user, } else { while (1) { cli(); - c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); if (c <= 0) { restore_flags(flags); @@ -964,9 +970,7 @@ static void mxser_flush_buffer(struct tty_struct *tty) info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; restore_flags(flags); wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); + tty_wakeup(tty); } static int mxser_ioctl(struct tty_struct *tty, struct file *file, @@ -976,8 +980,9 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; int retval; struct async_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct *p_cuser; /* user space */ + struct serial_icounter_struct __user *p_cuser; unsigned long templ; + void __user *argp = (void __user *)arg; if (PORTNO(tty) == MXSER_PORTS) return (mxser_ioctl_special(cmd, arg)); @@ -1003,20 +1008,20 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4); return (0); case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg); + return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); case TIOCSSOFTCAR: - if(get_user(templ, (unsigned long *) arg)) + if(get_user(templ, (unsigned long __user *) arg)) return -EFAULT; arg = templ; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return (0); case TIOCGSERIAL: - return (mxser_get_serial_info(info, (struct serial_struct *) arg)); + return mxser_get_serial_info(info, argp); case TIOCSSERIAL: - return (mxser_set_serial_info(info, (struct serial_struct *) arg)); + return mxser_set_serial_info(info, argp); case TIOCSERGETLSR: /* Get line status register */ - return (mxser_get_lsr_info(info, (unsigned int *) arg)); + return mxser_get_lsr_info(info, argp); /* * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change * - mask passed in arg for lines of interest @@ -1060,7 +1065,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, cli(); cnow = info->icount; restore_flags(flags); - p_cuser = (struct serial_icounter_struct *) arg; + p_cuser = argp; if(put_user(cnow.cts, &p_cuser->cts)) return -EFAULT; if(put_user(cnow.dsr, &p_cuser->dsr)) @@ -1069,7 +1074,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, return -EFAULT; return put_user(cnow.dcd, &p_cuser->dcd); case MOXA_HighSpeedOn: - return put_user(info->baud_base != 115200 ? 1 : 0, (int *) arg); + return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); default: return (-ENOIOCTLCMD); } @@ -1079,21 +1084,22 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, static int mxser_ioctl_special(unsigned int cmd, unsigned long arg) { int i, result, status; + void __user *argp = (void __user *)arg; switch (cmd) { case MOXA_GET_CONF: - if(copy_to_user((struct mxser_hwconf *) arg, mxsercfg, + if(copy_to_user(argp, mxsercfg, sizeof(struct mxser_hwconf) * 4)) return -EFAULT; return 0; case MOXA_GET_MAJOR: - if(copy_to_user((int *) arg, &ttymajor, sizeof(int))) + if(copy_to_user(argp, &ttymajor, sizeof(int))) return -EFAULT; return 0; case MOXA_GET_CUMAJOR: result = 0; - if(copy_to_user((int *) arg, &result, sizeof(int))) + if(copy_to_user(argp, &result, sizeof(int))) return -EFAULT; return 0; @@ -1103,9 +1109,9 @@ static int mxser_ioctl_special(unsigned int cmd, unsigned long arg) if (mxvar_table[i].base) result |= (1 << i); } - return put_user(result, (unsigned long *) arg); + return put_user(result, (unsigned long __user *) argp); case MOXA_GETDATACOUNT: - if(copy_to_user((struct mxser_log *) arg, &mxvar_log, sizeof(mxvar_log))) + if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) return -EFAULT; return (0); case MOXA_GETMSTATUS: @@ -1139,7 +1145,7 @@ static int mxser_ioctl_special(unsigned int cmd, unsigned long arg) else GMStatus[i].cts = 0; } - if(copy_to_user((struct mxser_mstatus *) arg, GMStatus, + if(copy_to_user(argp, GMStatus, sizeof(struct mxser_mstatus) * MXSER_PORTS)) return -EFAULT; return 0; @@ -1289,73 +1295,10 @@ void mxser_hangup(struct tty_struct *tty) info->event = 0; info->count = 0; info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = 0; + info->tty = NULL; wake_up_interruptible(&info->open_wait); } -/* - * This is the serial driver's generic interrupt routine - */ -static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - int status, i; - struct mxser_struct *info; - struct mxser_struct *port; - int max, irqbits, bits, msr; - int pass_counter = 0; - int handled = 0; - - port = 0; - for (i = 0; i < MXSER_BOARDS; i++) { - if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) { - port = dev_id; - break; - } - } - - if (i == MXSER_BOARDS) - return IRQ_NONE; - if (port == 0) - return IRQ_NONE; - max = mxser_numports[mxsercfg[i].board_type]; - - while (1) { - irqbits = inb(port->vector) & port->vectormask; - if (irqbits == port->vectormask) - break; - handled = 1; - for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { - if (irqbits == port->vectormask) - break; - if (bits & irqbits) - continue; - info = port + i; - if (!info->tty || - (inb(info->base + UART_IIR) & UART_IIR_NO_INT)) - continue; - status = inb(info->base + UART_LSR) & info->read_status_mask; - if (status & UART_LSR_DR) - mxser_receive_chars(info, &status); - msr = inb(info->base + UART_MSR); - if (msr & UART_MSR_ANY_DELTA) - mxser_check_modem_status(info, msr); - if (status & UART_LSR_THRE) { -/* 8-2-99 by William - if ( info->x_char || (info->xmit_cnt > 0) ) - */ - mxser_transmit_chars(info); - } - } - if (pass_counter++ > MXSER_ISR_PASS_LIMIT) { -#if 0 - printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n"); -#endif - break; /* Prevent infinite loops */ - } - } - return IRQ_RETVAL(handled); -} - static inline void mxser_receive_chars(struct mxser_struct *info, int *status) { @@ -1476,6 +1419,69 @@ static inline void mxser_check_modem_status(struct mxser_struct *info, } } +/* + * This is the serial driver's generic interrupt routine + */ +static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int status, i; + struct mxser_struct *info; + struct mxser_struct *port; + int max, irqbits, bits, msr; + int pass_counter = 0; + int handled = 0; + + port = NULL; + for (i = 0; i < MXSER_BOARDS; i++) { + if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) { + port = dev_id; + break; + } + } + + if (i == MXSER_BOARDS) + return IRQ_NONE; + if (port == 0) + return IRQ_NONE; + max = mxser_numports[mxsercfg[i].board_type]; + + while (1) { + irqbits = inb(port->vector) & port->vectormask; + if (irqbits == port->vectormask) + break; + handled = 1; + for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { + if (irqbits == port->vectormask) + break; + if (bits & irqbits) + continue; + info = port + i; + if (!info->tty || + (inb(info->base + UART_IIR) & UART_IIR_NO_INT)) + continue; + status = inb(info->base + UART_LSR) & info->read_status_mask; + if (status & UART_LSR_DR) + mxser_receive_chars(info, &status); + msr = inb(info->base + UART_MSR); + if (msr & UART_MSR_ANY_DELTA) + mxser_check_modem_status(info, msr); + if (status & UART_LSR_THRE) { +/* 8-2-99 by William + if ( info->x_char || (info->xmit_cnt > 0) ) + */ + mxser_transmit_chars(info); + } + } + if (pass_counter++ > MXSER_ISR_PASS_LIMIT) { +#if 0 + printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n"); +#endif + break; /* Prevent infinite loops */ + } + } + return IRQ_RETVAL(handled); +} + static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, struct mxser_struct *info) { @@ -1653,7 +1659,7 @@ static int mxser_startup(struct mxser_struct *info) /* * and set the speed of the serial port */ - mxser_change_speed(info, 0); + mxser_change_speed(info, NULL); info->flags |= ASYNC_INITIALIZED; restore_flags(flags); @@ -1685,7 +1691,7 @@ static void mxser_shutdown(struct mxser_struct *info) */ if (info->xmit_buf) { free_page((unsigned long) info->xmit_buf); - info->xmit_buf = 0; + info->xmit_buf = NULL; } info->IER = 0; outb(0x00, info->base + UART_IER); /* disable all intrs */ @@ -2036,7 +2042,7 @@ static int mxser_change_speed(struct mxser_struct *info, * ------------------------------------------------------------ */ static int mxser_get_serial_info(struct mxser_struct *info, - struct serial_struct *retinfo) + struct serial_struct __user *retinfo) { struct serial_struct tmp; @@ -2057,7 +2063,7 @@ static int mxser_get_serial_info(struct mxser_struct *info, } static int mxser_set_serial_info(struct mxser_struct *info, - struct serial_struct *new_info) + struct serial_struct __user *new_info) { struct serial_struct new_serial; unsigned int flags; @@ -2098,7 +2104,7 @@ static int mxser_set_serial_info(struct mxser_struct *info, if (info->flags & ASYNC_INITIALIZED) { if (flags != (info->flags & ASYNC_SPD_MASK)) { - mxser_change_speed(info, 0); + mxser_change_speed(info, NULL); } } else retval = mxser_startup(info); @@ -2115,7 +2121,7 @@ static int mxser_set_serial_info(struct mxser_struct *info, * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. */ -static int mxser_get_lsr_info(struct mxser_struct *info, unsigned int *value) +static int mxser_get_lsr_info(struct mxser_struct *info, unsigned int __user *value) { unsigned char status; unsigned int result;