📄 stallion.c
字号:
static void stl_putchar(struct tty_struct *tty, unsigned char ch);static void stl_flushchars(struct tty_struct *tty);static int stl_writeroom(struct tty_struct *tty);static int stl_charsinbuffer(struct tty_struct *tty);static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);static void stl_settermios(struct tty_struct *tty, struct termios *old);static void stl_throttle(struct tty_struct *tty);static void stl_unthrottle(struct tty_struct *tty);static void stl_stop(struct tty_struct *tty);static void stl_start(struct tty_struct *tty);static void stl_flushbuffer(struct tty_struct *tty);static void stl_breakctl(struct tty_struct *tty, int state);static void stl_waituntilsent(struct tty_struct *tty, int timeout);static void stl_sendxchar(struct tty_struct *tty, char ch);static void stl_hangup(struct tty_struct *tty);static int stl_memopen(struct inode *ip, struct file *fp);static int stl_memclose(struct inode *ip, struct file *fp);static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);static int stl_portinfo(stlport_t *portp, int portnr, char *pos);static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data);static int stl_brdinit(stlbrd_t *brdp);static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);static int stl_mapirq(int irq, char *name);static void stl_getserial(stlport_t *portp, struct serial_struct *sp);static int stl_setserial(stlport_t *portp, struct serial_struct *sp);static int stl_getbrdstats(combrd_t *bp);static int stl_getportstats(stlport_t *portp, comstats_t *cp);static int stl_clrportstats(stlport_t *portp, comstats_t *cp);static int stl_getportstruct(unsigned long arg);static int stl_getbrdstruct(unsigned long arg);static int stl_waitcarrier(stlport_t *portp, struct file *filp);static void stl_delay(int len);static void stl_intr(int irq, void *dev_id, struct pt_regs *regs);static void stl_eiointr(stlbrd_t *brdp);static void stl_echatintr(stlbrd_t *brdp);static void stl_echmcaintr(stlbrd_t *brdp);static void stl_echpciintr(stlbrd_t *brdp);static void stl_echpci64intr(stlbrd_t *brdp);static void stl_offintr(void *private);static void *stl_memalloc(int len);static stlbrd_t *stl_allocbrd(void);static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);static inline int stl_initbrds(void);static inline int stl_initeio(stlbrd_t *brdp);static inline int stl_initech(stlbrd_t *brdp);static inline int stl_getbrdnr(void);#ifdef CONFIG_PCIstatic inline int stl_findpcibrds(void);static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp);#endif/* * CD1400 uart specific handling functions. */static void stl_cd1400setreg(stlport_t *portp, int regnr, int value);static int stl_cd1400getreg(stlport_t *portp, int regnr);static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value);static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp);static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp);static int stl_cd1400getsignals(stlport_t *portp);static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts);static void stl_cd1400ccrwait(stlport_t *portp);static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx);static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx);static void stl_cd1400disableintrs(stlport_t *portp);static void stl_cd1400sendbreak(stlport_t *portp, int len);static void stl_cd1400flowctrl(stlport_t *portp, int state);static void stl_cd1400sendflow(stlport_t *portp, int state);static void stl_cd1400flush(stlport_t *portp);static int stl_cd1400datastate(stlport_t *portp);static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase);static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase);static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr);static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr);static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr);static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr);/* * SC26198 uart specific handling functions. */static void stl_sc26198setreg(stlport_t *portp, int regnr, int value);static int stl_sc26198getreg(stlport_t *portp, int regnr);static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value);static int stl_sc26198getglobreg(stlport_t *portp, int regnr);static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp);static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp);static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp);static int stl_sc26198getsignals(stlport_t *portp);static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts);static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx);static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx);static void stl_sc26198disableintrs(stlport_t *portp);static void stl_sc26198sendbreak(stlport_t *portp, int len);static void stl_sc26198flowctrl(stlport_t *portp, int state);static void stl_sc26198sendflow(stlport_t *portp, int state);static void stl_sc26198flush(stlport_t *portp);static int stl_sc26198datastate(stlport_t *portp);static void stl_sc26198wait(stlport_t *portp);static void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty);static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase);static void stl_sc26198txisr(stlport_t *port);static void stl_sc26198rxisr(stlport_t *port, unsigned int iack);static void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch);static void stl_sc26198rxbadchars(stlport_t *portp);static void stl_sc26198otherisr(stlport_t *port, unsigned int iack);/*****************************************************************************//* * Generic UART support structure. */typedef struct uart { int (*panelinit)(stlbrd_t *brdp, stlpanel_t *panelp); void (*portinit)(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); void (*setport)(stlport_t *portp, struct termios *tiosp); int (*getsignals)(stlport_t *portp); void (*setsignals)(stlport_t *portp, int dtr, int rts); void (*enablerxtx)(stlport_t *portp, int rx, int tx); void (*startrxtx)(stlport_t *portp, int rx, int tx); void (*disableintrs)(stlport_t *portp); void (*sendbreak)(stlport_t *portp, int len); void (*flowctrl)(stlport_t *portp, int state); void (*sendflow)(stlport_t *portp, int state); void (*flush)(stlport_t *portp); int (*datastate)(stlport_t *portp); void (*intr)(stlpanel_t *panelp, unsigned int iobase);} uart_t;/* * Define some macros to make calling these functions nice and clean. */#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)#define stl_setport (* ((uart_t *) portp->uartp)->setport)#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)#define stl_flush (* ((uart_t *) portp->uartp)->flush)#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)/*****************************************************************************//* * CD1400 UART specific data initialization. */static uart_t stl_cd1400uart = { stl_cd1400panelinit, stl_cd1400portinit, stl_cd1400setport, stl_cd1400getsignals, stl_cd1400setsignals, stl_cd1400enablerxtx, stl_cd1400startrxtx, stl_cd1400disableintrs, stl_cd1400sendbreak, stl_cd1400flowctrl, stl_cd1400sendflow, stl_cd1400flush, stl_cd1400datastate, stl_cd1400eiointr};/* * Define the offsets within the register bank of a cd1400 based panel. * These io address offsets are common to the EasyIO board as well. */#define EREG_ADDR 0#define EREG_DATA 4#define EREG_RXACK 5#define EREG_TXACK 6#define EREG_MDACK 7#define EREG_BANKSIZE 8#define CD1400_CLK 25000000#define CD1400_CLK8M 20000000/* * Define the cd1400 baud rate clocks. These are used when calculating * what clock and divisor to use for the required baud rate. Also * define the maximum baud rate allowed, and the default base baud. */static int stl_cd1400clkdivs[] = { CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4};/*****************************************************************************//* * SC26198 UART specific data initization. */static uart_t stl_sc26198uart = { stl_sc26198panelinit, stl_sc26198portinit, stl_sc26198setport, stl_sc26198getsignals, stl_sc26198setsignals, stl_sc26198enablerxtx, stl_sc26198startrxtx, stl_sc26198disableintrs, stl_sc26198sendbreak, stl_sc26198flowctrl, stl_sc26198sendflow, stl_sc26198flush, stl_sc26198datastate, stl_sc26198intr};/* * Define the offsets within the register bank of a sc26198 based panel. */#define XP_DATA 0#define XP_ADDR 1#define XP_MODID 2#define XP_STATUS 2#define XP_IACK 3#define XP_BANKSIZE 4/* * Define the sc26198 baud rate table. Offsets within the table * represent the actual baud rate selector of sc26198 registers. */static unsigned int sc26198_baudtable[] = { 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800, 921600};#define SC26198_NRBAUDS (sizeof(sc26198_baudtable) / sizeof(unsigned int))/*****************************************************************************//* * Define the driver info for a user level control device. Used mainly * to get at port stats - only not using the port device itself. */static struct file_operations stl_fsiomem = { NULL, /* llseek */ NULL, /* read */ NULL, /* write */ NULL, /* readdir */ NULL, /* poll */ stl_memioctl, /* ioctl */ NULL, /* mmap */ stl_memopen, /* open */ NULL, /* flush */ stl_memclose, /* release */ NULL, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ NULL, /* revalidate */ NULL /* lock */};/*****************************************************************************/#ifdef MODULE/* * Loadable module initialization stuff. */int init_module(){ unsigned long flags;#if DEBUG printk("init_module()\n");#endif save_flags(flags); cli(); stl_init(); restore_flags(flags); return(0);}/*****************************************************************************/void cleanup_module(){ stlbrd_t *brdp; stlpanel_t *panelp; stlport_t *portp; unsigned long flags; int i, j, k;#if DEBUG printk("cleanup_module()\n");#endif printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle, stl_drvversion); save_flags(flags); cli();/* * Free up all allocated resources used by the ports. This includes * memory and interrupts. As part of this process we will also do * a hangup on every open port - to try to flush out any processes * hanging onto ports. */ i = tty_unregister_driver(&stl_serial); j = tty_unregister_driver(&stl_callout); if (i || j) { printk("STALLION: failed to un-register tty driver, " "errno=%d,%d\n", -i, -j); restore_flags(flags); return; } if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) printk("STALLION: failed to un-register serial memory device, " "errno=%d\n", -i); if (stl_tmpwritebuf != (char *) NULL) kfree_s(stl_tmpwritebuf, STL_TXBUFSIZE); for (i = 0; (i < stl_nrbrds); i++) { if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL) continue; for (j = 0; (j < STL_MAXPANELS); j++) { panelp = brdp->panels[j]; if (panelp == (stlpanel_t *) NULL) continue; for (k = 0; (k < STL_PORTSPERPANEL); k++) { portp = panelp->ports[k]; if (portp == (stlport_t *) NULL) continue; if (portp->tty != (struct tty_struct *) NULL) stl_hangup(portp->tty); if (portp->tx.buf != (char *) NULL) kfree_s(portp->tx.buf, STL_TXBUFSIZE); kfree_s(portp, sizeof(stlport_t)); } kfree_s(panelp, sizeof(stlpanel_t)); } release_region(brdp->ioaddr1, brdp->iosize1); if (brdp->iosize2 > 0) release_region(brdp->ioaddr2, brdp->iosize2); kfree_s(brdp, sizeof(stlbrd_t)); stl_brds[i] = (stlbrd_t *) NULL; } for (i = 0; (i < stl_numintrs); i++) free_irq(stl_gotintrs[i], NULL); restore_flags(flags);}/*****************************************************************************//* * Check for any arguments passed in on the module load command line. */static void stl_argbrds(){ stlconf_t conf; stlbrd_t *brdp; int nrargs, i;#if DEBUG printk("stl_argbrds()\n");#endif nrargs = sizeof(stl_brdsp) / sizeof(char **); for (i = stl_nrbrds; (i < nrargs); i++) { memset(&conf, 0, sizeof(conf)); if (stl_parsebrd(&conf, stl_brdsp[i]) == 0) continue; if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL) continue; stl_nrbrds = i + 1; brdp->brdnr = i; brdp->brdtype = conf.brdtype; brdp->ioaddr1 = conf.ioaddr1; brdp->ioaddr2 = conf.ioaddr2; brdp->irq = conf.irq; brdp->irqtype = conf.irqtype; stl_brdinit(brdp); }}/*****************************************************************************//* * Convert an ascii string number into an unsigned long. */static unsigned long stl_atol(char *str){ unsigned long val; int base, c; char *sp; val = 0; sp = str; if ((*sp == '0') && (*(sp+1) == 'x')) { base = 16; sp += 2; } else if (*sp == '0') { base = 8; sp++; } else { base = 10; } for (; (*sp != 0); sp++) { c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0'); if ((c < 0) || (c >= base)) { printk("STALLION: invalid argument %s\n", str); val = 0; break; } val = (val * base) + c; } return(val);}/*****************************************************************************//* * Parse the supplied argument string, into the board conf struct. */static int stl_parsebrd(stlconf_t *confp, char **argp){ char *sp; int nrbrdnames, i;#if DEBUG printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);#endif if ((argp[0] == (char *) NULL) || (*argp[0] == 0)) return(0); for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++) *sp = TOLOWER(*sp); nrbrdnames = sizeof(stl_brdstr) / sizeof(stlbrdtype_t); for (i = 0; (i < nrbrdnames); i++) { if (strcmp(stl_brdstr[i].name, argp[0]) == 0) break; } if (i >= nrbrdnames) { printk("STALLION: unknown board name, %s?\n", argp[0]); return(0); } confp->brdtype = stl_brdstr[i].type; i = 1; if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) confp->ioaddr1 = stl_atol(argp[i]); i++; if (confp->brdtype == BRD_ECH) { if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) confp->ioaddr2 = stl_atol(argp[i]); i++; } if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) confp->irq = stl_atol(argp[i]); return(1);}#endif/*****************************************************************************//* * Local driver kernel memory allocation routine. */static void *stl_memalloc(int len){ return((void *) kmalloc(len, GFP_KERNEL));}/*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -