OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_66/] [or1ksim/] [peripheral/] [16450.c] - Diff between revs 123 and 185

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 123 Rev 185
Line 28... Line 28...
*/
*/
 
 
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
 
#include <sys/types.h>  /* CZ 250801 */
 
#include <sys/stat.h>   /* CZ 250801 */
 
#include <fcntl.h>      /* CZ 250801 */ 
 
#include <sys/poll.h>   /* CZ 250801 */
 
#include <sys/time.h>   /* CZ 250801 */ 
 
#include <unistd.h>     /* CZ 250801 */ 
 
#include <errno.h>      /* CZ 250801 */ 
 
 
#include "16450.h"
#include "16450.h"
#include "sim-config.h"
#include "sim-config.h"
#include "pic.h"
#include "pic.h"
 
 
Line 57... Line 64...
        bauds_per_char += (5 + (uarts[uartchip].regs.lcr & 0x2));
        bauds_per_char += (5 + (uarts[uartchip].regs.lcr & 0x2));
 
 
        uarts[uartchip].char_clks *= bauds_per_char;
        uarts[uartchip].char_clks *= bauds_per_char;
}
}
 
 
 
/* CZ 260801 --- The simulator expects to access only 32
 
   bit words. Since we only have an 8 bit data space, simply
 
   ignore the bottom 24 bits. */
/* Set a specific UART register with value. */
/* Set a specific UART register with value. */
void uart_write(unsigned long addr, unsigned char value)
void uart_write(unsigned long addr, unsigned int arg_value)
{
{
        int chipsel;
        int chipsel;
 
        unsigned char value = arg_value >> 24;
 
 
        debug("uart_write(%x,%x)\n", addr, value);
        debug("uart_write(%x,%x)\n", addr, value);
 
 
        for(chipsel = 0; chipsel < NR_UARTS; chipsel++)
        for(chipsel = 0; chipsel < NR_UARTS; chipsel++)
                if ((addr & ~(UART_ADDR_SPACE-1)) == uarts[chipsel].baseaddr)
                if ((addr & ~(UART_ADDR_SPACE-1)) == uarts[chipsel].baseaddr)
                        break;
                        break;
                else if (chipsel == NR_UARTS)
                else if (chipsel == NR_UARTS)
                        return;
                        return;
 
 
        if (uarts[chipsel].regs.lcr & UART_LCR_DLAB) {
        if (uarts[chipsel].regs.lcr & UART_LCR_DLAB)
                switch (addr % UART_ADDR_SPACE) {
          {
 
            switch (addr % UART_ADDR_SPACE)
 
              {
                        case UART_DLL:
                        case UART_DLL:
                                uarts[chipsel].regs.dll = value;
                                uarts[chipsel].regs.dll = value;
                                break;
                set_char_clks(chipsel);
 
                return;
                        case UART_DLH:
                        case UART_DLH:
                                uarts[chipsel].regs.dlh = value;
                                uarts[chipsel].regs.dlh = value;
                                break;
 
                        default:
 
                                debug("write out of range (addr %x, DLAB=1)\n", addr);
 
                }
 
                set_char_clks(chipsel);
                set_char_clks(chipsel);
                return;
                return;
 
              default: /* Fall through to normal processing */
 
                break;
 
              }
        }
        }
 
 
        switch (addr % UART_ADDR_SPACE) {
        switch (addr % UART_ADDR_SPACE) {
                case UART_TXBUF:
                case UART_TXBUF:
                        uarts[chipsel].regs.txbuf = value;
                        uarts[chipsel].regs.txbuf = value;
Line 111... Line 124...
        }
        }
        set_char_clks(chipsel);
        set_char_clks(chipsel);
        return;
        return;
}
}
 
 
 
/* CZ 260801 --- The simulator expects to access only 32
 
   bit words. Since we only have an 8 bit data space, simply
 
   fill in the bottom 24 bits with zero */
/* Read a specific UART register. */
/* Read a specific UART register. */
unsigned char uart_read(unsigned long addr)
unsigned int uart_read(unsigned long addr)
{
{
        unsigned char value = 0;
        unsigned char value = 0;
        int chipsel;
        int chipsel;
 
 
        debug("uart_read(%x)\n", addr);
        debug("uart_read(%x)\n", addr);
Line 125... Line 141...
                if ((addr & ~(UART_ADDR_SPACE-1)) == uarts[chipsel].baseaddr)
                if ((addr & ~(UART_ADDR_SPACE-1)) == uarts[chipsel].baseaddr)
                        break;
                        break;
                else if (chipsel == NR_UARTS)
                else if (chipsel == NR_UARTS)
                        return 0;
                        return 0;
 
 
        if (uarts[chipsel].regs.lcr & UART_LCR_DLAB) {
        if (uarts[chipsel].regs.lcr & UART_LCR_DLAB)
                switch (addr % UART_ADDR_SPACE) {
          {
 
            switch (addr % UART_ADDR_SPACE)
 
              {
                        case UART_DLL:
                        case UART_DLL:
                                value = uarts[chipsel].regs.dll;
                return uarts[chipsel].regs.dll << 24;
                                break;
 
                        case UART_DLH:
                        case UART_DLH:
                                value = uarts[chipsel].regs.dlh;
                return uarts[chipsel].regs.dlh << 24;
 
              default: /* Fall through to normal processing */
                                break;
                                break;
                        default:
 
                                debug("read out of range (addr %x, DLAB=1)\n", addr);
 
                }
                }
                return value;
 
        }
        }
 
 
        switch (addr % UART_ADDR_SPACE) {
        switch (addr % UART_ADDR_SPACE) {
                case UART_RXBUF:
                case UART_RXBUF:
                        value = uarts[chipsel].regs.rxbuf;
                        value = uarts[chipsel].regs.rxbuf;
Line 173... Line 188...
                        value = uarts[chipsel].regs.scr;
                        value = uarts[chipsel].regs.scr;
                        break;
                        break;
                default:
                default:
                        debug("read out of range (addr %x)\n", addr);
                        debug("read out of range (addr %x)\n", addr);
        }
        }
        return value;
        return value << 24;
}
}
 
 
 
 
/* Reset. It initializes all registers of all UART devices to zero values,
/* Reset. It initializes all registers of all UART devices to zero values,
   (re)opens all RX/TX file streams and places devices in memory address
   (re)opens all RX/TX file streams and places devices in memory address
   space. */
   space. */
void uart_reset()
void uart_reset()
{
{
  int i;
  int i;
 
  static int initialized = 0; /* If we're not initialized, don't close it */
 
  int saved_tx_fds[NR_UARTS];
 
  int saved_rx_fds[NR_UARTS];
 
 
 
  if(initialized)
 
    {
 
      for(i = 0; i < NR_UARTS; i++)
 
        {
 
          struct stat buf;
 
 
 
          if(uarts[i].txfd >= 0)
 
            {
 
              if(fstat(uarts[i].txfd,&buf) ||
 
                 (!S_ISFIFO(buf.st_mode) &&
 
                  !S_ISSOCK(buf.st_mode)))
 
                {
 
                  close(uarts[i].txfd);
 
                  saved_tx_fds[i] = -1;
 
                }
 
              else
 
                saved_tx_fds[i] = uarts[i].txfd;
 
            }
 
          else
 
            saved_tx_fds[i] = -1;
 
 
 
          if(uarts[i].rxfd >= 0)
 
            {
 
              if(fstat(uarts[i].rxfd,&buf) ||
 
                 (!S_ISFIFO(buf.st_mode) &&
 
                  !S_ISSOCK(buf.st_mode)))
 
                {
 
                  close(uarts[i].rxfd);
 
                  saved_rx_fds[i] = -1;
 
                }
 
              else
 
                saved_rx_fds[i] = uarts[i].txfd;
 
            }
 
          else
 
            saved_rx_fds[i] = -1;
 
        }
 
    }
 
  else
 
    {
 
      for(i=0;i<NR_UARTS;i++)
 
        saved_tx_fds[i] = saved_rx_fds[i] = -1;
 
      initialized = 1;
 
    }
 
 
  printf("Resetting %u UART(s).\n", NR_UARTS);
  printf("Resetting %u UART(s).\n", NR_UARTS);
  memset(uarts, 0, sizeof(uarts));
  memset(uarts, 0, sizeof(uarts));
 
  for(i=0;i<NR_UARTS;i++)
 
    {
 
      uarts[i].txfd = saved_tx_fds[i];
 
      uarts[i].rxfd = saved_rx_fds[i];
 
    }
 
 
  for(i = 0; i < NR_UARTS; i++)
  for(i = 0; i < NR_UARTS; i++)
    if (config.uarts[i].txfile) { /* MM: Try to create stream.  */
    if (config.uarts[i].txfile) { /* MM: Try to create stream.  */
      if (!(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r"))
      /* CZ changed this to use descriptors and non blocking I/O */
          && !(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r+"))) {
      if ((uarts[i].rxfd = open(config.uarts[i].rxfile,
        printf("UART%d has problems with RX file stream.\n", i);
                                O_RDONLY | O_NONBLOCK)) < 0)
 
        {
 
          char sTemp[256];
 
 
 
          sprintf(sTemp,"UART%d RX - \"%s\"",i,config.uarts[i].rxfile);
 
          perror(sTemp);
 
          continue;
 
        }
 
      if((uarts[i].txfd = open(config.uarts[i].txfile,
 
                                O_WRONLY | O_NONBLOCK)) < 0)
 
        {
 
          char sTemp[256];
 
 
 
          if(errno == ENXIO)
 
            {
 
              /* In this case, we're a pipe, and the user has
 
                 forgotten to start the read process first. Help
 
                 him out by writing an error message and exiting */
 
 
 
              fprintf(stderr,"Please start the serial port reader "
 
                      "before starting the simulator.\nIf you wish "
 
                      "to continue without this, please remove the "
 
                      "file \"%s\" and restart.\n",config.uarts[i].txfile);
 
              fflush(stderr);
 
              exit(1);
 
            }
 
          sprintf(sTemp,"UART%d TX - \"%s\"",i,config.uarts[i].txfile);
 
          perror(sTemp);
 
          close(uarts[i].rxfd);
 
          uarts[i].rxfd = -1;
        continue;
        continue;
      }
      }
      uarts[i].txfs = fopen(config.uarts[i].txfile, "a");
 
      uarts[i].baseaddr = config.uarts[i].baseaddr;
      uarts[i].baseaddr = config.uarts[i].baseaddr;
      if (uarts[i].txfs && uarts[i].txfs) {
 
        printf("UART%d at 0x%.8x uses ", i, uarts[i].baseaddr);
        printf("UART%d at 0x%.8x uses ", i, uarts[i].baseaddr);
        printf("%s for RX and %s for TX.\n", config.uarts[i].rxfile, config.uarts[i].txfile);
      printf("%s for RX and %s for TX.\n", config.uarts[i].rxfile,
      } else
             config.uarts[i].txfile);
        printf("UART%d has problems with TX file stream.\n", i);
      register_memoryarea(uarts[i].baseaddr, UART_ADDR_SPACE,
      register_memoryarea(uarts[i].baseaddr, UART_ADDR_SPACE, uart_read, uart_write);
                          uart_read, uart_write);
    }
    }
}
}
 
 
/* Simulation hook. Must be called every clock cycle to simulate all UART
/* Simulation hook. Must be called every clock cycle to simulate all UART
   devices. It does internal functional UART simulation. */
   devices. It does internal functional UART simulation. */
void uart_clock()
void uart_clock()
{
{
        int i;
        int i;
 
 
        for(i = 0; i < NR_UARTS; i++) {
        for(i = 0; i < NR_UARTS; i++) {
                if (!uarts[i].txfs) {
 
 
          if(uarts[i].txfd < 0)
                        continue;
                        continue;
                }
 
 
 
                /* Transmit */
                /* Transmit */
                if (uarts[i].istat.txser == EMPTY) {
          if (uarts[i].istat.txser == EMPTY)
 
            {
                        uarts[i].regs.lsr |= UART_LSR_TXBUFE;
                        uarts[i].regs.lsr |= UART_LSR_TXBUFE;
                        if (uarts[i].istat.txbuf == FULL) {
              if (uarts[i].istat.txbuf == FULL)
 
                {
                                uarts[i].iregs.txser = uarts[i].regs.txbuf;
                                uarts[i].iregs.txser = uarts[i].regs.txbuf;
                                uarts[i].istat.txser = FULL;
                                uarts[i].istat.txser = FULL;
                                uarts[i].istat.txbuf = EMPTY;
                                uarts[i].istat.txbuf = EMPTY;
                                uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
                                uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
                        } else
                }
 
              else
                                uarts[i].regs.lsr |= UART_LSR_TXSERE;
                                uarts[i].regs.lsr |= UART_LSR_TXSERE;
                } else if (uarts[i].char_clks == uarts[i].istat.txser_clks++) {
            }
 
          else if (uarts[i].char_clks == uarts[i].istat.txser_clks++)
 
            {
                        debug("TX \'%c\' via UART%d...\n", uarts[i].iregs.txser, i);
                        debug("TX \'%c\' via UART%d...\n", uarts[i].iregs.txser, i);
                        if (uarts[i].regs.mcr & UART_MCR_LOOP)
                        if (uarts[i].regs.mcr & UART_MCR_LOOP)
                                uarts[i].iregs.loopback = uarts[i].iregs.txser;
                                uarts[i].iregs.loopback = uarts[i].iregs.txser;
                        else
                        else
                                fputc((int)uarts[i].iregs.txser, uarts[i].txfs);
                switch(send_byte(uarts[i].txfd,config.uarts[i].jitter,
 
                               i,(int)uarts[i].iregs.txser))
 
                  {
 
                  case -1: /* An error occurred */
 
                    close(uarts[i].txfd);
 
                    close(uarts[i].rxfd);
 
                    uarts[i].txfd = uarts[i].rxfd = -1;
 
                    continue;
 
                  case 0:  /* The device wasn't ready */
 
                    uarts[i].istat.txser_clks = 0; /* Try again later */
 
                    break;
 
                  case 1:  /* OK...it got sent */
                        uarts[i].istat.txser = EMPTY;
                        uarts[i].istat.txser = EMPTY;
                        uarts[i].istat.txser_clks = 0;
                        uarts[i].istat.txser_clks = 0;
 
                    break;
 
                  }
                }
                }
 
 
                /* Receive */
                /* Receive */
                if (uarts[i].istat.rxser == EMPTY)
                if (uarts[i].istat.rxser == EMPTY)
                        uarts[i].istat.rxser = FULL;
                        uarts[i].istat.rxser = FULL;
                else if (uarts[i].char_clks == uarts[i].istat.rxser_clks++) {
          else if (uarts[i].char_clks == uarts[i].istat.rxser_clks++)
 
            {
                        debug("Receiving via UART%d...\n", i);
                        debug("Receiving via UART%d...\n", i);
                        if (uarts[i].regs.mcr & UART_MCR_LOOP)
                        if (uarts[i].regs.mcr & UART_MCR_LOOP)
                                uarts[i].iregs.rxser = uarts[i].iregs.loopback;
                                uarts[i].iregs.rxser = uarts[i].iregs.loopback;
                        else
                        else
                                uarts[i].iregs.rxser = (char)fgetc(uarts[i].rxfs);
                switch(receive_byte(uarts[i].rxfd,config.uarts[i].jitter,
 
                                    i,&uarts[i].iregs.rxser))
 
                  {
 
                  case -1: /* An error occurred */
 
                    close(uarts[i].txfd);
 
                    close(uarts[i].rxfd);
 
                    uarts[i].txfd = uarts[i].rxfd = -1;
 
                    continue;
 
                  case 0:
 
                    uarts[i].istat.rxser_clks = 0;
 
                    break;
 
                  case 1:
                        uarts[i].istat.rxser = EMPTY;
                        uarts[i].istat.rxser = EMPTY;
                        uarts[i].istat.rxser_clks = 0;
                        uarts[i].istat.rxser_clks = 0;
                        if (uarts[i].istat.rxbuf == FULL)
                        if (uarts[i].istat.rxbuf == FULL)
                                uarts[i].regs.lsr |= UART_LSR_OVRRUN;
                                uarts[i].regs.lsr |= UART_LSR_OVRRUN;
                        uarts[i].regs.lsr |= UART_LSR_RDRDY;
                        uarts[i].regs.lsr |= UART_LSR_RDRDY;
                        uarts[i].regs.rxbuf = uarts[i].iregs.rxser;
                        uarts[i].regs.rxbuf = uarts[i].iregs.rxser;
                        uarts[i].istat.rxbuf = FULL;
                        uarts[i].istat.rxbuf = FULL;
 
                    break;
 
                  }
                }
                }
 
 
                /* Loopback */
                /* Loopback */
                if (uarts[i].regs.mcr & UART_MCR_LOOP) {
          if (uarts[i].regs.mcr & UART_MCR_LOOP)
 
            {
                        debug("uart_clock: Loopback\n");
                        debug("uart_clock: Loopback\n");
                        if ((uarts[i].regs.mcr & UART_MCR_AUX2) !=
                        if ((uarts[i].regs.mcr & UART_MCR_AUX2) !=
                            ((uarts[i].regs.msr & UART_MSR_DCD) >> 4))
                            ((uarts[i].regs.msr & UART_MSR_DCD) >> 4))
                                uarts[i].regs.msr |= UART_MSR_DDCD;
                                uarts[i].regs.msr |= UART_MSR_DDCD;
                        if ((uarts[i].regs.mcr & UART_MCR_AUX1) <
                        if ((uarts[i].regs.mcr & UART_MCR_AUX1) <
Line 280... Line 408...
 
 
                /* Interrupt detection in proper priority order. */
                /* Interrupt detection in proper priority order. */
                uarts[i].regs.iir = UART_IIR_NO_INT;
                uarts[i].regs.iir = UART_IIR_NO_INT;
                if (uarts[i].regs.ier & UART_IER_RLSI &&
                if (uarts[i].regs.ier & UART_IER_RLSI &&
                    uarts[i].regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
                    uarts[i].regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
                                        | UART_LSR_FRAME | UART_LSR_BREAK)) {
                                   | UART_LSR_FRAME | UART_LSR_BREAK))
 
            {
                        uarts[i].regs.iir = UART_IIR_RLSI;
                        uarts[i].regs.iir = UART_IIR_RLSI;
                }
                }
                else if (uarts[i].regs.ier & UART_IER_RDI &&
                else if (uarts[i].regs.ier & UART_IER_RDI &&
                    uarts[i].regs.lsr & UART_LSR_RDRDY) {
                   uarts[i].regs.lsr & UART_LSR_RDRDY)
 
            {
                        uarts[i].regs.iir = UART_IIR_RDI;
                        uarts[i].regs.iir = UART_IIR_RDI;
                }
                }
                else if (uarts[i].regs.ier & UART_IER_THRI &&
                else if (uarts[i].regs.ier & UART_IER_THRI &&
                    uarts[i].regs.lsr & UART_LSR_TXBUFE) {
                   uarts[i].regs.lsr & UART_LSR_TXBUFE)
 
            {
                        uarts[i].regs.iir = UART_IIR_THRI;
                        uarts[i].regs.iir = UART_IIR_THRI;
                }
                }
                else if (uarts[i].regs.ier & UART_IER_MSI &&
                else if (uarts[i].regs.ier & UART_IER_MSI &&
                    uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
                    uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
                                        | UART_MSR_TERI | UART_MSR_DDCD)) {
                                        | UART_MSR_TERI | UART_MSR_DDCD))
 
            {
                        uarts[i].regs.iir = UART_IIR_MSI;
                        uarts[i].regs.iir = UART_IIR_MSI;
                }
                }
                if (!(uarts[i].regs.iir & UART_IIR_NO_INT))
                if (!(uarts[i].regs.iir & UART_IIR_NO_INT))
                        report_interrupt(INT_UART);
                        report_interrupt(INT_UART);
        }
        }
Line 307... Line 439...
void uart_status()
void uart_status()
{
{
        int i;
        int i;
 
 
        for(i = 0; i < NR_UARTS; i++) {
        for(i = 0; i < NR_UARTS; i++) {
                if (!uarts[i].txfs)
    if (uarts[i].txfd < 0)
                        continue;
                        continue;
 
 
                printf("\nUART%d visible registers at 0x%.8x:\n", i, uarts[i].baseaddr);
                printf("\nUART%d visible registers at 0x%.8x:\n", i, uarts[i].baseaddr);
                printf("RXBUF: %.2x  TXBUF: %.2x\n", uarts[i].regs.rxbuf, uarts[i].regs.txbuf);
                printf("RXBUF: %.2x  TXBUF: %.2x\n", uarts[i].regs.rxbuf, uarts[i].regs.txbuf);
                printf("DLL  : %.2x  DLH  : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
                printf("DLL  : %.2x  DLH  : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
Line 327... Line 459...
                printf("char_clks: %d\n", uarts[i].char_clks);
                printf("char_clks: %d\n", uarts[i].char_clks);
                printf("rxser_clks: %d  txser_clks: %d\n", uarts[i].istat.rxser_clks, uarts[i].istat.txser_clks);
                printf("rxser_clks: %d  txser_clks: %d\n", uarts[i].istat.rxser_clks, uarts[i].istat.txser_clks);
                printf("rxser: %d  txser: %d\n", uarts[i].istat.rxser, uarts[i].istat.txser);
                printf("rxser: %d  txser: %d\n", uarts[i].istat.rxser, uarts[i].istat.txser);
                printf("rxbuf: %d  txbuf: %d\n", uarts[i].istat.rxbuf, uarts[i].istat.txbuf);
                printf("rxbuf: %d  txbuf: %d\n", uarts[i].istat.rxbuf, uarts[i].istat.txbuf);
 
 
                printf("RX fs: %p  TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
    printf("RX fd: %d  TX fd: %d\n\n", uarts[i].rxfd, uarts[i].txfd);
 
  }
 
}
 
 
 
/* Send a byte. Return 1 for OK. 0 for timeout. -1 if a
 
   system error occurred. Asynchronous port is implied by
 
   passing a negative number to the timeout field. In this
 
   case, the function will return without generating an
 
   error message if it can not send. This simulates
 
   congestion control from the external source. */
 
int send_byte(int fd,int timeout,int uart_id,int byte)
 
{
 
  struct timeval now;
 
  struct timeval until;
 
  struct pollfd set;
 
  int msecs = 0;
 
  unsigned char ch = byte;
 
 
 
  if(gettimeofday(&now,NULL) < 0)
 
    {
 
      now.tv_sec = time(NULL);
 
      now.tv_usec = 0;
 
    }
 
 
 
  until.tv_sec = now.tv_sec;
 
  if(timeout > 0)
 
    until.tv_usec = now.tv_usec + timeout*1000;
 
  else
 
    until.tv_usec = now.tv_usec;
 
 
 
  if(until.tv_usec > 999999)
 
    {
 
      until.tv_sec++;
 
      until.tv_usec -= 1000000;
 
    }
 
 
 
  msecs = timeout > 0 ? timeout : 0;
 
  set.fd = fd;
 
  set.events = POLLOUT;
 
  set.revents = 0;
 
 
 
  while(msecs >= 0)
 
    {
 
      char sTemp[256];
 
 
 
      switch(poll(&set,1,msecs))
 
        {
 
        case 1: /* We're good, or we got an error */
 
          switch(write(fd,&ch,1))
 
            {
 
            case -1:
 
              sprintf(sTemp,"UART %d TX - write",uart_id);
 
              perror(sTemp);
 
              fflush(stderr);
 
              return -1;
 
            case 0:
 
              fprintf(stderr,"UART %d TX EOF detected. Shutting down"
 
                      " to prevent endless loop.\n",uart_id);
 
              fflush(stderr);
 
              if(uarts[uart_id].txfd >= 0)
 
                close(uarts[uart_id].txfd);
 
              if(uarts[uart_id].rxfd >= 0)
 
                close(uarts[uart_id].rxfd);
 
              uarts[uart_id].txfd = uarts[uart_id].rxfd = -1;
 
              return 0;
 
            case 1:
 
              return 1;
 
            }
 
        case 0: /* We timed out. Stop the loop. */
 
          msecs = -1;
 
          break;
 
        case -1:
 
          if(errno == EINTR)
 
            {
 
              if(gettimeofday(&now,NULL) < 0)
 
                {
 
                  now.tv_sec = time(NULL);
 
                  now.tv_usec = 0;
 
                }
 
              msecs = (until.tv_sec - now.tv_sec)*1000 +
 
                until.tv_usec - now.tv_usec;
 
              continue;
 
            }
 
          else
 
            {
 
              char sTemp[256];
 
 
 
              sprintf(sTemp,"UART %d TX - poll",uart_id);
 
              perror(sTemp);
 
              fflush(stderr);
 
              return -1;
 
            }
 
        }
 
    }
 
 
 
  if(timeout >= 0)
 
    {
 
      fprintf(stderr,"Transmit timeout occurred on UART %d. Data "
 
              "may be corrupt.\n",uart_id);
 
      fflush(stderr);
        }
        }
 
  return 0;
 
}
 
 
 
/* Receive a byte. Return 1 for OK. 0 for timeout. -1 if a
 
   system error occurred. Asynchronous port is implied by
 
   passing a negative number to the timeout field. In this
 
   case, the function will return without generating an
 
   error message. */
 
int receive_byte(int fd,int timeout,int uart_id,unsigned char* byte)
 
{
 
  struct timeval now;
 
  struct timeval until;
 
  struct pollfd set;
 
  int msecs = 0;
 
 
 
  if(gettimeofday(&now,NULL) < 0)
 
    {
 
      now.tv_sec = time(NULL);
 
      now.tv_usec = 0;
 
    }
 
 
 
  until.tv_sec = now.tv_sec;
 
  if(timeout > 0)
 
    until.tv_usec = now.tv_usec + timeout*1000;
 
  else
 
    until.tv_usec = now.tv_usec;
 
 
 
  if(until.tv_usec > 999999)
 
    {
 
      until.tv_sec++;
 
      until.tv_usec -= 1000000;
 
    }
 
 
 
  msecs = timeout > 0 ? timeout : 0;
 
  set.fd = fd;
 
  set.events = POLLIN;
 
  set.revents = 0;
 
 
 
  while(msecs >= 0)
 
    {
 
      char sTemp[256];
 
 
 
      switch(poll(&set,1,msecs))
 
        {
 
        case 1: /* We're good, or we got an error */
 
          switch(read(fd,byte,1))
 
            {
 
            case -1:
 
              sprintf(sTemp,"UART %d RX - read",uart_id);
 
              perror(sTemp);
 
              fflush(stderr);
 
              return -1;
 
            case 0:
 
              fprintf(stderr,"UART %d RX EOF detected. Shutting down"
 
                      " to prevent endless loop.\n",uart_id);
 
              fflush(stderr);
 
              if(uarts[uart_id].txfd >= 0)
 
                close(uarts[uart_id].txfd);
 
              if(uarts[uart_id].rxfd >= 0)
 
                close(uarts[uart_id].rxfd);
 
              uarts[uart_id].txfd = uarts[uart_id].rxfd = -1;
 
              return 0;
 
            case 1:
 
              return 1;
 
            }
 
        case 0: /* We timed out. Stop the loop. */
 
          *byte = 0xFF;
 
          msecs = -1;
 
          break;
 
        case -1:
 
          if(errno == EINTR)
 
            {
 
              if(gettimeofday(&now,NULL) < 0)
 
                {
 
                  now.tv_sec = time(NULL);
 
                  now.tv_usec = 0;
 
                }
 
              msecs = (until.tv_sec - now.tv_sec)*1000 +
 
                until.tv_usec - now.tv_usec;
 
              continue;
 
            }
 
          else
 
            {
 
              char sTemp[256];
 
 
 
              sprintf(sTemp,"UART %d RX - poll",uart_id);
 
              perror(sTemp);
 
              fflush(stderr);
 
              return -1;
 
            }
 
        }
 
    }
 
 
 
  if(timeout >= 0)
 
    {
 
      fprintf(stderr,"Receive timeout occurred on UART %d. Data "
 
              "may be corrupt.\n",uart_id);
 
      fflush(stderr);
 
    }
 
  return 0;
}
}
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.