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

📄 ns16550.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  This file contains the TTY driver for the National Semiconductor NS16550. * *  This part is widely cloned and second sourced.  It is found in a number  *  of "Super IO" controllers. * *  COPYRIGHT (c) 1998 by Radstone Technology * * * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. * * You are hereby granted permission to use, copy, modify, and distribute * this file, provided that this notice, plus the above copyright notice * and disclaimer, appears in all copies. Radstone Technology will provide * no support for this code. * *  This driver uses the termios pseudo driver. */#include <rtems.h>#include <rtems/libio.h>#include <stdlib.h>#include <ringbuf.h>#include <libchip/serial.h>#include <libchip/sersupp.h>#include "ns16550_p.h"/* * Flow control is only supported when using interrupts */console_flow ns16550_flow_RTSCTS = {  ns16550_negate_RTS,             /* deviceStopRemoteTx */  ns16550_assert_RTS              /* deviceStartRemoteTx */};console_flow ns16550_flow_DTRCTS = {  ns16550_negate_DTR,             /* deviceStopRemoteTx */  ns16550_assert_DTR              /* deviceStartRemoteTx */};console_fns ns16550_fns = {  libchip_serial_default_probe,   /* deviceProbe */  ns16550_open,                   /* deviceFirstOpen */  NULL,                           /* deviceLastClose */  NULL,                           /* deviceRead */  ns16550_write_support_int,      /* deviceWrite */  ns16550_initialize_interrupts,  /* deviceInitialize */  ns16550_write_polled,           /* deviceWritePolled */  ns16550_set_attributes,         /* deviceSetAttributes */  TRUE                            /* deviceOutputUsesInterrupts */};console_fns ns16550_fns_polled = {  libchip_serial_default_probe,        /* deviceProbe */  ns16550_open,                        /* deviceFirstOpen */  ns16550_close,                       /* deviceLastClose */  ns16550_inbyte_nonblocking_polled,   /* deviceRead */  ns16550_write_support_polled,        /* deviceWrite */  ns16550_init,                        /* deviceInitialize */  ns16550_write_polled,                /* deviceWritePolled */  ns16550_set_attributes,              /* deviceSetAttributes */  FALSE                                /* deviceOutputUsesInterrupts */};extern void set_vector( rtems_isr_entry, rtems_vector_number, int );/* *  ns16550_init */NS16550_STATIC void ns16550_init(int minor){  unsigned32              pNS16550;  unsigned8               ucTrash;  unsigned8               ucDataByte;  unsigned32              ulBaudDivisor;  ns16550_context        *pns16550Context;  setRegister_f           setReg;  getRegister_f           getReg;  pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context));  Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context;  pns16550Context->ucModemCtrl=SP_MODEM_IRQ;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  setReg   = Console_Port_Tbl[minor].setRegister;  getReg   = Console_Port_Tbl[minor].getRegister;  /* Clear the divisor latch, clear all interrupt enables,   * and reset and   * disable the FIFO's.   */  (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0);  ns16550_enable_interrupts(minor, NS16550_DISABLE_ALL_INTR);  /* Set the divisor latch and set the baud rate. */  ulBaudDivisor = NS16550_Baud(    (unsigned32) Console_Port_Tbl[minor].ulClock,    (unsigned32) Console_Port_Tbl[minor].pDeviceParams  );  ucDataByte = SP_LINE_DLAB;  (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);  /* XXX */  (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);  (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);  /* Clear the divisor latch and set the character size to eight bits */  /* with one stop bit and no parity checking. */  ucDataByte = EIGHT_BITS;  (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);  /* Enable and reset transmit and receive FIFOs. TJA     */  ucDataByte = SP_FIFO_ENABLE;  (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);  ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST;  (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);  ns16550_enable_interrupts(minor, NS16550_DISABLE_ALL_INTR);  /* Set data terminal ready. */  /* And open interrupt tristate line */  (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);  ucTrash = (*getReg)(pNS16550, NS16550_LINE_STATUS );  ucTrash = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER );}/* *  ns16550_open */NS16550_STATIC int ns16550_open(  int      major,  int      minor,  void    * arg){  /*   * Assert DTR   */  if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_DTRCTS) {    ns16550_assert_DTR(minor);  }  return(RTEMS_SUCCESSFUL);}/* *  ns16550_close */NS16550_STATIC int ns16550_close(  int      major,  int      minor,  void    * arg){  /*   * Negate DTR   */  if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_DTRCTS) {    ns16550_negate_DTR(minor);  }  return(RTEMS_SUCCESSFUL);}/*  *  ns16550_write_polled */NS16550_STATIC void ns16550_write_polled(  int   minor,   char  cChar){  unsigned32              pNS16550;  unsigned char           ucLineStatus;  int                     iTimeout;  getRegister_f           getReg;  setRegister_f           setReg;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  getReg   = Console_Port_Tbl[minor].getRegister;  setReg   = Console_Port_Tbl[minor].setRegister;  /*   * wait for transmitter holding register to be empty   */  iTimeout=1000;  ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);  while ((ucLineStatus & SP_LSR_THOLD) == 0) {    /*     * Yield while we wait     */#if 0     if(_System_state_Is_up(_System_state_Get())) {       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);     }#endif     ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);     if(!--iTimeout) {       break;     }  }  /*   * transmit character   */  (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, cChar);}/* * These routines provide control of the RTS and DTR lines *//* *  ns16550_assert_RTS */NS16550_STATIC int ns16550_assert_RTS(int minor){  unsigned32              pNS16550;  unsigned32              Irql;  ns16550_context        *pns16550Context;  setRegister_f           setReg;  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  setReg   = Console_Port_Tbl[minor].setRegister;  /*   * Assert RTS   */  rtems_interrupt_disable(Irql);  pns16550Context->ucModemCtrl|=SP_MODEM_RTS;  (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);  rtems_interrupt_enable(Irql);  return 0;}/* *  ns16550_negate_RTS */NS16550_STATIC int ns16550_negate_RTS(int minor){  unsigned32              pNS16550;  unsigned32              Irql;  ns16550_context        *pns16550Context;  setRegister_f           setReg;  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  setReg   = Console_Port_Tbl[minor].setRegister;  /*   * Negate RTS   */  rtems_interrupt_disable(Irql);  pns16550Context->ucModemCtrl&=~SP_MODEM_RTS;  (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);  rtems_interrupt_enable(Irql);  return 0;}/* * These flow control routines utilise a connection from the local DTR * line to the remote CTS line *//* *  ns16550_assert_DTR */NS16550_STATIC int ns16550_assert_DTR(int minor){  unsigned32              pNS16550;  unsigned32              Irql;  ns16550_context        *pns16550Context;  setRegister_f           setReg;  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  setReg   = Console_Port_Tbl[minor].setRegister;  /*   * Assert DTR   */  rtems_interrupt_disable(Irql);  pns16550Context->ucModemCtrl|=SP_MODEM_DTR;  (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl);  rtems_interrupt_enable(Irql);  return 0;}/* *  ns16550_negate_DTR */NS16550_STATIC int ns16550_negate_DTR(int minor){  unsigned32              pNS16550;  unsigned32              Irql;  ns16550_context        *pns16550Context;  setRegister_f           setReg;  pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;  pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1;  setReg   = Console_Port_Tbl[minor].setRegister;  /*   * Negate DTR   */  rtems_interrupt_disable(Irql);  pns16550Context->ucModemCtrl&=~SP_MODEM_DTR;  (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl);  rtems_interrupt_enable(Irql);  return 0;

⌨️ 快捷键说明

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