📄 jpt_driver.c
字号:
#include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/errno.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/serial.h>#include <linux/serial_reg.h>#include <linux/major.h>#include <linux/string.h>#include <linux/fcntl.h>#include <linux/fs.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/smp_lock.h>#include <linux/pci.h>#include <linux/timer.h>#include <linux/syscalls.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/bitops.h>#include <asm/uaccess.h>#include <asm/delay.h>#include "jpt_core.h"#define NUART_VERSION "1.0"#define PCI_VENDOR_ID_NUART 0x10EE#define PCI_DEVICE_ID_NUART 0x0100#define NUARTMAJOR 184#define NUART_BOARDS 5 /* Max. boards */#define NUART_PORTS 80 /* Max. ports */#define NUART_PORTS_PER_BOARD 16 /* Max. ports per board */#define WAKEUP_CHARS 256 #define VERSION_CODE(ver,rel,seq) ((ver << 16) | (rel << 8) | seq)static char *nuart_typename[] = { "rs232", "rs485", "rs422/rs485", "rs232/rs422/rs485"};struct nuart_hwconf { int board_type; int ports; unsigned long ioaddr_base; long baud_base; struct pci_dev *pdev;};struct nuart_struct { int port; unsigned long base; /* port base address */ int baud_base; /* max. speed */ int type; int mode; int flags; /* defined in tty.h */ struct tty_struct *tty; int x_char; /* xon/xoff character */ int close_delay; unsigned short closing_wait; unsigned long event; int count; /* # of fd on device */ int blocked_open; /* # of blocked opens */ int xmit_fifo_size; unsigned char *xmit_buf; int xmit_head; int xmit_tail; int xmit_cnt; unsigned char rrp; unsigned char rwp; unsigned char trp; unsigned char twp; char wbl[4]; /* register shadow */ struct nuart_reg reg; unsigned long read_status_mask; unsigned long ignore_status_mask;#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,0)) struct tq_struct tqueue;#else struct work_struct tqueue;#endif int cflag; unsigned long lflag; /* local flag */#if (LINUX_VERSION_CODE < VERSION_CODE(2,4,0)) struct wait_queue *open_wait; struct wait_queue *close_wait; struct wait_queue *delta_msr_wait;#else wait_queue_head_t open_wait; wait_queue_head_t close_wait; wait_queue_head_t delta_msr_wait;#endif struct async_icount icount; spinlock_t lock; long session; /* Session of opening process */ long pgrp; /* pgrp of opening process */ int timeout; int fifo_size; void (* receive_func)(struct nuart_struct *, unsigned long); void (* transmit_func)(struct nuart_struct *);};/* local flag */#define NUART_LFLAG_MSI 0x01#define NUART_LFLAG_RLSI 0x02#define NUART_LFLAG_THRI 0x04#define NUART_LFLAG_RDI 0x08/* REGISTER */#define NUART_PCR 0x200#define NUART_XPR 0x204#define NUART_BR 0x208#define NUART_MPR 0x20C#define NUART_PR 0x210/* NUART_PCR */#define NUART_CHE (1<<31)#define NUART_OCLR (1<<26)#define NUART_OSUSP (1<<25)#define NUART_PXOFF (1<<24)#define NUART_PXON (1<<23)#define NUART_BC (1<<22)#define NUART_BZO (1<<21)#define NUART_BZ (1<<20)#define NUART_ERRC (1<<19)#define NUART_RXX (1<<18)#define NUART_IXA (1<<17)#define NUART_IX (1<<16)#define NUART_CXOFF (1<<15)#define NUART_OX (1<<14)#define NUART_OCTS (1<<13)#define NUART_ODSR (1<<12)#define NUART_RTSC_LOW 0#define NUART_RTSC_HIGH (1<<10)#define NUART_RTSC_FLOW (2<<10)#define NUART_RTSC_TOG (3<<10)#define NUART_RTSC_MASK (3<<10)#define NUART_DTRC_LOW 0#define NUART_DTRC_HIGH (1<<8)#define NUART_DTRC_FLOW (2<<8)#define NUART_DTRC_TOG (3<<8)#define NUART_DTRC_MASK (3<<8)#define NUART_OBRK (1<<7)#define NUART_P_ODD 0#define NUART_P_EVEN (1<<5)#define NUART_P_MARK (2<<5)#define NUART_P_SPACE (3<<5)#define NUART_P_MASK (3<<5)#define NUART_PEN (1<<4)#define NUART_SBITS (1<<3)/* NUART_MPR */#define NUART_RXOFF (1<<24)#define NUART_TBUSY (1<<23)#define NUART_PERR (1<<22)#define NUART_FERR (1<<21)#define NUART_IBRK (1<<20)#define NUART_DCD (1<<19)#define NUART_RI (1<<18)#define NUART_DSR (1<<17)#define NUART_CTS (1<<16)#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))#define PORTNO(x) ((x)->index)#ifndef MIN#define MIN(a,b) ((a) < (b) ? (a) : (b))#endif#define SERIAL_TYPE_NORMAL 1#define NUART_EVENT_TXLOW 1#define NUART_EVENT_HANGUP 2static int ttymajor = NUARTMAJOR;static int verbose = 1;/* Variables for insmod */MODULE_AUTHOR("newtry");MODULE_DESCRIPTION("NewTry");MODULE_LICENSE("GPL");MODULE_PARM(ttymajor, "i");MODULE_PARM(verbose, "i");static struct tty_driver *nuvar_sdriver;static struct nuart_struct nuvar_table[NUART_PORTS];static unsigned char *nuvar_tmp_buf;static struct semaphore nuvar_tmp_buf_sem;static struct timer_list nuart_timer;struct nuart_hwconf nuartcfg[NUART_BOARDS];/* baud max 1.8432MHZ */static int nuart_baud_table[] ={ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 0 };static struct pci_device_id nuart_pcibrds[] = { { PCI_VENDOR_ID_NUART, PCI_DEVICE_ID_NUART, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NUART_BOARD_RS232}, { 0 }};MODULE_DEVICE_TABLE(pci, nuart_pcibrds);static int nuart_open(struct tty_struct *, struct file *);static void nuart_close(struct tty_struct *, struct file *);#if (LINUX_VERSION_CODE < VERSION_CODE(2,6,10))static int nuart_write(struct tty_struct *, int, const unsigned char *, int);#elsestatic int nuart_write(struct tty_struct *, const unsigned char *, int);#endifstatic int nuart_write_room(struct tty_struct *);static void nuart_flush_buffer(struct tty_struct *);static int nuart_chars_in_buffer(struct tty_struct *);static void nuart_flush_chars(struct tty_struct *);static void nuart_put_char(struct tty_struct *, unsigned char);static int nuart_ioctl(struct tty_struct *, struct file *, uint, ulong);static void nuart_throttle(struct tty_struct *);static void nuart_unthrottle(struct tty_struct *);static void nuart_set_termios(struct tty_struct *, struct termios *);static void nuart_stop(struct tty_struct *);static void nuart_start(struct tty_struct *);static void nuart_hangup(struct tty_struct *);static void nuart_receive_chars(struct nuart_struct *, unsigned long);static void nuart_transmit_chars(struct nuart_struct *);static void nuart16_receive_chars(struct nuart_struct *, unsigned long);static void nuart16_transmit_chars(struct nuart_struct *);static int nuart_block_til_ready(struct tty_struct *, struct file *, struct nuart_struct *);static int nuart_startup(struct nuart_struct *);static void nuart_shutdown(struct nuart_struct *);static int nuart_change_speed(struct nuart_struct *, struct termios *old_termios);static int nuart_get_serial_info(struct nuart_struct *, struct serial_struct *);static int nuart_set_serial_info(struct nuart_struct *, struct serial_struct *);static int nuart_get_lsr_info(struct nuart_struct *, unsigned int *);static void nuart_send_break(struct nuart_struct *, int);static int nuart_tiocmget(struct tty_struct * tty, struct file * file);static int nuart_tiocmset(struct tty_struct *tty, struct file * file, unsigned int set, unsigned int clear);//static int nuart_get_modem_info(struct nuart_struct *, unsigned int *);//static int nuart_set_modem_info(struct nuart_struct *, unsigned int, unsigned int *);static void nuart_timeout(unsigned long ptr);static void nuart_do_softint(void *private_);static int nuart_pci_probe(void);static void nuart_check_modem_status(struct nuart_struct *info, unsigned long status){ int delta_dcd = 0; if((info->reg.mpr & NUART_RI) != (status & NUART_RI)) info->icount.rng++; if((info->reg.mpr & NUART_DSR) != (status & NUART_DSR)) info->icount.dsr++; if((info->reg.mpr & NUART_DCD) != (status & NUART_DCD)) { info->icount.dcd++; delta_dcd = 1; } if((info->reg.mpr & NUART_CTS) != (status & NUART_CTS)) info->icount.cts++; wake_up_interruptible(&info->delta_msr_wait); if ( (info->flags & ASYNC_CHECK_CD) && delta_dcd ) { if ( status & NUART_DCD ) wake_up_interruptible(&info->open_wait); else { set_bit(NUART_EVENT_HANGUP, &info->event); schedule_work(&info->tqueue); } } if ( info->flags & ASYNC_CTS_FLOW ) { if ( info->tty->hw_stopped ) { if (status & NUART_CTS ) { info->tty->hw_stopped = 0; set_bit(NUART_EVENT_TXLOW, &info->event); schedule_work(&info->tqueue); } } else { if ( !(status & NUART_CTS) ) { info->tty->hw_stopped = 1; } } }}static void nuart_receive_chars(struct nuart_struct *info, unsigned long stat){ struct tty_struct *tty = info->tty; unsigned char rbuf[260]; unsigned long tmprrp; int count, pad, i; unsigned long status = stat; unsigned long flags = 0; count = (info->rwp - info->rrp) & 0xff; count = MIN(count, TTY_FLIPBUF_SIZE - tty->flip.count); if(!count) return; pad = info->rrp & 3; tmprrp = info->rrp & (~3); spin_lock_irqsave(&info->lock, flags); nuart_read_buf(info->base,tmprrp, rbuf, pad+count); spin_unlock_irqrestore(&info->lock, flags); for (i = pad; i < count + pad; i++) { tty->flip.count++; if(status & (NUART_PERR | NUART_FERR | NUART_IBRK)) { if (status & NUART_IBRK) { *tty->flip.flag_buf_ptr++ = TTY_BREAK; info->icount.brk++; if ( info->flags & ASYNC_SAK ) do_SAK(tty); status &= ~NUART_IBRK; } else if (status & NUART_PERR) { *tty->flip.flag_buf_ptr++ = TTY_PARITY; info->icount.parity++; status &= ~NUART_PERR; } else if (status & NUART_FERR) { *tty->flip.flag_buf_ptr++ = TTY_FRAME; info->icount.frame++; status &= ~NUART_FERR; } else *tty->flip.flag_buf_ptr++ = TTY_NORMAL; } else *tty->flip.flag_buf_ptr++ = TTY_NORMAL; *tty->flip.char_buf_ptr++ = rbuf[i]; } info->icount.rx += count; info->rrp += count;// schedule_delayed_work(&tty->flip.work, 1); tty_flip_buffer_push(tty); spin_lock_irqsave(&info->lock, flags); nuart_set_rrp(info->base, &info->reg, info->rrp); if(stat & (NUART_PERR | NUART_FERR | NUART_IBRK)) nuart_clr_err(info->base, &info->reg); spin_unlock_irqrestore(&info->lock, flags); return;}static void nuart16_receive_chars(struct nuart_struct *info, unsigned long stat){ struct tty_struct *tty = info->tty; unsigned char rbuf[260]; unsigned long tmprrp; int count, pad, i; unsigned long status = stat; unsigned long flags = 0; count = (info->rwp - info->rrp) & 0x7f; count = MIN(count, TTY_FLIPBUF_SIZE - tty->flip.count); if(!count) return; pad = info->rrp & 3; tmprrp = info->rrp & (~3); spin_lock_irqsave(&info->lock, flags); nuart_read_buf(info->base,tmprrp, rbuf, pad+count); spin_unlock_irqrestore(&info->lock, flags); for (i = pad; i < count + pad; i++) { tty->flip.count++; if(status & (NUART_PERR | NUART_FERR | NUART_IBRK)) { if (status & NUART_IBRK) { *tty->flip.flag_buf_ptr++ = TTY_BREAK; info->icount.brk++; if ( info->flags & ASYNC_SAK ) do_SAK(tty); status &= ~NUART_IBRK; } else if (status & NUART_PERR) { *tty->flip.flag_buf_ptr++ = TTY_PARITY; info->icount.parity++; status &= ~NUART_PERR; } else if (status & NUART_FERR) { *tty->flip.flag_buf_ptr++ = TTY_FRAME; info->icount.frame++; status &= ~NUART_FERR; } else *tty->flip.flag_buf_ptr++ = TTY_NORMAL; } else *tty->flip.flag_buf_ptr++ = TTY_NORMAL; *tty->flip.char_buf_ptr++ = rbuf[i]; } info->icount.rx += count; info->rrp += count;// schedule_delayed_work(&tty->flip.work, 1); tty_flip_buffer_push(tty); spin_lock_irqsave(&info->lock, flags); nuart_set_rrp(info->base, &info->reg, info->rrp); if(stat & (NUART_PERR | NUART_FERR | NUART_IBRK)) nuart_clr_err(info->base, &info->reg); spin_unlock_irqrestore(&info->lock, flags); return;}static void nuart_transmit_chars(struct nuart_struct *info){ int count, i; int wbl_pos; int buf_pos; char tbuf[256]; int c; unsigned long flags = 0; count = 248 - ((info->twp - info->trp) & 0xff); count = MIN(info->xmit_cnt, count); if(count <= 0) return; wbl_pos = info->twp & 3; buf_pos = info->twp & (~3); if(wbl_pos) memcpy(tbuf,info->wbl,wbl_pos); for(i = wbl_pos;i < count + wbl_pos; i++) { c = info->xmit_buf[info->xmit_tail++];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -