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
|