📄 moxa.c
字号:
short lowwater = 512; ofsAddr = moxa_ports[port].tableAddr; writew(lowwater, ofsAddr + Low_water); moxa_ports[port].breakCnt = 0; if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { moxafunc(ofsAddr, FC_SetBreakIrq, 0); } else { writew(readw(ofsAddr + HostStat) | WakeupBreak, ofsAddr + HostStat); } moxafunc(ofsAddr, FC_SetLineIrq, Magic_code); moxafunc(ofsAddr, FC_FlushQueue, 2); moxafunc(ofsAddr, FC_EnableCH, Magic_code); MoxaPortLineStatus(port);}void MoxaPortDisable(int port){ void __iomem *ofsAddr = moxa_ports[port].tableAddr; moxafunc(ofsAddr, FC_SetFlowCtl, 0); /* disable flow control */ moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code); writew(0, ofsAddr + HostStat); moxafunc(ofsAddr, FC_DisableCH, Magic_code);}long MoxaPortGetMaxBaud(int port){ if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) return (460800L); else return (921600L);}long MoxaPortSetBaud(int port, long baud){ void __iomem *ofsAddr; long max, clock; unsigned int val; if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0)) return (0); ofsAddr = moxa_ports[port].tableAddr; if (baud > max) baud = max; if (max == 38400L) clock = 614400L; /* for 9.8304 Mhz : max. 38400 bps */ else if (max == 57600L) clock = 691200L; /* for 11.0592 Mhz : max. 57600 bps */ else clock = 921600L; /* for 14.7456 Mhz : max. 115200 bps */ val = clock / baud; moxafunc(ofsAddr, FC_SetBaud, val); baud = clock / val; moxa_ports[port].curBaud = baud; return (baud);}int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud){ void __iomem *ofsAddr; tcflag_t cflag; tcflag_t mode = 0; if (moxa_ports[port].chkPort == 0 || termio == 0) return (-1); ofsAddr = moxa_ports[port].tableAddr; cflag = termio->c_cflag; /* termio->c_cflag */ mode = termio->c_cflag & CSIZE; if (mode == CS5) mode = MX_CS5; else if (mode == CS6) mode = MX_CS6; else if (mode == CS7) mode = MX_CS7; else if (mode == CS8) mode = MX_CS8; if (termio->c_cflag & CSTOPB) { if (mode == MX_CS5) mode |= MX_STOP15; else mode |= MX_STOP2; } else mode |= MX_STOP1; if (termio->c_cflag & PARENB) { if (termio->c_cflag & PARODD) mode |= MX_PARODD; else mode |= MX_PAREVEN; } else mode |= MX_PARNONE; moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode); if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { if (baud >= 921600L) return (-1); } MoxaPortSetBaud(port, baud); if (termio->c_iflag & (IXON | IXOFF | IXANY)) { writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); writeb(FC_SetXonXoff, ofsAddr + FuncCode); moxa_wait_finish(ofsAddr); } return (0);}int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState){ if (!MoxaPortIsValid(port)) return (-1); if (dtrState) { if (moxa_ports[port].lineCtrl & DTR_ON) *dtrState = 1; else *dtrState = 0; } if (rtsState) { if (moxa_ports[port].lineCtrl & RTS_ON) *rtsState = 1; else *rtsState = 0; } return (0);}void MoxaPortLineCtrl(int port, int dtr, int rts){ void __iomem *ofsAddr; int mode; ofsAddr = moxa_ports[port].tableAddr; mode = 0; if (dtr) mode |= DTR_ON; if (rts) mode |= RTS_ON; moxa_ports[port].lineCtrl = mode; moxafunc(ofsAddr, FC_LineControl, mode);}void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int txany){ void __iomem *ofsAddr; int mode; ofsAddr = moxa_ports[port].tableAddr; mode = 0; if (rts) mode |= RTS_FlowCtl; if (cts) mode |= CTS_FlowCtl; if (txflow) mode |= Tx_FlowCtl; if (rxflow) mode |= Rx_FlowCtl; if (txany) mode |= IXM_IXANY; moxafunc(ofsAddr, FC_SetFlowCtl, mode);}int MoxaPortLineStatus(int port){ void __iomem *ofsAddr; int val; ofsAddr = moxa_ports[port].tableAddr; if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) || (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) { moxafunc(ofsAddr, FC_LineStatus, 0); val = readw(ofsAddr + FuncArg); } else { val = readw(ofsAddr + FlagStat) >> 4; } val &= 0x0B; if (val & 8) { val |= 4; if ((moxa_ports[port].DCDState & DCD_oldstate) == 0) moxa_ports[port].DCDState = (DCD_oldstate | DCD_changed); } else { if (moxa_ports[port].DCDState & DCD_oldstate) moxa_ports[port].DCDState = DCD_changed; } val &= 7; return (val);}int MoxaPortDCDChange(int port){ int n; if (moxa_ports[port].chkPort == 0) return (0); n = moxa_ports[port].DCDState; moxa_ports[port].DCDState &= ~DCD_changed; n &= DCD_changed; return (n);}int MoxaPortDCDON(int port){ int n; if (moxa_ports[port].chkPort == 0) return (0); if (moxa_ports[port].DCDState & DCD_oldstate) n = 1; else n = 0; return (n);}int MoxaPortWriteData(int port, unsigned char * buffer, int len){ int c, total, i; ushort tail; int cnt; ushort head, tx_mask, spage, epage; ushort pageno, pageofs, bufhead; void __iomem *baseAddr, *ofsAddr, *ofs; ofsAddr = moxa_ports[port].tableAddr; baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem; tx_mask = readw(ofsAddr + TX_mask); spage = readw(ofsAddr + Page_txb); epage = readw(ofsAddr + EndPage_txb); tail = readw(ofsAddr + TXwptr); head = readw(ofsAddr + TXrptr); c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask); if (c > len) c = len; moxaLog.txcnt[port] += c; total = c; if (spage == epage) { bufhead = readw(ofsAddr + Ofs_txb); writew(spage, baseAddr + Control_reg); while (c > 0) { if (head > tail) len = head - tail - 1; else len = tx_mask + 1 - tail; len = (c > len) ? len : c; ofs = baseAddr + DynPage_addr + bufhead + tail; for (i = 0; i < len; i++) writeb(*buffer++, ofs + i); tail = (tail + len) & tx_mask; c -= len; } writew(tail, ofsAddr + TXwptr); } else { len = c; pageno = spage + (tail >> 13); pageofs = tail & Page_mask; do { cnt = Page_size - pageofs; if (cnt > c) cnt = c; c -= cnt; writeb(pageno, baseAddr + Control_reg); ofs = baseAddr + DynPage_addr + pageofs; for (i = 0; i < cnt; i++) writeb(*buffer++, ofs + i); if (c == 0) { writew((tail + len) & tx_mask, ofsAddr + TXwptr); break; } if (++pageno == epage) pageno = spage; pageofs = 0; } while (1); } writeb(1, ofsAddr + CD180TXirq); /* start to send */ return (total);}int MoxaPortReadData(int port, struct tty_struct *tty){ register ushort head, pageofs; int i, count, cnt, len, total, remain; ushort tail, rx_mask, spage, epage; ushort pageno, bufhead; void __iomem *baseAddr, *ofsAddr, *ofs; ofsAddr = moxa_ports[port].tableAddr; baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem; head = readw(ofsAddr + RXrptr); tail = readw(ofsAddr + RXwptr); rx_mask = readw(ofsAddr + RX_mask); spage = readw(ofsAddr + Page_rxb); epage = readw(ofsAddr + EndPage_rxb); count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1); if (count == 0) return 0; total = count; remain = count - total; moxaLog.rxcnt[port] += total; count = total; if (spage == epage) { bufhead = readw(ofsAddr + Ofs_rxb); writew(spage, baseAddr + Control_reg); while (count > 0) { if (tail >= head) len = tail - head; else len = rx_mask + 1 - head; len = (count > len) ? len : count; ofs = baseAddr + DynPage_addr + bufhead + head; for (i = 0; i < len; i++) tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL); head = (head + len) & rx_mask; count -= len; } writew(head, ofsAddr + RXrptr); } else { len = count; pageno = spage + (head >> 13); pageofs = head & Page_mask; do { cnt = Page_size - pageofs; if (cnt > count) cnt = count; count -= cnt; writew(pageno, baseAddr + Control_reg); ofs = baseAddr + DynPage_addr + pageofs; for (i = 0; i < cnt; i++) tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL); if (count == 0) { writew((head + len) & rx_mask, ofsAddr + RXrptr); break; } if (++pageno == epage) pageno = spage; pageofs = 0; } while (1); } if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) { moxaLowWaterChk = 1; moxa_ports[port].lowChkFlag = 1; } return (total);}int MoxaPortTxQueue(int port){ void __iomem *ofsAddr; ushort rptr, wptr, mask; int len; ofsAddr = moxa_ports[port].tableAddr; rptr = readw(ofsAddr + TXrptr); wptr = readw(ofsAddr + TXwptr); mask = readw(ofsAddr + TX_mask); len = (wptr - rptr) & mask; return (len);}int MoxaPortTxFree(int port){ void __iomem *ofsAddr; ushort rptr, wptr, mask; int len; ofsAddr = moxa_ports[port].tableAddr; rptr = readw(ofsAddr + TXrptr); wptr = readw(ofsAddr + TXwptr); mask = readw(ofsAddr + TX_mask); len = mask - ((wptr - rptr) & mask); return (len);}int MoxaPortRxQueue(int port){ void __iomem *ofsAddr; ushort rptr, wptr, mask; int len; ofsAddr = moxa_ports[port].tableAddr; rptr = readw(ofsAddr + RXrptr); wptr = readw(ofsAddr + RXwptr); mask = readw(ofsAddr + RX_mask); len = (wptr - rptr) & mask; return (len);}void MoxaPortTxDisable(int port){ void __iomem *ofsAddr; ofsAddr = moxa_ports[port].tableAddr; moxafunc(ofsAddr, FC_SetXoffState, Magic_code);}void MoxaPortTxEnable(int port){ void __iomem *ofsAddr; ofsAddr = moxa_ports[port].tableAddr; moxafunc(ofsAddr, FC_SetXonState, Magic_code);}int MoxaPortResetBrkCnt(int port){ ushort cnt; cnt = moxa_ports[port].breakCnt; moxa_ports[port].breakCnt = 0; return (cnt);}void MoxaPortSendBreak(int port, int ms100){ void __iomem *ofsAddr; ofsAddr = moxa_ports[port].tableAddr; if (ms100) { moxafunc(ofsAddr, FC_SendBreak, Magic_code); msleep(ms100 * 10); } else { moxafunc(ofsAddr, FC_SendBreak, Magic_code); msleep(250); } moxafunc(ofsAddr, FC_StopBreak, Magic_code);}static int moxa_get_serial_info(struct moxa_port *info, struct serial_struct __user *retinfo){ struct serial_struct tmp; memset(&tmp, 0, sizeof(tmp)); tmp.type = info->type; tmp.line = info->port; tmp.port = 0; tmp.irq = 0; tmp.flags = info->asyncflags; tmp.baud_base = 921600; tmp.close_delay = info->close_delay; tmp.closing_wait = info->closing_wait; tmp.custom_divisor = 0; tmp.hub6 = 0; if(copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; return (0);}static int moxa_set_serial_info(struct moxa_port *info, struct serial_struct __user *new_info){ struct serial_struct new_serial; if(copy_from_user(&new_serial, new_info, sizeof(new_serial))) return -EFAULT; if ((new_serial.irq != 0) || (new_serial.port != 0) ||// (new_serial.type != info->type) || (new_serial.custom_divisor != 0) || (new_serial.baud_base != 921600)) return (-EPERM); if (!capable(CAP_SYS_ADMIN)) { if (((new_serial.flags & ~ASYNC_USR_MASK) != (info->asyncflags & ~ASYNC_USR_MASK))) return (-EPERM); } else { info->close_delay = new_serial.close_delay * HZ / 100; info->closing_wait = new_serial.closing_wait * HZ / 100; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -