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

📄 ns16550.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* *  ns16550_set_attributes * *  This function sets the channel to reflect the requested termios *  port settings. */NS16550_STATIC int ns16550_set_attributes(  int                   minor,  const struct termios *t){  unsigned32              pNS16550;  unsigned32              ulBaudDivisor;  unsigned8               ucLineControl;  unsigned32              baud_requested;  setRegister_f           setReg;  getRegister_f           getReg;  unsigned32              Irql;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  setReg   = Console_Port_Tbl[minor].setRegister;  getReg   = Console_Port_Tbl[minor].getRegister;  /*   *  Calculate the baud rate divisor   */  baud_requested = t->c_cflag & CBAUD;  if (!baud_requested)    baud_requested = B9600;              /* default to 9600 baud */  ulBaudDivisor = NS16550_Baud(    (unsigned32) Console_Port_Tbl[minor].ulClock,    termios_baud_to_number(baud_requested)  );  ucLineControl = 0;  /*   *  Parity   */  if (t->c_cflag & PARENB) {    ucLineControl |= SP_LINE_PAR;    if (!(t->c_cflag & PARODD))      ucLineControl |= SP_LINE_ODD;  }  /*   *  Character Size   */  if (t->c_cflag & CSIZE) {    switch (t->c_cflag & CSIZE) {      case CS5:  ucLineControl |= FIVE_BITS;  break;      case CS6:  ucLineControl |= SIX_BITS;   break;      case CS7:  ucLineControl |= SEVEN_BITS; break;      case CS8:  ucLineControl |= EIGHT_BITS; break;    }  } else {    ucLineControl |= EIGHT_BITS;               /* default to 9600,8,N,1 */  }  /*   *  Stop Bits   */  if (t->c_cflag & CSTOPB) {    ucLineControl |= SP_LINE_STOP;              /* 2 stop bits */  } else {    ;                                           /* 1 stop bit */  }  /*   *  Now actually set the chip   */  rtems_interrupt_disable(Irql);    /*     *  Set the baud rate      */    (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB);    /* XXX are these registers right? */    (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);    (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);    /*     *  Now write the line control     */    (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );  rtems_interrupt_enable(Irql);  return 0;}/* *  ns16550_process * *  This routine is the console interrupt handler for A port. */NS16550_STATIC void ns16550_process(        int             minor){  unsigned32              pNS16550;  volatile unsigned8      ucLineStatus;   volatile unsigned8      ucInterruptId;  unsigned char           cChar;  getRegister_f           getReg;  setRegister_f           setReg;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  getReg   = Console_Port_Tbl[minor].getRegister;  setReg   = Console_Port_Tbl[minor].setRegister;  do {    /*     * Deal with any received characters     */    while(TRUE) {      ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);      if(~ucLineStatus & SP_LSR_RDY) {        break;      }      cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);      rtems_termios_enqueue_raw_characters(         Console_Port_Data[minor].termios_data,        &cChar,         1       );    }    /*     *  TX all the characters we can     */    while(TRUE) {        ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);        if(~ucLineStatus & SP_LSR_THOLD) {          /*           * We'll get another interrupt when           * the transmitter holding reg. becomes           * free again           */          break;        }#if 0        /* XXX flow control not completely supported in libchip */        if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) {          ns16550_negate_RTS(minor);        }#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 != &ns16550_flow_RTSCTS) {          ns16550_negate_RTS(minor);        }        Console_Port_Data[minor].bActive = FALSE;        ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);        break;      }      ucInterruptId = (*getReg)(pNS16550, NS16550_INTERRUPT_ID);    }  } while((ucInterruptId&0xf)!=0x1);}/* *  ns16550_isr */NS16550_STATIC rtems_isr ns16550_isr(  rtems_vector_number vector){  int     minor;  for(minor=0;minor<Console_Port_Count;minor++) {    if(Console_Port_Tbl[minor].ulIntVector == vector &&        Console_Port_Tbl[minor].deviceType == SERIAL_NS16550 ) {      ns16550_process(minor);    }  }}/* *  ns16550_enable_interrupts * *  This routine initializes the port to have the specified interrupts masked. */NS16550_STATIC void ns16550_enable_interrupts(  int minor,  int mask){  unsigned32     pNS16550;  setRegister_f  setReg;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  setReg   = Console_Port_Tbl[minor].setRegister;  (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask);}/* *  ns16550_initialize_interrupts * *  This routine initializes the port to operate in interrupt driver mode. */ NS16550_STATIC void ns16550_initialize_interrupts(int minor){  ns16550_init(minor);  Console_Port_Data[minor].bActive = FALSE;  set_vector(ns16550_isr, Console_Port_Tbl[minor].ulIntVector, 1);  ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);}/*  *  ns16550_write_support_int * *  Console Termios output entry point. */NS16550_STATIC int ns16550_write_support_int(  int   minor,   const char *buf,   int   len){  unsigned32     Irql;  unsigned32     pNS16550;  setRegister_f  setReg;  setReg   = Console_Port_Tbl[minor].setRegister;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  /*   *  We are using interrupt driven output and termios only sends us   *  one character at a time.   */  if ( !len )    return 0;  if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) {    ns16550_assert_RTS(minor);  }  rtems_interrupt_disable(Irql);    if ( Console_Port_Data[minor].bActive == FALSE) {      Console_Port_Data[minor].bActive = TRUE;      ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR);    }    (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, *buf);  rtems_interrupt_enable(Irql);  return 1;}/*  *  ns16550_write_support_polled * *  Console Termios output entry point. * */NS16550_STATIC int ns16550_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) {    /*     * transmit character     */    ns16550_write_polled(minor, *buf++);    nwrite++;  }  /*   * return the number of bytes written.   */  return nwrite;}/*  *  ns16550_inbyte_nonblocking_polled  * *  Console Termios polling input entry point. */NS16550_STATIC int ns16550_inbyte_nonblocking_polled(   int minor ){  unsigned32           pNS16550;  unsigned char        ucLineStatus;  char                 cChar;  getRegister_f        getReg;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  getReg   = Console_Port_Tbl[minor].getRegister;  ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);  if(ucLineStatus & SP_LSR_RDY) {    cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);    return (int)cChar;  } else {    return -1;  }}

⌨️ 快捷键说明

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