⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 console.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 4 页
字号:
    case B110:    in_baud = 110;      break;    case B134:    in_baud = 134;      break;    case B150:    in_baud = 150;      break;    case B200:    in_baud = 200;      break;    case B300:    in_baud = 300;      break;    case B600:    in_baud = 600;      break;    case B1200:   in_baud = 1200;     break;    case B1800:   in_baud = 1800;     break;    case B2400:   in_baud = 2400;     break;    case B4800:   in_baud = 4800;     break;    case B9600:   in_baud = 9600;     break;    case B19200:  in_baud = 19200;    break;    case B38400:  in_baud = 38400;    break;    case B57600:  in_baud = 57600;    break;    case B115200: in_baud = 115200;   break;    case B230400: in_baud = 230400;   break;    case B460800: in_baud = 460800;   break;  }  /* Number of bits per char */  csize = 0x07; /* to avoid a warning */  switch ( t->c_cflag & CSIZE ) {    case CS5:     csize = 0x04;       break;    case CS6:     csize = 0x05;       break;    case CS7:     csize = 0x06;       break;    case CS8:     csize = 0x07;       break;  }  /* Parity */  if ( t->c_cflag & PARODD )    parodd = 0x80;              /* Odd parity */  else    parodd = 0;  if ( t->c_cflag & PARENB )    parenb = 0x40;              /* Parity enabled on Tx and Rx */  else    parenb = 0x00;              /* No parity on Tx and Rx */  /* CD2401 IGNPAR and INPCK bits are inverted wrt POSIX standard? */  if ( t->c_iflag & INPCK )    ignpar = 0;                 /* Check parity on input */  else    ignpar = 0x10;              /* Do not check parity on input */  if ( t->c_iflag & IGNPAR ) {    inpck = 0x03;               /* Discard error character */    parmrk = 0;  } else {    if ( t->c_iflag & PARMRK ) {      inpck = 0x01;             /* Translate to 0xFF 0x00 <char> */      parmrk = 0x04;    } else {      inpck = 0x01;             /* Translate to 0x00 */      parmrk = 0;    }  }  /* Stop bits */  if ( t->c_cflag & CSTOPB )    cstopb = 0x04;              /* Two stop bits */  else    cstopb = 0x02;              /* One stop bit */  /* Modem flow control */  if ( t->c_cflag & CLOCAL )    hw_flow_ctl = 0x04;         /* Always assert RTS before Tx */  else    hw_flow_ctl = 0x07;         /* Always assert RTS before Tx,                                   wait for CTS and DSR */  /* XON/XOFF Tx flow control */  if ( t->c_iflag & IXON ) {    sw_flow_ctl = 0x40;         /* Tx in-band flow ctl enabled, wait for XON */    extra_flow_ctl = 0x30;      /* Eat XON/XOFF, XON/XOFF in SCHR1, SCHR2 */  }  else {    sw_flow_ctl = 0;            /* Tx in-band flow ctl disabled */    extra_flow_ctl = 0;         /* Pass on XON/XOFF */  }  /* CL/LF translation */  if ( t->c_iflag & ICRNL )    icrnl = 0x40;               /* Map CR to NL on input */  else    icrnl = 0;                  /* Pass on CR */  if ( t->c_iflag & INLCR )    inlcr = 0x20;               /* Map NL to CR on input */  else    inlcr = 0;                  /* Pass on NL */  if ( t->c_iflag & IGNCR )    igncr = 0x80;               /* CR discarded on input */  else    igncr = 0;  /* Break handling */  if ( t->c_iflag & IGNBRK ) {    ignbrk = 0x10;              /* Ignore break on input */    brkint = 0x08;  } else {    if ( t->c_iflag & BRKINT ) {      ignbrk = 0;               /* Generate SIGINT (interrupt ) */      brkint = 0;    } else {      ignbrk = 0;               /* Convert to 0x00 */      brkint = 0x08;    }  }  /* Stripping */  if ( t->c_iflag & ISTRIP )    istrip = 0x80;              /* Strip to 7 bits */  else    istrip = 0;                 /* Leave as 8 bits */  rx_period = cd2401_bitrate_divisor( 20000000Ul, &in_baud );  tx_period = cd2401_bitrate_divisor( 20000000Ul, &out_baud );  /*   *  If this is the first time that the line characteristics are set up, then   *  the device must be re-initialized.   *  Also check if we need to change anything. It is preferable to not touch   *  the device if nothing changes. As soon as we touch it, it tends to   *  glitch. If anything changes, we reprogram all registers. This is   *  harmless.   */  if ( ( CD2401_Channel_Info[minor].tty == 0 ) ||       ( cd2401->cor1 != (parodd | parenb | ignpar | csize) ) ||       ( cd2401->cor2 != (sw_flow_ctl | hw_flow_ctl) ) ||       ( cd2401->cor3 != (extra_flow_ctl | cstopb) )  ||       ( cd2401->cor6 != (igncr | icrnl | inlcr | ignbrk | brkint | parmrk | inpck) ) ||       ( cd2401->cor7 != istrip ) ||       ( cd2401->u1.async.schr1 != t->c_cc[VSTART] ) ||       ( cd2401->u1.async.schr2 != t->c_cc[VSTOP] ) ||       ( cd2401->rbpr != (unsigned char)rx_period ) ||       ( cd2401->rcor != (unsigned char)(rx_period >> 8) ) ||       ( cd2401->tbpr != (unsigned char)tx_period ) ||       ( cd2401->tcor != ( (tx_period >> 3) & 0xE0 ) ) )    need_reinitialization = TRUE;  /* Write to the ports */  rtems_interrupt_disable (level);  cd2401->car = minor;          /* Select channel */  read_enabled = cd2401->csr & 0x80 ? TRUE : FALSE;    if ( (t->c_cflag & CREAD ? TRUE : FALSE ) != read_enabled ) {    /* Read enable status is changing */    need_reinitialization = TRUE;  }    if ( need_reinitialization ) {     /*      *  Could not find a way to test whether the CD2401 was done transmitting.     *  The TxEmpty interrupt does not seem to indicate that the FIFO is empty     *  in DMA mode. So, just wait a while for output to drain. May not be     *  enough, but it will have to do (should be long enough for 1 char at     *  9600 bsp)...     */    cd2401_udelay( 2000L );      /* Clear channel */    cd2401_chan_cmd (minor, 0x40, 1);    cd2401->car = minor;    /* Select channel */    cd2401->cmr = 0x42;     /* Interrupt Rx, DMA Tx, async mode */    cd2401->cor1 = parodd | parenb | ignpar | csize;    cd2401->cor2 = sw_flow_ctl | hw_flow_ctl;    cd2401->cor3 = extra_flow_ctl | cstopb;    cd2401->cor4 = 0x0A;    /* No DSR/DCD/CTS detect; FIFO threshold of 10 */    cd2401->cor5 = 0x0A;    /* No DSR/DCD/CTS detect; DTR threshold of 10 */    cd2401->cor6 = igncr | icrnl | inlcr | ignbrk | brkint | parmrk | inpck;    cd2401->cor7 = istrip;  /* No LNext; ignore XON/XOFF if frame error; no tx translations */    /* Special char 1: XON character */    cd2401->u1.async.schr1 = t->c_cc[VSTART];     /* special char 2: XOFF character */    cd2401->u1.async.schr2 = t->c_cc[VSTOP];        /*      *  Special chars 3 and 4, char range, LNext, RFAR[1..4] and CRC     *  are unused, left as is.     */    /* Set baudrates for receiver and transmitter */    cd2401->rbpr = (unsigned char)rx_period;    cd2401->rcor = (unsigned char)(rx_period >> 8); /* no DPLL */    cd2401->tbpr = (unsigned char)tx_period;    cd2401->tcor = (tx_period >> 3) & 0xE0; /* no x1 ext clk, no loopback */      /* Timeout for 4 chars at 9600, 8 bits per char, 1 stop bit */    cd2401->u2.w.rtpr  = 0x04;  /* NEED TO LOOK AT THIS LINE! */        if ( t->c_cflag & CREAD ) {      /* Re-initialize channel, enable rx and tx */      cd2401_chan_cmd (minor, 0x2A, 1);      /* Enable rx data ints */      cd2401->ier = 0x08;    } else {      /* Re-initialize channel, enable tx, disable rx */      cd2401_chan_cmd (minor, 0x29, 1);    }  }       CD2401_RECORD_SET_ATTRIBUTES_INFO(( minor, need_reinitialization, csize,                                      cstopb, parodd, parenb, ignpar, inpck,                                      hw_flow_ctl, sw_flow_ctl, extra_flow_ctl,                                      icrnl, igncr, inlcr, brkint, ignbrk,                                      parmrk, istrip, tx_period, rx_period,                                      out_baud, in_baud ));  rtems_interrupt_enable (level);    /*    *  Looks like the CD2401 needs time to settle after initialization. Give it   *  10 ms. I don't really believe it, but if output resumes to quickly after   *  this call, the first few characters are not right.      */  if ( need_reinitialization )    cd2401_udelay( 10000L );  /* Return something */  return RTEMS_SUCCESSFUL;}/* *  cd2401_startRemoreTx * *  Defined as a callback, but it would appear that it is never called. The *  POSIX standard states that when the tcflow() function is called with the *  TCION action, the system wall transmit a START character. Presumably, *  tcflow() is called internally when IXOFF is set in the termios c_iflag *  field when the input buffer can accomodate enough characters. It should *  probably be called from fillBufferQueue(). Clearly, the function is also *  explicitly callable by user code. The action is clearly to send the START *  character, regardless of whether START/STOP flow control is in effect. * *  Input parameters: *    minor - selected channel * *  Output parameters: NONE * *  Return value: IGNORED * *  PROPER START CHARACTER MUST BE PROGRAMMED IN SCHR1. */int cd2401_startRemoteTx(  int minor){  rtems_interrupt_level level;  rtems_interrupt_disable (level);  cd2401->car = minor;              /* Select channel */  cd2401->stcr = 0x01;              /* Send SCHR1 ahead of chars in FIFO */  CD2401_RECORD_START_REMOTE_TX_INFO(( minor ));    rtems_interrupt_enable (level);  /* Return something */  return RTEMS_SUCCESSFUL;}/* *  cd2401_stopRemoteTx * *  Defined as a callback, but it would appear that it is never called. The *  POSIX standard states that when the tcflow() function is called with the *  TCIOFF function, the system wall transmit a STOP character. Presumably, *  tcflow() is called internally when IXOFF is set in the termios c_iflag *  field as the input buffer is about to overflow. It should probably be *  called from rtems_termios_enqueue_raw_characters(). Clearly, the function *  is also explicitly callable by user code. The action is clearly to send *  the STOP character, regardless of whether START/STOP flow control is in *  effect. * *  Input parameters: *    minor - selected channel * *  Output parameters: NONE * *  Return value: IGNORED * *  PROPER STOP CHARACTER MUST BE PROGRAMMED IN SCHR2. */int cd2401_stopRemoteTx(  int minor){  rtems_interrupt_level level;  rtems_interrupt_disable (level);  cd2401->car = minor;              /* Select channel */  cd2401->stcr = 0x02;              /* Send SCHR2 ahead of chars in FIFO */  CD2401_RECORD_STOP_REMOTE_TX_INFO(( minor ));  rtems_interrupt_enable (level);  /* Return something */  return RTEMS_SUCCESSFUL;}/* *  cd2401_write * *  Initiate DMA output. Termios guarantees that the buffer does not wrap *  around, so we can do DMA strait from the supplied buffer. * *  Input parameters: *    minor - selected channel *    buf - output buffer *    len - number of chars to output * *  Output parameters:  NONE * *  Return value: IGNORED * *  MUST BE EXECUTED WITH THE CD2401 INTERRUPTS DISABLED! *  The processor is placed at interrupt level CD2401_INT_LEVEL explicitly in *  console_write(). The processor is necessarily at interrupt level 1 in *  cd2401_tx_isr(). */int cd2401_write(  int minor,  const char *buf,  int len){  cd2401->car = minor;              /* Select channel */  if ( (cd2401->dmabsts & 0x08) == 0 ) {    /* Next buffer is A. Wait for it to be ours. */    while ( cd2401->atbsts & 0x01 );    CD2401_Channel_Info[minor].own_buf_A = FALSE;    CD2401_Channel_Info[minor].len = len;    CD2401_Channel_Info[minor].buf = buf;    cd2401->atbadru = (rtems_unsigned16)( ( (rtems_unsigned32) buf ) >> 16 );    cd2401->atbadrl = (rtems_unsigned16)( (rtems_unsigned32) buf );    cd2401->atbcnt = len;    CD2401_RECORD_WRITE_INFO(( len, buf, 'A' ));    cd2401->atbsts = 0x03;          /* CD2401 owns buffer, int when empty */  }  else {    /* Next buffer is B. Wait for it to be ours. */    while ( cd2401->btbsts & 0x01 );    CD2401_Channel_Info[minor].own_buf_B = FALSE;    CD2401_Channel_Info[minor].len = len;    CD2401_Channel_Info[minor].buf = buf;    cd2401->btbadru = (rtems_unsigned16)( ( (rtems_unsigned32) buf ) >> 16 );    cd2401->btbadrl = (rtems_unsigned16)( (rtems_unsigned32) buf );    cd2401->btbcnt = len;    CD2401_RECORD_WRITE_INFO(( len, buf, 'B' ));    cd2401->btbsts = 0x03;          /* CD2401 owns buffer, int when empty */  }  /* Nuts -- Need TxD ints */  CD2401_Channel_Info[minor].txEmpty = FALSE;  cd2401->ier |= 0x01;  /* Return something */  return RTEMS_SUCCESSFUL;}#if 0/* *  cd2401_drainOutput * *  Wait for the txEmpty indication on the specified channel. * *  Input parameters: *    minor - selected channel * *  Output parameters:  NONE * *  Return value: IGNORED * *  MUST NOT BE EXECUTED WITH THE CD2401 INTERRUPTS DISABLED! *  The txEmpty flag is set by the tx ISR. * *  DOES NOT WORK! DO NOT ENABLE THIS CODE. THE CD2401 DOES NOT COOPERATE! *  The code is here to document that the output FIFO is NOT empty when *  the CD2401 reports that the Tx buffer is empty. */int cd2401_drainOutput(  int minor){  CD2401_RECORD_DRAIN_OUTPUT_INFO(( CD2401_Channel_Info[minor].txEmpty,                                    CD2401_Channel_Info[minor].own_buf_A,                                    CD2401_Channel_Info[minor].own_buf_B ));      while( ! (CD2401_Channel_Info[minor].txEmpty &&             CD2401_Channel_Info[minor].own_buf_A &&            CD2401_Channel_Info[minor].own_buf_B) );          /* Return something */  return RTEMS_SUCCESSFUL;}#endif/* * _167Bug_pollRead * *  Read a character from the 167Bug console, and return it. Return -1 *  if there is no character in the input FIFO. * *  Input parameters: *    minor - selected channel * *  Output parameters:  NONE * *  Return value: char returned as positive signed int *                -1 if no character is present in the input FIFO. * *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O! */int _167Bug_pollRead(  int minor){  int char_not_available;  unsigned char c;  rtems_interrupt_level previous_level;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -