📄 moxa.c
字号:
(tty->termios->c_cflag & CLOCAL)) wake_up_interruptible(&ch->open_wait);}static void moxa_stop(struct tty_struct *tty){ struct moxa_str *ch = (struct moxa_str *) tty->driver_data; if (ch == NULL) return; MoxaPortTxDisable(ch->port); ch->statusflags |= TXSTOPPED;}static void moxa_start(struct tty_struct *tty){ struct moxa_str *ch = (struct moxa_str *) tty->driver_data; if (ch == NULL) return; if (!(ch->statusflags & TXSTOPPED)) return; MoxaPortTxEnable(ch->port); ch->statusflags &= ~TXSTOPPED;}static void moxa_hangup(struct tty_struct *tty){ struct moxa_str *ch = (struct moxa_str *) tty->driver_data; moxa_flush_buffer(tty); shut_down(ch); ch->event = 0; ch->count = 0; ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE); ch->tty = 0; wake_up_interruptible(&ch->open_wait);}static void moxa_poll(unsigned long ignored){ register int card; struct moxa_str *ch; struct tty_struct *tp; int i, ports; moxaTimer_on = 0; del_timer(&moxaTimer); if (MoxaDriverPoll() < 0) { moxaTimer.function = moxa_poll; moxaTimer.expires = jiffies + (HZ / 50); moxaTimer_on = 1; add_timer(&moxaTimer); return; } for (card = 0; card < MAX_BOARDS; card++) { if ((ports = MoxaPortsOfCard(card)) <= 0) continue; ch = &moxaChannels[card * MAX_PORTS_PER_BOARD]; for (i = 0; i < ports; i++, ch++) { if ((ch->asyncflags & ASYNC_INITIALIZED) == 0) continue; if (!(ch->statusflags & THROTTLE) && (MoxaPortRxQueue(ch->port) > 0)) receive_data(ch); if ((tp = ch->tty) == 0) continue; if (ch->statusflags & LOWWAIT) { if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) { if (!tp->stopped) { ch->statusflags &= ~LOWWAIT; if ((tp->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tp->ldisc.write_wakeup) (tp->ldisc.write_wakeup) (tp); wake_up_interruptible(&tp->write_wait); } } } if (!I_IGNBRK(tp) && (MoxaPortResetBrkCnt(ch->port) > 0)) { tty_insert_flip_char(tp, 0, TTY_BREAK); tty_schedule_flip(tp); } if (MoxaPortDCDChange(ch->port)) { if (ch->asyncflags & ASYNC_CHECK_CD) { if (MoxaPortDCDON(ch->port)) wake_up_interruptible(&ch->open_wait); else { set_bit(MOXA_EVENT_HANGUP, &ch->event); MOD_DEC_USE_COUNT; if (schedule_task(&ch->tqueue) == 0) MOD_INC_USE_COUNT; } } } } } moxaTimer.function = moxa_poll; moxaTimer.expires = jiffies + (HZ / 50); moxaTimer_on = 1; add_timer(&moxaTimer);}/******************************************************************************/static void set_tty_param(struct tty_struct *tty){ register struct termios *ts; struct moxa_str *ch; int rts, cts, txflow, rxflow, xany; ch = (struct moxa_str *) tty->driver_data; ts = tty->termios; if (ts->c_cflag & CLOCAL) ch->asyncflags &= ~ASYNC_CHECK_CD; else ch->asyncflags |= ASYNC_CHECK_CD; rts = cts = txflow = rxflow = xany = 0; if (ts->c_cflag & CRTSCTS) rts = cts = 1; if (ts->c_iflag & IXON) txflow = 1; if (ts->c_iflag & IXOFF) rxflow = 1; if (ts->c_iflag & IXANY) xany = 1; MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany); MoxaPortSetTermio(ch->port, ts);}static int block_till_ready(struct tty_struct *tty, struct file *filp, struct moxa_str *ch){ DECLARE_WAITQUEUE(wait,current); unsigned long flags; int retval; int do_clocal = C_CLOCAL(tty); /* * 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) || (ch->asyncflags & ASYNC_CLOSING)) { if (ch->asyncflags & ASYNC_CLOSING) interruptible_sleep_on(&ch->close_wait);#ifdef SERIAL_DO_RESTART if (ch->asyncflags & ASYNC_HUP_NOTIFY) return (-EAGAIN); else return (-ERESTARTSYS);#else return (-EAGAIN);#endif } /* * If this is a callout device, then just make sure the normal * device isn't being used. */ if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { if (ch->asyncflags & ASYNC_NORMAL_ACTIVE) return (-EBUSY); if ((ch->asyncflags & ASYNC_CALLOUT_ACTIVE) && (ch->asyncflags & ASYNC_SESSION_LOCKOUT) && (ch->session != current->session)) return (-EBUSY); if ((ch->asyncflags & ASYNC_CALLOUT_ACTIVE) && (ch->asyncflags & ASYNC_PGRP_LOCKOUT) && (ch->pgrp != current->pgrp)) return (-EBUSY); ch->asyncflags |= ASYNC_CALLOUT_ACTIVE; return (0); } /* * If non-blocking mode is set, then make the check up front * and then exit. */ if (filp->f_flags & O_NONBLOCK) { if (ch->asyncflags & ASYNC_CALLOUT_ACTIVE) return (-EBUSY); ch->asyncflags |= ASYNC_NORMAL_ACTIVE; return (0); } /* * Block waiting for the carrier detect and the line to become free */ retval = 0; add_wait_queue(&ch->open_wait, &wait);#ifdef SERIAL_DEBUG_OPEN printk("block_til_ready before block: ttys%d, count = %d\n", ch->line, ch->count);#endif save_flags(flags); cli(); if (!tty_hung_up_p(filp)) ch->count--; restore_flags(flags); ch->blocked_open++; while (1) { current->state = TASK_INTERRUPTIBLE; if (tty_hung_up_p(filp) || !(ch->asyncflags & ASYNC_INITIALIZED)) {#ifdef SERIAL_DO_RESTART if (ch->asyncflags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS;#else retval = -EAGAIN;#endif break; } if (!(ch->asyncflags & ASYNC_CALLOUT_ACTIVE) && !(ch->asyncflags & ASYNC_CLOSING) && (do_clocal || MoxaPortDCDON(ch->port))) break; if (signal_pending(current)) { retval = -ERESTARTSYS; break; } schedule(); } current->state = TASK_RUNNING; remove_wait_queue(&ch->open_wait, &wait); if (!tty_hung_up_p(filp)) ch->count++; ch->blocked_open--;#ifdef SERIAL_DEBUG_OPEN printk("block_til_ready after blocking: ttys%d, count = %d\n", ch->line, ch->count);#endif if (retval) return (retval); ch->asyncflags |= ASYNC_NORMAL_ACTIVE; return (0);}static void setup_empty_event(struct tty_struct *tty){ struct moxa_str *ch = tty->driver_data; unsigned long flags; save_flags(flags); cli(); ch->statusflags |= EMPTYWAIT; moxaEmptyTimer_on[ch->port] = 0; del_timer(&moxaEmptyTimer[ch->port]); moxaEmptyTimer[ch->port].expires = jiffies + HZ; moxaEmptyTimer_on[ch->port] = 1; add_timer(&moxaEmptyTimer[ch->port]); restore_flags(flags);}static void check_xmit_empty(unsigned long data){ struct moxa_str *ch; ch = (struct moxa_str *) data; moxaEmptyTimer_on[ch->port] = 0; del_timer(&moxaEmptyTimer[ch->port]); if (ch->tty && (ch->statusflags & EMPTYWAIT)) { if (MoxaPortTxQueue(ch->port) == 0) { ch->statusflags &= ~EMPTYWAIT; if ((ch->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && ch->tty->ldisc.write_wakeup) (ch->tty->ldisc.write_wakeup) (ch->tty); wake_up_interruptible(&ch->tty->write_wait); return; } moxaEmptyTimer[ch->port].expires = jiffies + HZ; moxaEmptyTimer_on[ch->port] = 1; add_timer(&moxaEmptyTimer[ch->port]); } else ch->statusflags &= ~EMPTYWAIT;}static void shut_down(struct moxa_str *ch){ struct tty_struct *tp; if (!(ch->asyncflags & ASYNC_INITIALIZED)) return; tp = ch->tty; MoxaPortDisable(ch->port); /* * If we're a modem control device and HUPCL is on, drop RTS & DTR. */ if (tp->termios->c_cflag & HUPCL) MoxaPortLineCtrl(ch->port, 0, 0); ch->asyncflags &= ~ASYNC_INITIALIZED;}static void receive_data(struct moxa_str *ch){ struct tty_struct *tp; struct termios *ts; int i, count, rc, space; unsigned char *charptr, *flagptr; unsigned long flags; ts = 0; tp = ch->tty; if (tp) ts = tp->termios; /************************************************** if ( !tp || !ts || !(ts->c_cflag & CREAD) ) { *****************************************************/ if (!tp || !ts) { MoxaPortFlushData(ch->port, 0); return; } space = TTY_FLIPBUF_SIZE - tp->flip.count; if (space <= 0) return; charptr = tp->flip.char_buf_ptr; flagptr = tp->flip.flag_buf_ptr; rc = tp->flip.count; save_flags(flags); cli(); count = MoxaPortReadData(ch->port, charptr, space); restore_flags(flags); for (i = 0; i < count; i++) *flagptr++ = 0; charptr += count; rc += count; tp->flip.count = rc; tp->flip.char_buf_ptr = charptr; tp->flip.flag_buf_ptr = flagptr; tty_schedule_flip(ch->tty);}#define Magic_code 0x404/* * System Configuration *//* * for C218 BIOS initialization */#define C218_ConfBase 0x800#define C218_status (C218_ConfBase + 0) /* BIOS running status */#define C218_diag (C218_ConfBase + 2) /* diagnostic status */#define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218) */#define C218DLoad_len (C218_ConfBase + 6) /* WORD */#define C218check_sum (C218_ConfBase + 8) /* BYTE */#define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */#define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */#define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */#define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */#define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */#define C218_LoadBuf 0x0F00#define C218_KeyCode 0x218#define CP204J_KeyCode 0x204/* * for C320 BIOS initialization */#define C320_ConfBase 0x800#define C320_LoadBuf 0x0f00#define STS_init 0x05 /* for C320_status */#define C320_status C320_ConfBase + 0 /* BIOS running status */#define C320_diag C320_ConfBase + 2 /* diagnostic status */#define C320_key C320_ConfBase + 4 /* WORD (0320H for C320) */#define C320DLoad_len C320_ConfBase + 6 /* WORD */#define C320check_sum C320_ConfBase + 8 /* WORD */#define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */#define C320bapi_len C320_ConfBase + 0x0c /* WORD */#define C320UART_no C320_ConfBase + 0x0e /* WORD */#define C320_KeyCode 0x320#define FixPage_addr 0x0000 /* starting addr of static page */#define DynPage_addr 0x2000 /* starting addr of dynamic page */#define C218_start 0x3000 /* starting addr of C218 BIOS prg */#define Control_reg 0x1ff0 /* select page and reset control */#define HW_reset 0x80/* * Function Codes */#define FC_CardReset 0x80#define FC_ChannelReset 1 /* C320 firmware not supported */#define FC_EnableCH 2#define FC_DisableCH 3#define FC_SetParam 4#define FC_SetMode 5#define FC_SetRate 6#define FC_LineControl 7#define FC_LineStatus 8#define FC_XmitControl 9#define FC_FlushQueue 10#define FC_SendBreak 11#define FC_StopBreak 12#define FC_LoopbackON 13#define FC_LoopbackOFF 14#define FC_ClrIrqTable 15#define FC_SendXon 16#define FC_SetTermIrq 17 /* C320 firmware not supported */#define FC_SetCntIrq 18 /* C320 firmware not supported */#define FC_SetBreakIrq 19#define FC_SetLineIrq 20#define FC_SetFlowCtl 21#define FC_GenIrq 22#define FC_InCD180 23#define FC_OutCD180 24#define FC_InUARTreg 23#define FC_OutUARTreg 24#define FC_SetXonXoff 25#define FC_OutCD180CCR 26#define FC_ExtIQueue 27#define FC_ExtOQueue 28#define FC_ClrLineIrq 29#define FC_HWFlowCtl 30#define FC_GetClockRate 35#define FC_SetBaud 36#define FC_SetDataMode 41#define FC_GetCCSR 43#define FC_GetDataError 45#define FC_RxControl 50#define FC_ImmSend 51#define FC_SetXonState 52#define FC_SetXoffState 53#define FC_SetRxFIFOTrig 54#define FC_SetTxFIFOCnt 55#define FC_UnixRate 56#define FC_UnixResetTimer 57#define RxFIFOTrig1 0#define RxFIFOTrig4 1#define RxFIFOTrig8 2#define RxFIFOTrig14 3/* * Dual-Ported RAM */#define DRAM_global 0#define INT_data (DRAM_global + 0)#define Config_base (DRAM_global + 0x108)#define IRQindex (INT_data + 0)#define IRQpending (INT_data + 4)#define IRQtable (INT_data + 8)/* * Interrupt Status */#define IntrRx 0x01 /* receiver data O.K. */#define IntrTx 0x02 /* transmit buffer empty */#define IntrFunc 0x04 /* function complete */#define IntrBreak 0x08 /* received break */#define IntrLine 0x10 /* line status change for transmitter */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -