📄 jpt_driver.c
字号:
} } if(info->tty->termios->c_iflag & IXON) { nuart_set_xchar(info->base, &info->reg, START_CHAR(info->tty), STOP_CHAR(info->tty)); pcr |= (NUART_OX | NUART_IX); } else { pcr_mask |= (NUART_OX | NUART_IX); } if (cflag & CLOCAL) info->flags &= ~ASYNC_CHECK_CD; else info->flags |= ASYNC_CHECK_CD; /* set up parity check flag */ info->read_status_mask = 0; if(I_INPCK(info->tty)) info->read_status_mask |= (NUART_FERR | NUART_PERR); if(I_BRKINT(info->tty) || I_PARMRK(info->tty)) info->read_status_mask |= NUART_IBRK; info->ignore_status_mask = 0; if(I_IGNBRK(info->tty)) { info->read_status_mask |= NUART_IBRK; info->ignore_status_mask |= NUART_IBRK; if(I_IGNPAR(info->tty)) { info->ignore_status_mask |= (NUART_PERR | NUART_FERR); info->read_status_mask |= (NUART_PERR | NUART_FERR); } } if(quot == 0 || quot == 1) { pcr |= NUART_BZO; if(quot == 0) pcr |= NUART_BZ; } pcr_mask |= (NUART_P_MASK | NUART_SBITS | NUART_PEN | 7); info->reg.pcr &= ~pcr_mask; info->reg.pcr |= pcr; spin_lock_irqsave(&info->lock, flags); nuart_set_pcr(info->base, &info->reg, info->reg.pcr); nuart_baud(info->base, &info->reg, quot); spin_unlock_irqrestore(&info->lock, flags); return ret;}static int nuart_block_til_ready(struct tty_struct *tty, struct file *filp, struct nuart_struct *info){ DECLARE_WAITQUEUE(wait, current); unsigned long flags; int retval; int do_clocal = 0; /* * If the device is in the middle of being closed, then block * until it's done, and then try again. *//* if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { if (info->flags & ASYNC_CLOSING) interruptible_sleep_on(&info->close_wait);#ifdef SERIAL_DO_RESTART if (info->flags & ASYNC_HUP_NOTIFY) return (-EAGAIN); else return (-ERESTARTSYS);#else return (-EAGAIN);#endif }*/ /* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { info->flags |= ASYNC_NORMAL_ACTIVE; return (0); } if (tty->termios->c_cflag & CLOCAL) do_clocal = 1; retval = 0; add_wait_queue(&info->open_wait, &wait); spin_lock_irqsave(&info->lock, flags); if (!tty_hung_up_p(filp)) info->count--; spin_unlock_irqrestore(&info->lock, flags); info->blocked_open++; while (1) { spin_lock_irqsave(&info->lock, flags); nuart_dtr(info->base, &info->reg, 1); nuart_rts(info->base, &info->reg, 1); spin_unlock_irqrestore(&info->lock, flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) {#ifdef SERIAL_DO_RESTART if (info->flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS;#else retval = -EAGAIN;#endif break; } info->reg.mpr = nuart_get_stat(info->base); if (!(info->flags & ASYNC_CLOSING) && (do_clocal || (info->reg.mpr & NUART_DCD))) break; if (signal_pending(current)) { retval = -ERESTARTSYS; break; } schedule(); } set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); if (!tty_hung_up_p(filp)) info->count++; info->blocked_open--; if (retval) return (retval); info->flags |= ASYNC_NORMAL_ACTIVE; return (0);}static void nuart_close(struct tty_struct *tty, struct file *filp){ struct nuart_struct *info = (struct nuart_struct *) tty->driver_data; unsigned long flags, timeout; if (PORTNO(tty) == NUART_PORTS) return; if (!info || !info->base) return; spin_lock_irqsave(&info->lock, flags); if (tty_hung_up_p(filp)) { spin_unlock_irqrestore(&info->lock, flags); return; } if ((tty->count == 1) && (info->count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty * structure will be freed. Info->count should always * be one in these conditions. If it's greater than * one, we've got real problems, since it means the * serial port won't be shutdown. */ printk("nuart_close: bad serial port count; tty->count is 1, " "info->count is %d\n", info->count); info->count = 1; } if (--info->count < 0) { printk("nuart_close: bad serial port count for ttys%d: %d\n", info->port, info->count); info->count = 0; } if (info->count) { spin_unlock_irqrestore(&info->lock, flags); return; } info->flags |= ASYNC_CLOSING; spin_unlock_irqrestore(&info->lock, flags); info->cflag = tty->termios->c_cflag; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) tty_wait_until_sent(tty, info->closing_wait); if(info->flags & ASYNC_INITIALIZED) { timeout = jiffies + HZ; spin_lock_irqsave(&info->lock, flags); info->reg.mpr = nuart_get_stat(info->base); spin_unlock_irqrestore(&info->lock, flags); while(info->reg.mpr & NUART_TBUSY) { spin_lock_irqsave(&info->lock, flags); info->reg.mpr = nuart_get_stat(info->base); spin_unlock_irqrestore(&info->lock, flags); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(5); if(time_after(jiffies, timeout)) break; } } nuart_shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); tty->closing = 0; info->tty = 0; info->event = 0; if (info->blocked_open) { if (info->close_delay) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(info->close_delay); } wake_up_interruptible(&info->open_wait); } info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&info->close_wait);}static void nuart_shutdown(struct nuart_struct *info){ unsigned long flags = 0; if (!(info->flags & ASYNC_INITIALIZED)) return; spin_lock_irqsave(&info->lock, flags); /* * clear delta_msr_wait queue to avoid mem leaks: we may free the irq * here so the queue might never be waken up */ wake_up_interruptible(&info->delta_msr_wait); if (info->xmit_buf) { free_page((unsigned long) info->xmit_buf); info->xmit_buf = 0; } if(!info->tty || (info->tty->termios->c_cflag & HUPCL)) info->reg.pcr &= ~(NUART_RTSC_HIGH | NUART_DTRC_HIGH); nuart_port_disable(info->base, &info->reg); if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); info->flags &= ~ASYNC_INITIALIZED; spin_unlock_irqrestore(&info->lock, flags);}int nuart_initbrd(int board, struct nuart_hwconf *hwconf){ struct nuart_struct *info; int i, n; nuart_card_disable(hwconf->ioaddr_base); n = board * NUART_PORTS_PER_BOARD; info = &nuvar_table[n]; for (i = 0; i < hwconf->ports; i++, n++, info++) { memset(info, 0, sizeof(struct nuart_struct)); info->port = n; info->base = hwconf->ioaddr_base + i*1024; info->type = hwconf->board_type; nuart_port_initial(info->base, &info->reg); info->baud_base = hwconf->baud_base; info->flags = 0; info->close_delay = 5 * HZ / 10; info->closing_wait = 30 * HZ; INIT_WORK(&info->tqueue, nuart_do_softint, info); info->cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->delta_msr_wait); spin_lock_init(&info->lock); if(hwconf->ports >= 16) { info->fifo_size = 128; info->receive_func = nuart16_receive_chars; info->transmit_func = nuart16_transmit_chars; } else { info->fifo_size = 256; info->receive_func = nuart_receive_chars; info->transmit_func = nuart_transmit_chars; } } nuart_card_enable(hwconf->ioaddr_base); return 0;}static int nuart_pci_probe(void){ struct pci_dev *pdev = NULL; struct nuart_hwconf hwconf; int n, b; int card_found = 0; unsigned long ioaddress; u32 id; n = (sizeof(nuart_pcibrds) / sizeof(nuart_pcibrds[0])) - 1; for (b = 0; b < n; b++) { while ((pdev = pci_find_device(nuart_pcibrds[b].vendor, nuart_pcibrds[b].device, pdev))) { if (pci_enable_device(pdev)) continue; printk("Found Jpt board(BusNo=%d,DevNo=%d)\n", pdev->bus->number, PCI_SLOT(pdev->devfn)); if(card_found >= NUART_BOARDS) { printk("Too many Jpt Serial boards find (maximum %d),board not configured\n",NUART_BOARDS); goto PROBE_OUT; } memset(&hwconf, 0, sizeof(struct nuart_hwconf)); hwconf.pdev = pdev; ioaddress = pci_resource_start (pdev, 0); if(!ioaddress) continue; hwconf.ioaddr_base = (unsigned long)ioremap(ioaddress, 65536); if (!hwconf.ioaddr_base) continue; pci_read_config_dword(pdev, 0x2c, &id); nuart_get_config(id, &hwconf.board_type, &hwconf.ports); if(!hwconf.ports) continue; if(hwconf.board_type == -1) continue; if(hwconf.ports <= 8) hwconf.baud_base = 14745600/8; else hwconf.baud_base = 14745600/hwconf.ports; printk("type = %s, port = %d, baud base = %ld\n", nuart_typename[hwconf.board_type], hwconf.ports, hwconf.baud_base); if (nuart_initbrd(card_found, &hwconf) < 0) continue; memcpy(&nuartcfg[card_found], &hwconf, sizeof(struct nuart_hwconf)); card_found ++; } }PROBE_OUT: return card_found;}static struct tty_operations nuart_ops = { .open = nuart_open, .close = nuart_close, .write = nuart_write, .put_char = nuart_put_char, .flush_chars = nuart_flush_chars, .write_room = nuart_write_room, .chars_in_buffer = nuart_chars_in_buffer, .flush_buffer = nuart_flush_buffer, .ioctl = nuart_ioctl, .throttle = nuart_throttle, .unthrottle = nuart_unthrottle, .set_termios = nuart_set_termios, .stop = nuart_stop, .start = nuart_start, .hangup = nuart_hangup, .tiocmget = nuart_tiocmget, .tiocmset = nuart_tiocmset,};static int __init nuart_module_init(void){ int i, m; nuvar_sdriver = alloc_tty_driver(NUART_PORTS + 1); if (!nuvar_sdriver) return -ENOMEM; printk("Jpt serial driver version %s\n", NUART_VERSION); /* Initialize the tty_driver structure */ nuvar_sdriver->owner = THIS_MODULE; nuvar_sdriver->name = "ttyN"; nuvar_sdriver->devfs_name = "tts/M"; nuvar_sdriver->major = ttymajor; nuvar_sdriver->minor_start = 0; nuvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; nuvar_sdriver->subtype = SERIAL_TYPE_NORMAL; nuvar_sdriver->init_termios = tty_std_termios; nuvar_sdriver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; nuvar_sdriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(nuvar_sdriver, &nuart_ops); printk("Tty devices major number = %d\n", ttymajor); memset(nuvar_table, 0, NUART_PORTS * sizeof(struct nuart_struct)); for (i = 0; i < NUART_BOARDS; i++) { nuartcfg[i].board_type = -1; } m = 0; /* start finding PCI board here */#ifdef CONFIG_PCI m = nuart_pci_probe();#endif if(m == 0) printk("No Jpt card founded in yout system!\n"); if(m <= 0) goto init_err_out; init_MUTEX(&nuvar_tmp_buf_sem); init_timer(&nuart_timer); if (!tty_register_driver(nuvar_sdriver)) { nuart_timer.function = nuart_timeout; nuart_timer.data = (unsigned long)0; nuart_timer.expires = jiffies + 1; add_timer(&nuart_timer); return 0; } printk("Couldn't install Jpt driver !\n");init_err_out: put_tty_driver(nuvar_sdriver); for (i = 0; i < NUART_BOARDS; i++) { if (nuartcfg[i].board_type == -1) continue; if (nuartcfg[i].ioaddr_base) iounmap((void *)(nuartcfg[i].ioaddr_base)); } return -1;}static void __exit nuart_module_exit(void){ int i, err = 0; if (verbose) printk("Unloading module Jpt..."); del_timer(&nuart_timer); if ((err |= tty_unregister_driver(nuvar_sdriver))) printk("Couldn't unregister Jpt serial driver\n"); put_tty_driver(nuvar_sdriver); for (i = 0; i < NUART_BOARDS; i++) { if (nuartcfg[i].board_type == -1) continue; if(nuartcfg[i].ioaddr_base) { iounmap((void *)(nuartcfg[i].ioaddr_base)); } } if (verbose) printk("Done.\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -