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

📄 z85c30.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
   *  Calculate the baud rate divisor   */  baud_requested = t->c_cflag & CBAUD;  if (!baud_requested)    baud_requested = B9600;              /* default to 9600 baud */  ulBaudDivisor = Z85C30_Baud(     (unsigned32) Console_Port_Tbl[minor].ulClock,    (unsigned32) termios_baud_to_number( baud_requested )  );  wr3 = SCC_WR3_RX_EN;  wr4 = SCC_WR4_16_CLOCK;  wr5 = SCC_WR5_TX_EN;  /*   *  Parity   */  if (t->c_cflag & PARENB) {    wr4 |= SCC_WR4_PAR_EN;    if (!(t->c_cflag & PARODD))      wr4 |= SCC_WR4_PAR_EVEN;  }   /*   *  Character Size   */  if (t->c_cflag & CSIZE) {    switch (t->c_cflag & CSIZE) {      case CS5:   break;      case CS6:  wr3 |= SCC_WR3_RX_6_BITS;  wr5 |= SCC_WR5_TX_6_BITS;  break;      case CS7:  wr3 |= SCC_WR3_RX_7_BITS;  wr5 |= SCC_WR5_TX_7_BITS;  break;      case CS8:  wr3 |= SCC_WR3_RX_8_BITS;  wr5 |= SCC_WR5_TX_8_BITS;  break;    }  } else {    wr3 |= SCC_WR3_RX_8_BITS;       /* default to 9600,8,N,1 */    wr5 |= SCC_WR5_TX_8_BITS;       /* default to 9600,8,N,1 */  }  /*   *  Stop Bits   */  if (t->c_cflag & CSTOPB) {    wr4 |= SCC_WR4_2_STOP;                      /* 2 stop bits */  } else {    wr4 |= SCC_WR4_1_STOP;                      /* 1 stop bits */  }  /*   *  Now actually set the chip   */  rtems_interrupt_disable(Irql);    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, wr4 );    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, wr3 );    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, wr5 );    /*     * Setup the lower 8 bits time constants=1E.     * If the time constans=1E, then the desire     * baud rate will be equilvalent to 9600, via register 12.     */    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff );    /*     * using register 13     * Setup the upper 8 bits time constant     */    (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff );  rtems_interrupt_enable(Irql);  return 0;}/* *  z85c30_process * *  This is the per port ISR handler. */Z85C30_STATIC void z85c30_process(  int        minor,  unsigned8  ucIntPend){  unsigned32          ulCtrlPort;  volatile unsigned8  z85c30_status;  unsigned char       cChar;  setRegister_f       setReg;  getRegister_f       getReg;  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;  setReg     = Console_Port_Tbl[minor].setRegister;  getReg     = Console_Port_Tbl[minor].getRegister;  /*   * Deal with any received characters   */  while (ucIntPend&SCC_RR3_B_RX_IP)  {    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);    if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {      break;    }    /*     * Return the character read.     */    cChar = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);    rtems_termios_enqueue_raw_characters(      Console_Port_Data[minor].termios_data,      &cChar,      1    );  }  /*   *  There could be a race condition here if there is not yet a TX   *  interrupt pending but the buffer is empty.  This condition has   *  been seen before on other z8530 drivers but has not been seen   *  with this one.  The typical solution is to use "vector includes   *  status" or to only look at the interrupts actually pending   *  in RR3.   */  while (TRUE) {    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);    if (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {      /*       * We'll get another interrupt when       * the transmitter holding reg. becomes       * free again and we are clear to send       */      break;    }  #if 0    if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) {      /*       * We can't transmit yet       */      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);      /*       * The next state change of CTS will wake us up       */      break;    }#endif      rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1);    if (rtems_termios_dequeue_characters(         Console_Port_Data[minor].termios_data, 1)) {      if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {        z85c30_negate_RTS(minor);      }      Console_Port_Data[minor].bActive = FALSE;      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);      break;    }  }  if (ucIntPend & SCC_RR3_B_EXT_IP) {    /*     * Clear the external status interrupt     */    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);  }  /*   * Reset interrupts   */  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_HI_IUS);}/* *  z85c30_isr * *  This is the ISR handler for each Z8530. */Z85C30_STATIC rtems_isr z85c30_isr(  rtems_vector_number vector){  int                 minor;  unsigned32          ulCtrlPort;  volatile unsigned8  ucIntPend;  volatile unsigned8  ucIntPendPort;  getRegister_f       getReg;  for (minor=0;minor<Console_Port_Count;minor++) {    if(Console_Port_Tbl[minor].ulIntVector == vector &&        Console_Port_Tbl[minor].deviceType == SERIAL_Z85C30 ) {      ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort2;      getReg     = Console_Port_Tbl[minor].getRegister;      do {        ucIntPend = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD3);          /*           * If this is channel A select channel A status           */          if (ulCtrlPort == Console_Port_Tbl[minor].ulCtrlPort1) {            ucIntPendPort = ucIntPend >> 3;            ucIntPendPort &= 7;          } else {            ucIntPendPort = ucIntPend &= 7;          }          if (ucIntPendPort) {            z85c30_process(minor, ucIntPendPort);          }      } while (ucIntPendPort);    }  }}/* *  z85c30_enable_interrupts * *  This routine enables the specified interrupts for this minor. */Z85C30_STATIC void z85c30_enable_interrupts(  int minor,  int interrupt_mask){  unsigned32     ulCtrlPort;  setRegister_f  setReg;  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;  setReg     = Console_Port_Tbl[minor].setRegister;  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR1, interrupt_mask);}/* *  z85c30_initialize_interrupts * *  This routine initializes the port to use interrupts. */Z85C30_STATIC void z85c30_initialize_interrupts(  int minor){  unsigned32     ulCtrlPort1;  unsigned32     ulCtrlPort2;  setRegister_f  setReg;  ulCtrlPort1 = Console_Port_Tbl[minor].ulCtrlPort1;  ulCtrlPort2 = Console_Port_Tbl[minor].ulCtrlPort2;  setReg      = Console_Port_Tbl[minor].setRegister;  z85c30_init(minor);  Console_Port_Data[minor].bActive=FALSE;  z85c30_initialize_port( minor );  if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {    z85c30_negate_RTS(minor);  }  set_vector(z85c30_isr, Console_Port_Tbl[minor].ulIntVector, 1);  z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR2, 0);              /* XXX vector */  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR9, SCC_WR9_MIE);  /*   * Reset interrupts   */  (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);}/*  *  z85c30_write_support_int * *  Console Termios output entry point. * */Z85C30_STATIC int z85c30_write_support_int(  int   minor,   const char *buf,   int   len){  unsigned32     Irql;  unsigned32     ulCtrlPort;  setRegister_f  setReg;  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;  setReg     = Console_Port_Tbl[minor].setRegister;  /*   *  We are using interrupt driven output and termios only sends us   *  one character at a time.   */  if ( !len )    return 0;  /*   *  Put the character out and enable interrupts if necessary.   */  if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {    z85c30_assert_RTS(minor);  }  rtems_interrupt_disable(Irql);    if ( Console_Port_Data[minor].bActive == FALSE) {      Console_Port_Data[minor].bActive = TRUE;      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR);    }    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, *buf);  rtems_interrupt_enable(Irql);  return 1;}/*  *  z85c30_inbyte_nonblocking_polled * *  This routine polls for a character. */Z85C30_STATIC int z85c30_inbyte_nonblocking_polled(  int  minor){  volatile unsigned8  z85c30_status;  unsigned32          ulCtrlPort;  getRegister_f       getReg;  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;  getReg     = Console_Port_Tbl[minor].getRegister;  /*   * return -1 if a character is not available.   */  z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);  if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {    return -1;  }  /*   * Return the character read.   */  return (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);}/*  *  z85c30_write_support_polled * *  Console Termios output entry point. * */Z85C30_STATIC int z85c30_write_support_polled(  int   minor,  const char *buf,  int   len){  int nwrite=0;  /*   * poll each byte in the string out of the port.   */  while (nwrite < len) {    z85c30_write_polled(minor, *buf++);    nwrite++;  }  /*   * return the number of bytes written.   */  return nwrite;}/*  *  z85c30_write_polled * *  This routine transmits a character using polling. */Z85C30_STATIC void z85c30_write_polled(  int   minor,  char  cChar){  volatile unsigned8 z85c30_status;  unsigned32         ulCtrlPort;  getRegister_f      getReg;  setRegister_f      setReg;  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;  getReg     = Console_Port_Tbl[minor].getRegister;  setReg     = Console_Port_Tbl[minor].setRegister;  /*   * Wait for the Transmit buffer to indicate that it is empty.   */  z85c30_status = (*getReg)( ulCtrlPort, SCC_WR0_SEL_RD0 );  while (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {    /*     * Yield while we wait     */#if 0    if (_System_state_Is_up(_System_state_Get())) {      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);    }#endif    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);  }  /*   * Write the character.   */  (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR8, cChar );}

⌨️ 快捷键说明

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