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

📄 mc68681.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  This file contains the termios TTY driver for the Motorola MC68681. * *  This part is available from a number of secondary sources. *  In particular, we know about the following: * *     + Exar 88c681 and 68c681 * *  COPYRIGHT (c) 1989-1999. *  On-Line Applications Research Corporation (OAR). * *  The license and distribution terms for this file may be *  found in the file LICENSE in this distribution or at *  http://www.rtems.com/license/LICENSE. * *  $Id: mc68681.c,v 1.28.6.2 2003/09/26 20:15:47 joel Exp $ */#include <rtems.h>#include <rtems/libio.h>#include <stdlib.h>#include <libchip/serial.h>#include <libchip/mc68681.h>#include <libchip/sersupp.h>#include "mc68681_p.h"/* * Flow control is only supported when using interrupts */console_fns mc68681_fns ={  libchip_serial_default_probe,   /* deviceProbe */  mc68681_open,                   /* deviceFirstOpen */  NULL,                           /* deviceLastClose */  NULL,                           /* deviceRead */  mc68681_write_support_int,      /* deviceWrite */  mc68681_initialize_interrupts,  /* deviceInitialize */  mc68681_write_polled,           /* deviceWritePolled */  mc68681_set_attributes,         /* deviceSetAttributes */  TRUE                            /* deviceOutputUsesInterrupts */};console_fns mc68681_fns_polled ={  libchip_serial_default_probe,        /* deviceProbe */  mc68681_open,                        /* deviceFirstOpen */  mc68681_close,                       /* deviceLastClose */  mc68681_inbyte_nonblocking_polled,   /* deviceRead */  mc68681_write_support_polled,        /* deviceWrite */  mc68681_init,                        /* deviceInitialize */  mc68681_write_polled,                /* deviceWritePolled */  mc68681_set_attributes,              /* deviceSetAttributes */  FALSE,                               /* deviceOutputUsesInterrupts */};extern void set_vector( rtems_isr_entry, rtems_vector_number, int );/* *  Console Device Driver Entry Points *//* *  mc68681_baud_rate * *  This routine returns the proper ACR bit and baud rate field values *  based on the requested baud rate.  The baud rate set to be used *  must be configured by the user. */MC68681_STATIC int mc68681_baud_rate(  int           minor,  int           baud,  unsigned int *baud_mask_p,  unsigned int *acr_bit_p,  unsigned int *command);/* *  mc68681_set_attributes * *  This function sets the DUART channel to reflect the requested termios *  port settings. */MC68681_STATIC int mc68681_set_attributes(   int minor,  const struct termios *t){  unsigned32             pMC68681_port;  unsigned32             pMC68681;  unsigned int           mode1;  unsigned int           mode2;  unsigned int           baud_mask;  unsigned int           acr_bit;  unsigned int           cmd;  setRegister_f          setReg;  rtems_interrupt_level  Irql;  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;  setReg        = Console_Port_Tbl[minor].setRegister;  /*   *  Set the baud rate   */  if (mc68681_baud_rate( minor, t->c_cflag, &baud_mask, &acr_bit, &cmd ) == -1)    return -1;  baud_mask |=  baud_mask << 4;  acr_bit   <<= 7;  /*   *  Parity   */  mode1 = 0;  mode2 = 0;  if (t->c_cflag & PARENB) {    if (t->c_cflag & PARODD)      mode1 |= 0x04;    /* else		mode1 |= 0x04; */  } else {   mode1 |= 0x10;  }  /*   *  Character Size   */  if (t->c_cflag & CSIZE) {    switch (t->c_cflag & CSIZE) {      case CS5:  break;      case CS6:  mode1 |= 0x01;  break;      case CS7:  mode1 |= 0x02;  break;      case CS8:  mode1 |= 0x03;  break;    }  } else {    mode1 |= 0x03;       /* default to 9600,8,N,1 */  }  /*   *  Stop Bits   */    if (t->c_cflag & CSTOPB) {    mode2 |= 0x0F;                      /* 2 stop bits */  } else {    if ((t->c_cflag & CSIZE) == CS5)    /* CS5 and 1 stop bits not supported */      return -1;    mode2 |= 0x07;                      /* 1 stop bit */  } /*  *   Hardware Flow Control  */  if(t->c_cflag & CRTSCTS) {	  mode1 |= 0x80; /* Enable Rx RTS Control */	  mode2 |= 0x10; /* Enable CTS Enable Tx */  }  rtems_interrupt_disable(Irql);    (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit );    (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud_mask );    if ( cmd ) {      (*setReg)( pMC68681_port, MC68681_COMMAND, cmd );         /* RX */      (*setReg)( pMC68681_port, MC68681_COMMAND, cmd | 0x20 );  /* TX */    }    (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );    (*setReg)( pMC68681_port, MC68681_MODE, mode1 );    (*setReg)( pMC68681_port, MC68681_MODE, mode2 );  rtems_interrupt_enable(Irql);  return 0;}/* *  mc68681_initialize_context * *  This function sets the default values of the per port context structure. */MC68681_STATIC void mc68681_initialize_context(  int               minor,  mc68681_context  *pmc68681Context){  int          port;  unsigned int pMC68681;  unsigned int pMC68681_port;    pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;  pmc68681Context->mate = -1;  for (port=0 ; port<Console_Port_Count ; port++ ) {    if ( Console_Port_Tbl[port].ulCtrlPort1 == pMC68681 &&          Console_Port_Tbl[port].ulCtrlPort2 != pMC68681_port ) {      pmc68681Context->mate = port;      pmc68681Context->imr  = 0;      break;    }  }}/* *  mc68681_init * *  This function initializes the DUART to a quiecsent state. */MC68681_STATIC void mc68681_init(int minor){  unsigned32              pMC68681_port;  unsigned32              pMC68681;  mc68681_context        *pmc68681Context;  setRegister_f           setReg;  getRegister_f           getReg;  pmc68681Context = (mc68681_context *) malloc(sizeof(mc68681_context));  Console_Port_Data[minor].pDeviceContext = (void *)pmc68681Context;  mc68681_initialize_context( minor, pmc68681Context );  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;  setReg        = Console_Port_Tbl[minor].setRegister;  getReg        = Console_Port_Tbl[minor].getRegister;  /*   *  Reset everything and leave this port disabled.   */  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_RX );  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_TX );  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_BREAK );  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_STOP_BREAK );  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );  (*setReg)( pMC68681_port, MC68681_MODE_REG_1A, 0x00 );  (*setReg)( pMC68681_port, MC68681_MODE_REG_2A, 0x02 );  /*   *  Disable interrupts on RX and TX for this port   */  mc68681_enable_interrupts( minor, MC68681_IMR_DISABLE_ALL );}/* *  mc68681_open * *  This function opens a port for communication. * *  Default state is 9600 baud, 8 bits, No parity, and 1 stop bit. */MC68681_STATIC int mc68681_open(  int      major,  int      minor,  void    *arg){  unsigned32             pMC68681;  unsigned32             pMC68681_port;  unsigned int           baud;  unsigned int           acr_bit;  unsigned int           vector;  unsigned int           command;  rtems_interrupt_level  Irql;  setRegister_f          setReg;  unsigned int			 status;      pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;  setReg        = Console_Port_Tbl[minor].setRegister;  vector        = Console_Port_Tbl[minor].ulIntVector;      /* XXX default baud rate should be from configuration table */  status = mc68681_baud_rate( minor, B9600, &baud, &acr_bit, &command );  if (status < 0) rtems_fatal_error_occurred (RTEMS_NOT_DEFINED);  /*   *  Set the DUART channel to a default useable state   */  rtems_interrupt_disable(Irql);    (*setReg)( pMC68681, MC68681_AUX_CTRL_REG, acr_bit << 7 );    (*setReg)( pMC68681_port, MC68681_CLOCK_SELECT, baud );    if ( command ) {      (*setReg)( pMC68681_port, MC68681_COMMAND, command );         /* RX */      (*setReg)( pMC68681_port, MC68681_COMMAND, command | 0x20 );  /* TX */    }    (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_MR_PTR );    (*setReg)( pMC68681_port, MC68681_MODE, 0x13 );    (*setReg)( pMC68681_port, MC68681_MODE, 0x07 );  rtems_interrupt_enable(Irql);  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_TX );  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_ENABLE_RX );  (*setReg)( pMC68681, MC68681_INTERRUPT_VECTOR_REG, vector );  return RTEMS_SUCCESSFUL;}/* *  mc68681_close * *  This function shuts down the requested port. */MC68681_STATIC int mc68681_close(  int      major,  int      minor,  void    *arg){  unsigned32      pMC68681;  unsigned32      pMC68681_port;  setRegister_f   setReg;  pMC68681      = Console_Port_Tbl[minor].ulCtrlPort1;  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;  setReg        = Console_Port_Tbl[minor].setRegister;  /*   *  Disable interrupts from this channel and then disable it totally.   */#if 0  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_TX );  (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_DISABLE_RX );#endif  return(RTEMS_SUCCESSFUL);}/*  *  mc68681_write_polled * *  This routine polls out the requested character. */MC68681_STATIC void mc68681_write_polled(  int   minor,   char  cChar){  unsigned32              pMC68681_port;  unsigned char           ucLineStatus;  int                     iTimeout;  getRegister_f           getReg;  setRegister_f           setReg;  pMC68681_port = Console_Port_Tbl[minor].ulCtrlPort2;  getReg        = Console_Port_Tbl[minor].getRegister;  setReg        = Console_Port_Tbl[minor].setRegister;  /*   * wait for transmitter holding register to be empty   */  iTimeout = 1000;  ucLineStatus = (*getReg)(pMC68681_port, MC68681_STATUS);  while ((ucLineStatus & (MC68681_TX_READY|MC68681_TX_EMPTY)) == 0) {    if ((ucLineStatus & 0xF0))      (*setReg)( pMC68681_port, MC68681_COMMAND, MC68681_MODE_REG_RESET_ERROR );    /*     * Yield while we wait     */#if 0     if(_System_state_Is_up(_System_state_Get())) {       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);     }

⌨️ 快捷键说明

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