📄 serial167.c
字号:
mapping is slightly different from serial.c because there is still the possibility of supporting 75 kbit/sec with the Cyclades board.) */ if (i & CBAUDEX) { if (i == B57600) i = 16; else if(i == B115200) i = 18;#ifdef B78600 else if(i == B78600) i = 17;#endif else info->tty->termios->c_cflag &= ~CBAUDEX; }#endif if (i == 15) { if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) i += 1; if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) i += 3; } /* Don't ever change the speed of the console port. It will * run at the speed specified in bootinfo, or at 19.2K */ /* Actually, it should run at whatever speed 166Bug was using */ /* Note info->timeout isn't used at present */ if (info != serial_console_info) { info->tbpr = baud_bpr[i]; /* Tx BPR */ info->tco = baud_co[i]; /* Tx CO */ info->rbpr = baud_bpr[i]; /* Rx BPR */ info->rco = baud_co[i] >> 5; /* Rx CO */ if (baud_table[i] == 134) { info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; /* get it right for 134.5 baud */ } else if (baud_table[i]) { info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2; /* this needs to be propagated into the card info */ } else { info->timeout = 0; } } /* By tradition (is it a standard?) a baud rate of zero implies the line should be/has been closed. A bit later in this routine such a test is performed. */ /* byte size and parity */ info->cor7 = 0; info->cor6 = 0; info->cor5 = 0; info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]); /* receive threshold */ /* Following two lines added 101295, RGH. */ /* It is obviously wrong to access CyCORx, and not info->corx here, * try and remember to fix it later! */ channel = info->line; base_addr[CyCAR] = (u_char)channel; if (C_CLOCAL(info->tty)) { if (base_addr[CyIER] & CyMdmCh) base_addr[CyIER] &= ~CyMdmCh; /* without modem intr */ /* ignore 1->0 modem transitions */ if (base_addr[CyCOR4] & (CyDSR|CyCTS|CyDCD)) base_addr[CyCOR4] &= ~(CyDSR|CyCTS|CyDCD); /* ignore 0->1 modem transitions */ if (base_addr[CyCOR5] & (CyDSR|CyCTS|CyDCD)) base_addr[CyCOR5] &= ~(CyDSR|CyCTS|CyDCD); } else { if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh) base_addr[CyIER] |= CyMdmCh; /* with modem intr */ /* act on 1->0 modem transitions */ if ((base_addr[CyCOR4] & (CyDSR|CyCTS|CyDCD)) != (CyDSR|CyCTS|CyDCD)) base_addr[CyCOR4] |= CyDSR|CyCTS|CyDCD; /* act on 0->1 modem transitions */ if ((base_addr[CyCOR5] & (CyDSR|CyCTS|CyDCD)) != (CyDSR|CyCTS|CyDCD)) base_addr[CyCOR5] |= CyDSR|CyCTS|CyDCD; } info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP; info->cor2 = CyETC; switch(cflag & CSIZE){ case CS5: info->cor1 = Cy_5_BITS; break; case CS6: info->cor1 = Cy_6_BITS; break; case CS7: info->cor1 = Cy_7_BITS; break; case CS8: info->cor1 = Cy_8_BITS; break; } if (cflag & PARENB){ if (cflag & PARODD){ info->cor1 |= CyPARITY_O; }else{ info->cor1 |= CyPARITY_E; } }else{ info->cor1 |= CyPARITY_NONE; } /* CTS flow control flag */#if 0 /* Don't complcate matters for now! RGH 141095 */ if (cflag & CRTSCTS){ info->flags |= ASYNC_CTS_FLOW; info->cor2 |= CyCtsAE; }else{ info->flags &= ~ASYNC_CTS_FLOW; info->cor2 &= ~CyCtsAE; }#endif if (cflag & CLOCAL) info->flags &= ~ASYNC_CHECK_CD; else info->flags |= ASYNC_CHECK_CD; /*********************************************** The hardware option, CyRtsAO, presents RTS when the chip has characters to send. Since most modems use RTS as reverse (inbound) flow control, this option is not used. If inbound flow control is necessary, DTR can be programmed to provide the appropriate signals for use with a non-standard cable. Contact Marcio Saito for details. ***********************************************/ channel = info->line; save_flags(flags); cli(); base_addr[CyCAR] = (u_char)channel; /* CyCMR set once only in mvme167_init_serial() */ if (base_addr[CyLICR] != channel << 2) base_addr[CyLICR] = channel << 2; if (base_addr[CyLIVR] != 0x5c) base_addr[CyLIVR] = 0x5c; /* tx and rx baud rate */ if (base_addr[CyCOR1] != info->cor1) need_init_chan = 1; if (base_addr[CyTCOR] != info->tco) base_addr[CyTCOR] = info->tco; if (base_addr[CyTBPR] != info->tbpr) base_addr[CyTBPR] = info->tbpr; if (base_addr[CyRCOR] != info->rco) base_addr[CyRCOR] = info->rco; if (base_addr[CyRBPR] != info->rbpr) base_addr[CyRBPR] = info->rbpr; /* set line characteristics according configuration */ if (base_addr[CySCHR1] != START_CHAR(info->tty)) base_addr[CySCHR1] = START_CHAR(info->tty); if (base_addr[CySCHR2] != STOP_CHAR(info->tty)) base_addr[CySCHR2] = STOP_CHAR(info->tty); if (base_addr[CySCRL] != START_CHAR(info->tty)) base_addr[CySCRL] = START_CHAR(info->tty); if (base_addr[CySCRH] != START_CHAR(info->tty)) base_addr[CySCRH] = START_CHAR(info->tty); if (base_addr[CyCOR1] != info->cor1) base_addr[CyCOR1] = info->cor1; if (base_addr[CyCOR2] != info->cor2) base_addr[CyCOR2] = info->cor2; if (base_addr[CyCOR3] != info->cor3) base_addr[CyCOR3] = info->cor3; if (base_addr[CyCOR4] != info->cor4) base_addr[CyCOR4] = info->cor4; if (base_addr[CyCOR5] != info->cor5) base_addr[CyCOR5] = info->cor5; if (base_addr[CyCOR6] != info->cor6) base_addr[CyCOR6] = info->cor6; if (base_addr[CyCOR7] != info->cor7) base_addr[CyCOR7] = info->cor7; if (need_init_chan) write_cy_cmd(base_addr,CyINIT_CHAN); base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */ /* 2ms default rx timeout */ ti = info->default_timeout ? info->default_timeout : 0x02; if (base_addr[CyRTPRL] != ti) base_addr[CyRTPRL] = ti; if (base_addr[CyRTPRH] != 0) base_addr[CyRTPRH] = 0; /* Set up RTS here also ????? RGH 141095 */ if(i == 0){ /* baud rate is zero, turn off line */ if ((base_addr[CyMSVR2] & CyDTR) == CyDTR) base_addr[CyMSVR2] = 0;#ifdef SERIAL_DEBUG_DTR printk("cyc: %d: dropping DTR\n", __LINE__); printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);#endif }else{ if ((base_addr[CyMSVR2] & CyDTR) != CyDTR) base_addr[CyMSVR2] = CyDTR;#ifdef SERIAL_DEBUG_DTR printk("cyc: %d: raising DTR\n", __LINE__); printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);#endif } if (info->tty){ clear_bit(TTY_IO_ERROR, &info->tty->flags); } restore_flags(flags);} /* config_setup */static voidcy_put_char(struct tty_struct *tty, unsigned char ch){ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags;#ifdef SERIAL_DEBUG_IO printk("cy_put_char ttyS%d(0x%02x)\n", info->line, ch);#endif if (serial_paranoia_check(info, tty->device, "cy_put_char")) return; if (!tty || !info->xmit_buf) return; save_flags(flags); cli(); if (info->xmit_cnt >= PAGE_SIZE - 1) { restore_flags(flags); return; } info->xmit_buf[info->xmit_head++] = ch; info->xmit_head &= PAGE_SIZE - 1; info->xmit_cnt++; restore_flags(flags);} /* cy_put_char */static voidcy_flush_chars(struct tty_struct *tty){ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags; volatile unsigned char *base_addr = (u_char *)BASE_ADDR; int channel; #ifdef SERIAL_DEBUG_IO printk("cy_flush_chars ttyS%d\n", info->line); /* */#endif if (serial_paranoia_check(info, tty->device, "cy_flush_chars")) return; if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf) return; channel = info->line; save_flags(flags); cli(); base_addr[CyCAR] = channel; base_addr[CyIER] |= CyTxMpty; restore_flags(flags);} /* cy_flush_chars *//* This routine gets called when tty_write has put something into the write_queue. If the port is not already transmitting stuff, start it off by enabling interrupts. The interrupt service routine will then ensure that the characters are sent. If the port is already active, there is no need to kick it. */static intcy_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count){ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags; int c, total = 0;#ifdef SERIAL_DEBUG_IO printk("cy_write ttyS%d\n", info->line); /* */#endif if (serial_paranoia_check(info, tty->device, "cy_write")){ return 0; } if (!tty || !info->xmit_buf || !tmp_buf){ return 0; } while (1) { save_flags(flags); cli(); c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); if (c <= 0){ restore_flags(flags); break; } if (from_user) { down(&tmp_buf_sem); copy_from_user(tmp_buf, buf, c); c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); up(&tmp_buf_sem); } else memcpy(info->xmit_buf + info->xmit_head, buf, c); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); info->xmit_cnt += c; restore_flags(flags); buf += c; count -= c; total += c; } if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped ) { start_xmit(info); } return total;} /* cy_write */static intcy_write_room(struct tty_struct *tty){ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; int ret; #ifdef SERIAL_DEBUG_IO printk("cy_write_room ttyS%d\n", info->line); /* */#endif if (serial_paranoia_check(info, tty->device, "cy_write_room")) return 0; ret = PAGE_SIZE - info->xmit_cnt - 1; if (ret < 0) ret = 0; return ret;} /* cy_write_room */static intcy_chars_in_buffer(struct tty_struct *tty){ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; #ifdef SERIAL_DEBUG_IO printk("cy_chars_in_buffer ttyS%d %d\n", info->line, info->xmit_cnt); /* */#endif if (serial_paranoia_check(info, tty->device, "cy_chars_in_buffer")) return 0; return info->xmit_cnt;} /* cy_chars_in_buffer */static voidcy_flush_buffer(struct tty_struct *tty){ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_IO printk("cy_flush_buffer ttyS%d\n", info->line); /* */#endif if (serial_paranoia_check(info, tty->device, "cy_flush_buffer")) return; save_flags(flags); cli(); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; restore_flags(flags); wake_up_interruptible(&tty->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty);} /* cy_flush_buffer *//* This routine is called by the upper-layer tty layer to signal that incoming characters should be throttled or that the throttle should be released. */static voidcy_throttle(struct tty_struct * tty){ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags; volatile unsigned char *base_addr = (u_char *)BASE_ADDR; int channel;#ifdef SERIAL_DEBUG_THROTTLE char buf[64]; printk("throttle %s: %d....\n", _tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); printk("cy_throttle ttyS%d\n", info->line);#endif if (serial_paranoia_check(info, tty->device, "cy_nthrottle")){ return; } if (I_IXOFF(tty)) { info->x_char = STOP_CHAR(tty); /* Should use the "Send Special Character" feature!!! */ } channel = info->line; save_flags(flags); cli(); base_addr[CyCAR] = (u_char)channel; base_addr[CyMSVR1] = 0; restore_flags(flags); return;} /* cy_throttle */static voidcy_unthrottle(struct tty_struct * tty){ struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; unsigned long flags; volatile unsigned char *base_addr = (u_char *)BASE_ADDR; int channel;#ifdef SERIAL_DEBUG_THROTTLE char buf[64]; printk("throttle %s: %d....\n", _tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); printk("cy_unthrottle ttyS%d\n", info->line);#endif if (serial_paranoia_check(info, tty->device, "cy_nthrottle")){ return; } if (I_IXOFF(tty)) { info->x_char = START_CHAR(tty); /* Should use the "Send Special Character" feature!!! */ } channel = info->line; save_flags(flags); cli(); base_addr[CyCAR] = (u_char)channel; base_addr[CyMSVR1] = CyRTS; restore_flags(flags); return;} /* cy_unthrottle */static intget_serial_info(struct cyclades_port * info, struct serial_struct * retinfo){ struct serial_struct tmp;/* CP('g'); */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -