Updated serial port code to be multi-threaded. Interrupts still get lost, gotta dig more.

This commit is contained in:
waltje
2017-06-05 05:00:28 -04:00
parent e5acdbbeab
commit b2e2e2f4cc
3 changed files with 224 additions and 261 deletions

View File

@@ -8,7 +8,7 @@
*
* Definitions for the Bottom Half of the SERIAL card.
*
* Version: @(#)plat_serial.h 1.0.3 2017/05/17
* Version: @(#)plat_serial.h 1.0.5 2017/06/04
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2017 Fred N. van Kempen.
@@ -18,7 +18,7 @@
typedef struct {
char name[79]; /* name of open port */
char name[80]; /* name of open port */
void (*rd_done)(void *, int);
void *rd_arg;
#ifdef BHTTY_C
@@ -28,6 +28,9 @@ typedef struct {
int tmo; /* current timeout value */
DCB dcb, /* terminal settings */
odcb;
thread_t *tid; /* pointer to receiver thread */
char buff[1024];
int icnt, ihead, itail;
#endif
} BHTTY;
@@ -41,7 +44,7 @@ extern int bhtty_params(BHTTY *, char __dbit, char __par, char __sbit);
extern int bhtty_sstate(BHTTY *, void *__arg);
extern int bhtty_gstate(BHTTY *, void *__arg);
extern int bhtty_crtscts(BHTTY *, char __yesno);
extern int bhtty_active(BHTTY *, int);
extern int bhtty_write(BHTTY *, unsigned char);
extern int bhtty_read(BHTTY *, unsigned char *, int);

View File

@@ -12,7 +12,7 @@
* Windows and UNIX systems, with support for FTDI and Prolific
* USB ports. Support for these has been removed.
*
* Version: @(#)win_serial.c 1.0.2 2017/05/17
* Version: @(#)win_serial.c 1.0.3 2017/06/04
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2017 Fred N. van Kempen.
@@ -21,6 +21,7 @@
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "plat_thread.h"
#define BHTTY_C
#include "plat_serial.h"
@@ -28,6 +29,60 @@
extern void pclog(char *__fmt, ...);
/* Handle the receiving of data from the host port. */
static void
bhtty_reader(void *arg)
{
BHTTY *pp = (BHTTY *)arg;
unsigned char b;
DWORD n;
pclog("%s: thread started\n", pp->name);
/* As long as the channel is open.. */
while (pp->tid != NULL) {
/* Post a READ on the device. */
n = 0;
if (ReadFile(pp->handle, &b, (DWORD)1, &n, &pp->rov) == FALSE) {
n = GetLastError();
if (n != ERROR_IO_PENDING) {
/* Not good, we got an error. */
pclog("%s: I/O error %d in read!\n", pp->name, n);
break;
}
/* The read is pending, wait for it.. */
if (GetOverlappedResult(pp->handle, &pp->rov, &n, TRUE) == FALSE) {
n = GetLastError();
pclog("%s: I/O error %d in read!\n", pp->name, n);
break;
}
}
pclog("%s: got %d bytes of data\n", pp->name, n);
if (n == 1) {
/* We got data, update stuff. */
if (pp->icnt < sizeof(pp->buff)) {
pclog("%s: queued byte %02x (%d)\n", pp->name, b, pp->icnt+1);
pp->buff[pp->ihead++] = b;
pp->ihead &= (sizeof(pp->buff)-1);
pp->icnt++;
/* Do a callback to let them know. */
if (pp->rd_done != NULL)
pp->rd_done(pp->rd_arg, n);
} else {
pclog("%s: RX buffer overrun!\n", pp->name);
}
}
}
/* Error or done, clean up. */
pp->tid = NULL;
pclog("%s: thread stopped.\n", pp->name);
}
/* Set the state of a port. */
int
bhtty_sstate(BHTTY *pp, void *arg)
@@ -35,8 +90,8 @@ bhtty_sstate(BHTTY *pp, void *arg)
int i = 0;
/* Make sure we can do this. */
if (pp == NULL || arg == NULL) {
pclog("invalid argument\n");
if (arg == NULL) {
pclog("%s: invalid argument\n", pp->name);
return(-1);
}
@@ -57,8 +112,8 @@ bhtty_gstate(BHTTY *pp, void *arg)
int i = 0;
/* Make sure we can do this. */
if (pp == NULL || arg == NULL) {
pclog("BHTTY: invalid argument\n");
if (arg == NULL) {
pclog("%s: invalid argument\n", pp->name);
return(-1);
}
@@ -76,12 +131,6 @@ bhtty_gstate(BHTTY *pp, void *arg)
int
bhtty_crtscts(BHTTY *pp, char yesno)
{
/* Make sure we can do this. */
if (pp == NULL) {
pclog("invalid handle\n");
return(-1);
}
/* Get the current mode. */
if (bhtty_gstate(pp, &pp->dcb) < 0) return(-1);
@@ -124,12 +173,6 @@ bhtty_crtscts(BHTTY *pp, char yesno)
int
bhtty_params(BHTTY *pp, char dbit, char par, char sbit)
{
/* Make sure we can do this. */
if (pp == NULL) {
pclog("invalid handle\n");
return(-1);
}
/* Get the current mode. */
if (bhtty_gstate(pp, &pp->dcb) < 0) return(-1);
@@ -220,8 +263,8 @@ bhtty_raw(BHTTY *pp, void *arg)
DCB *dcb = (DCB *)arg;
/* Make sure we can do this. */
if (pp == NULL || arg == NULL) {
pclog("invalid parameter\n");
if (arg == NULL) {
pclog("%s: invalid parameter\n", pp->name);
return;
}
@@ -263,12 +306,6 @@ bhtty_speed(BHTTY *pp, long speed)
{
int i;
/* Make sure we can do this. */
if (pp == NULL) {
pclog("invalid handle\n");
return(-1);
}
/* Get the current mode and speed. */
if (bhtty_gstate(pp, &pp->dcb) < 0) return(-1);
@@ -296,12 +333,6 @@ bhtty_flush(BHTTY *pp)
COMSTAT cs;
int i = 0;
/* Make sure we can do this. */
if (pp == NULL) {
pclog("invalid handle\n");
return(-1);
}
/* First, clear any errors. */
(void)ClearCommError(pp->handle, &dwErrs, &cs);
@@ -327,13 +358,18 @@ bhtty_flush(BHTTY *pp)
void
bhtty_close(BHTTY *pp)
{
/* Make sure we can do this. */
if (pp == NULL) {
pclog("BHTTY: invalid handle\n");
return;
}
/* If the polling thread is running, stop it. */
(void)bhtty_active(pp, 0);
/* Close the event handles. */
if (pp->rov.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(pp->rov.hEvent);
if (pp->wov.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(pp->wov.hEvent);
if (pp->handle != INVALID_HANDLE_VALUE) {
pclog("%s: closing host port\n", pp->name);
/* Restore the previous port state, if any. */
(void)bhtty_sstate(pp, &pp->odcb);
@@ -351,20 +387,11 @@ bhtty_close(BHTTY *pp)
BHTTY *
bhtty_open(char *port, int tmo)
{
char buff[64];
char temp[64];
COMMTIMEOUTS to;
#if 0
COMMCONFIG conf;
DWORD d;
#endif
BHTTY *pp;
int i = 0;
/* Make sure we can do this. */
if (port == NULL) {
pclog("invalid argument!\n");
return(NULL);
}
DWORD d;
/* First things first... create a control block. */
if ((pp = (BHTTY *)malloc(sizeof(BHTTY))) == NULL) {
@@ -375,45 +402,53 @@ bhtty_open(char *port, int tmo)
strncpy(pp->name, port, sizeof(pp->name)-1);
/* Try a regular Win32 serial port. */
sprintf(buff, "\\\\.\\%s", pp->name);
pp->handle = CreateFile(buff,
(GENERIC_READ|GENERIC_WRITE),
0, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (pp->handle == INVALID_HANDLE_VALUE) {
sprintf(temp, "\\\\.\\%s", pp->name);
if ((pp->handle = CreateFile(temp,
(GENERIC_READ|GENERIC_WRITE),
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0)) == INVALID_HANDLE_VALUE) {
pclog("%s: open port: %d\n", pp->name, GetLastError());
free(pp);
return(NULL);
}
#if 0
/* Create event handles. */
pp->rov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
pp->wov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
/* Set up buffer size of the port. */
if (SetupComm(pp->handle, 32768L, 32768L) == FALSE) {
/* This fails on FTDI-based devices. */
pclog("%s: set buffers: %d\n", pp->name, GetLastError());
// CloseHandle(pp->handle);
// free(pp);
// return(NULL);
#if 0
CloseHandle(pp->handle);
free(pp);
return(NULL);
#endif
}
/* Grab default config for the driver and set it. */
d = sizeof(COMMCONFIG);
memset(&conf, 0x00, d);
conf.dwSize = d;
if (GetDefaultCommConfig(pp->name, &conf, &d) == TRUE) {
if (GetDefaultCommConfig(temp, &conf, &d) == TRUE) {
/* Change config here... */
/* Set new configuration. */
if (SetCommConfig(pp->handle, &conf, d) == FALSE) {
/* This fails on FTDI-based devices. */
pclog("%s: set configuration: %d\n", pp->name, GetLastError());
// CloseHandle(pp->handle);
// free(pp);
// return(NULL);
#if 0
CloseHandle(pp->handle);
free(pp);
return(NULL);
#endif
}
}
#endif
pclog("%s: host port '%s' open\n", pp->name, temp);
/*
* We now have an open port. To allow for clean exit
@@ -460,8 +495,7 @@ bhtty_open(char *port, int tmo)
to.ReadTotalTimeoutConstant = tmo;
}
if (SetCommTimeouts(pp->handle, &to) == FALSE) {
pclog("%s: error %d while setting TO\n",
pp->name, GetLastError());
pclog("%s: error %d while setting TO\n", pp->name, GetLastError());
(void)bhtty_close(pp);
return(NULL);
}
@@ -476,25 +510,22 @@ bhtty_open(char *port, int tmo)
}
/* A pending WRITE has finished, handle it. */
static VOID CALLBACK
bhtty_write_comp(DWORD err, DWORD num, OVERLAPPED *priv)
/* Activate the I/O for this port. */
int
bhtty_active(BHTTY *pp, int flg)
{
BHTTY *pp = (BHTTY *)priv->hEvent;
if (flg) {
pclog("%s: starting thread..\n", pp->name);
pp->tid = thread_create(bhtty_reader, pp);
} else {
if (pp->tid != NULL) {
pclog("%s: stopping thread..\n", pp->name);
thread_kill(pp->tid);
pp->tid = NULL;
}
}
//pclog("%s: write complete, status %d, num %d\n", pp->name, err, num);
#if 0
if (
if (GetOverlappedResult(p->handle,
&p->rov, &mst, TRUE) == FALSE) {
r = GetLastError();
if (r != ERROR_OPERATION_ABORTED)
/* OK, we're being shut down. */
sprintf(serial_errmsg,
"%s: I/O read error!", p->name);
return(-1);
}
#endif
return(0);
}
@@ -502,56 +533,26 @@ bhtty_write_comp(DWORD err, DWORD num, OVERLAPPED *priv)
int
bhtty_write(BHTTY *pp, unsigned char val)
{
DWORD n;
DWORD n = 0;
/* Make sure we can do this. */
if (pp == NULL) {
pclog("invalid parameter\n");
return(-1);
}
//pclog("BHwrite(%08lx, %02x, '%c')\n", pp->handle, val, val);
/* Save the control pointer for later use. */
pp->wov.hEvent = (HANDLE)pp;
if (WriteFileEx(pp->handle,
&val, 1,
&pp->wov,
bhtty_write_comp) == FALSE) {
pclog("%s: writing byte %02x\n", pp->name, val);
if (WriteFile(pp->handle, &val, 1, &n, &pp->wov) == FALSE) {
n = GetLastError();
pclog("%s: I/O error %d in write!\n", pp->name, n);
return(-1);
if (n != ERROR_IO_PENDING) {
/* Not good, we got an error. */
pclog("%s: I/O error %d in write!\n", pp->name, n);
return(-1);
}
/* The write is pending, wait for it.. */
if (GetOverlappedResult(pp->handle, &pp->wov, &n, TRUE) == FALSE) {
n = GetLastError();
pclog("%s: I/O error %d in write!\n", pp->name, n);
return(-1);
}
}
/* Its pending, so handled in the completion routine. */
SleepEx(1, TRUE);
return(0);
}
/*
* A pending READ has finished, handle it.
*/
static VOID CALLBACK
bhtty_read_comp(DWORD err, DWORD num, OVERLAPPED *priv)
{
BHTTY *pp = (BHTTY *)priv->hEvent;
DWORD r;
//pclog("%s: read complete, status %d, num %d\n", pp->name, err, num);
if (GetOverlappedResult(pp->handle, &pp->rov, &r, TRUE) == FALSE) {
r = GetLastError();
if (r != ERROR_OPERATION_ABORTED)
/* OK, we're being shut down. */
pclog("%s: I/O read error!", pp->name);
return;
}
//pclog("%s: read done, num=%d (%d)\n", pp->name, num, r);
/* Do a callback to let them know. */
if (pp->rd_done != NULL)
pp->rd_done(pp->rd_arg, num);
return((int)n);
}
@@ -561,46 +562,18 @@ bhtty_read_comp(DWORD err, DWORD num, OVERLAPPED *priv)
* For now, we will use one byte per call. Eventually,
* we should go back to loading a buffer full of data,
* just to speed things up a bit. --FvK
*
* Also, not that we do not wait here. We just POST a
* read operation, and the completion routine will do
* the clean-up and notify the caller.
*/
int
bhtty_read(BHTTY *pp, unsigned char *bufp, int max)
{
DWORD r;
if (pp->icnt == 0) return(0);
/* Just one byte. */
max = 1;
/* Make sure we can do this. */
if (pp == NULL) {
pclog("invalid parameter\n");
return(-1);
while (max-- > 0) {
*bufp++ = pp->buff[pp->itail++];
pclog("%s: dequeued byte %02x (%d)\n", pp->name, *(bufp-1), pp->icnt);
pp->itail &= (sizeof(pp->buff)-1);
if (--pp->icnt == 0) break;
}
/* Save the control pointer for later use. */
pp->rov.hEvent = (HANDLE)pp;
//pclog("%s: read(%08lx, %d)\n", pp->name, pp->handle, max);
/* Post a READ on the device. */
if (ReadFileEx(pp->handle,
bufp, (DWORD)max,
&pp->rov,
bhtty_read_comp) == FALSE) {
r = GetLastError();
if (r != ERROR_IO_PENDING) {
/* OK, we're being shut down. */
if (r != ERROR_INVALID_HANDLE)
pclog("%s: I/O read error!\n", pp->name);
return(-1);
}
}
/* Make ourself alertable. */
SleepEx(1, TRUE);
/* OK, it's pending, so we are good for now. */
return(0);
return(max);
}

View File

@@ -33,7 +33,7 @@
*
* Based on the 86Box serial port driver as a framework.
*
* Version: @(#)serial.c 1.0.6 2017/06/02
* Version: @(#)serial.c 1.0.7 2017/06/04
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
* Copyright 2017 Fred N. van Kempen.
@@ -47,6 +47,9 @@
#include "plat_serial.h"
#define NUM_SERIAL 2 /* we support 2 ports */
enum {
SERINT_LSR = 1,
SERINT_RECEIVE = 2,
@@ -137,8 +140,7 @@ enum {
#define MSR_MASK (0x0f)
static SERIAL serial1, /* serial port 1 data */
serial2; /* serial port 2 data */
static SERIAL ports[NUM_SERIAL]; /* serial port data */
int serial_do_log;
@@ -222,16 +224,6 @@ serial_write_fifo(SERIAL *sp, uint8_t dat)
}
#ifdef WALTJE
static void
serial_write_str(SERIAL *sp, const char *str)
{
while (*str)
serial_write_fifo(sp, (uint8_t)*str++);
}
#endif
static uint8_t
read_fifo(SERIAL *sp)
{
@@ -244,19 +236,6 @@ read_fifo(SERIAL *sp)
}
/* BHTTY WRITE COMPLETE handler. */
static void
serial_wr_done(void *arg)
{
SERIAL *sp = (SERIAL *)arg;
/* The WRITE completed, we are ready for more. */
sp->lsr |= LSR_THRE;
sp->int_status |= SERINT_TRANSMIT;
update_ints(sp);
}
/* Handle a WRITE operation to one of our registers. */
static void
serial_write(uint16_t addr, uint8_t val, void *priv)
@@ -278,13 +257,12 @@ serial_write(uint16_t addr, uint8_t val, void *priv)
sp->thr = val;
if (sp->bh != NULL) {
/* We are linked, so send to BH layer. */
#if 0
bhtty_write((BHTTY *)sp->bh,
sp->thr, serial_wr_done, sp);
#else
bhtty_write((BHTTY *)sp->bh, sp->thr);
serial_wr_done(sp);
#endif
/* The WRITE completed, we are ready for more. */
sp->lsr |= LSR_THRE;
sp->int_status |= SERINT_TRANSMIT;
update_ints(sp);
} else {
/* Not linked. Just fake LOOPBACK mode. */
if (! (sp->mctrl & MCR_LMS))
@@ -316,19 +294,25 @@ serial_write(uint16_t addr, uint8_t val, void *priv)
baud = ((sp->dlab2<<8) | sp->dlab1);
if (baud > 0) {
speed = 115200UL/baud;
#ifdef ENABLE_SERIAL_LOG
serial_log(2, "Serial%d: divisor %u, baudrate %ld\n",
#endif
sp->port, baud, speed);
if ((sp->bh != NULL) && (speed > 0))
bhtty_speed((BHTTY *)sp->bh, speed);
} else {
#ifdef ENABLE_SERIAL_LOG
serial_log(1, "Serial%d: divisor %u invalid!\n",
sp->port, baud);
#endif
}
}
wl = (val & LCR_WLS) + 5; /* databits */
sb = (val & LCR_SBS) ? 2 : 1; /* stopbits */
pa = (val & (LCR_PE|LCR_EP|LCR_PS)) >> 3;
#ifdef ENABLE_SERIAL_LOG
serial_log(2, "Serial%d: WL=%d SB=%d PA=%d\n", sp->port, wl, sb, pa);
#endif
if (sp->bh != NULL)
bhtty_params((BHTTY *)sp->bh, wl, pa, sb);
sp->lcr = val;
@@ -344,12 +328,17 @@ serial_write(uint16_t addr, uint8_t val, void *priv)
*/
if (sp->rts_callback) {
sp->rts_callback(sp->rts_callback_p);
#ifdef ENABLE_SERIAL_LOG
serial_log(1, "RTS raised; sending ID\n");
#endif
}
}
if ((val & MCR_OUT2) && !(sp->mctrl & MCR_OUT2)) {
if (sp->bh == NULL) {
if (sp->bh != NULL) {
/* Linked, start host port. */
(void)bhtty_active(sp->bh, 1);
} else {
/* Not linked, start RX timer. */
timer_add(serial_timer,
&sp->receive_delay,
@@ -361,11 +350,6 @@ serial_write(uint16_t addr, uint8_t val, void *priv)
MSR_DCD | MSR_DDCD);
sp->int_status |= SERINT_MSR;
update_ints(sp);
#ifdef WALTJE
/* For testing. */
serial_write_str(sp, "Welcome!\r\n");
#endif
}
}
sp->mctrl = val;
@@ -420,12 +404,15 @@ static void
serial_rd_done(void *arg, int num)
{
SERIAL *sp = (SERIAL *)arg;
#ifdef WALTJE
serial_log(0, "%04x: %d bytes available: %02x (%c)\n",sp->addr,num,sp->hold,sp->hold);
#endif
/* Stuff the byte in the FIFO and set intr. */
serial_write_fifo(sp, sp->hold);
/* We can do at least 'num' bytes.. */
while (num-- > 0) {
/* Get a byte from them. */
if (bhtty_read(sp->bh, &sp->hold, 1) < 0) break;
/* Stuff it into the FIFO and set intr. */
serial_write_fifo(sp, sp->hold);
}
}
@@ -440,21 +427,19 @@ serial_read(uint16_t addr, void *priv)
case 0: /* DATA / DLAB1 */
if (sp->lcr & LCR_DLAB) {
ret = sp->dlab1;
break;
} else {
sp->lsr &= ~LSR_DR;
sp->int_status &= ~SERINT_RECEIVE;
update_ints(sp);
ret = read_fifo(sp);
if ((sp->bh == NULL) &&
(sp->fifo_read != sp->fifo_write))
sp->receive_delay = 1000 * TIMER_USEC;
}
sp->lsr &= ~LSR_DR;
sp->int_status &= ~SERINT_RECEIVE;
update_ints(sp);
ret = read_fifo(sp);
if ((sp->bh == NULL) && (sp->fifo_read != sp->fifo_write))
sp->receive_delay = 1000 * TIMER_USEC;
break;
case 1: /* LCR / DLAB2 */
if (sp->lcr & LCR_DLAB)
ret = sp->dlab2;
else
ret = sp->ier;
ret = (sp->lcr & LCR_DLAB) ? sp->dlab2 : sp->ier;
break;
case 2: /* IIR */
@@ -463,9 +448,8 @@ serial_read(uint16_t addr, void *priv)
sp->int_status &= ~SERINT_TRANSMIT;
update_ints(sp);
}
if (sp->fcr & 0x01) {
if (sp->fcr & 0x01)
ret |= 0xc0;
}
break;
case 3: /* LCR */
@@ -512,32 +496,25 @@ serial_setup(int port, uint16_t addr, int irq)
{
SERIAL *sp;
#ifdef ENABLE_SERIAL_LOG
serial_log(0, "Serial%d: I/O=%04x, IRQ=%d\n", port, addr, irq);
#endif
/* Grab the desired port block. */
sp = (port == 2) ? &serial2 : &serial1;
sp = &ports[port-1];
/* Set up the basic info. */
if (sp->addr != 0x0000) {
/* Unlink the previous handler. Just in case. */
io_removehandler(sp->addr, 8,
serial_read, NULL, NULL,
serial_write, NULL, NULL, sp);
serial_read, NULL, NULL, serial_write, NULL, NULL, sp);
}
sp->addr = addr;
sp->irq = irq;
/* Request an I/O range. */
io_sethandler(sp->addr, 8,
serial_read, NULL, NULL,
serial_write, NULL, NULL, sp);
#if 1
/* Do not disable here, it breaks the SIO chips. */
#else
/* No DTR/RTS callback for now. */
sp->rts_callback = NULL;
#endif
serial_read, NULL, NULL, serial_write, NULL, NULL, sp);
}
@@ -548,17 +525,10 @@ serial_remove(int port)
SERIAL *sp;
/* Grab the desired port block. */
sp = (port == 2) ? &serial2 : &serial1;
sp = &ports[port-1];
// FIXME: stop timer, if enabled!
#if 1
/* Do not disable here, it breaks the SIO chips. */
#else
/* Remove any callbacks. */
sp->rts_callback = NULL;
#endif
/* Close the host device. */
if (sp->bh != NULL)
(void)serial_link(port, NULL);
@@ -566,8 +536,7 @@ serial_remove(int port)
/* Release our I/O range. */
if (sp->addr != 0x0000) {
io_removehandler(sp->addr, 8,
serial_read, NULL, NULL,
serial_write, NULL, NULL, sp);
serial_read, NULL, NULL, serial_write, NULL, NULL, sp);
}
sp->addr = 0x0000;
sp->irq = 0;
@@ -578,21 +547,31 @@ serial_remove(int port)
void
serial_init(void)
{
SERIAL *sp;
int i;
#if ENABLE_SERIAL_LOG
serial_do_log = ENABLE_SERIAL_LOG;
#endif
memset(&serial1, 0x00, sizeof(SERIAL));
serial1.port = 1;
serial_setup(serial1.port, SERIAL1_ADDR, SERIAL1_IRQ);
#ifdef xWALTJE
serial_link(serial1.port, "COM1");
#endif
memset(&serial2, 0x00, sizeof(SERIAL));
serial2.port = 2;
serial_setup(serial2.port, SERIAL2_ADDR, SERIAL2_IRQ);
#ifdef xWALTJE
serial_link(serial2.port, "COM2");
/* FIXME: we should probably initialize the platform module here. */
/* Initialize each port. */
for (i=0; i<NUM_SERIAL; i++) {
sp = &ports[i];
memset(sp, 0x00, sizeof(SERIAL));
sp->port = (i+1);
if (i == 0)
serial_setup(sp->port, SERIAL1_ADDR, SERIAL1_IRQ);
else
serial_setup(sp->port, SERIAL2_ADDR, SERIAL2_IRQ);
}
#ifdef WALTJE
/* Link to host port. */
serial_link(1, "COM1");
serial_link(2, "COM2");
#endif
}
@@ -605,11 +584,15 @@ serial_init(void)
void
serial_reset(void)
{
serial1.iir = serial1.ier = serial1.lcr = serial1.mctrl = 0;
serial1.fifo_read = serial1.fifo_write = 0;
SERIAL *sp;
int i;
serial2.iir = serial2.ier = serial2.lcr = serial2.mctrl = 0;
serial2.fifo_read = serial2.fifo_write = 0;
for (i=0; i<NUM_SERIAL; i++) {
sp = &ports[i];
sp->iir = sp->ier = sp->lcr = sp->mctrl = 0x00;
sp->fifo_read = sp->fifo_write = 0x00;
}
}
@@ -621,19 +604,23 @@ serial_link(int port, char *arg)
BHTTY *bh;
/* Grab the desired port block. */
sp = (port == 2) ? &serial2 : &serial1;
sp = &ports[port-1];
if (arg != NULL) {
/* Make sure we're not already linked. */
if (sp->bh != NULL) {
#if ENABLE_SERIAL_LOG
serial_log(0, "Serial%d already linked!\n", port);
#endif
return(-1);
}
/* Request a port from the host system. */
bh = bhtty_open(arg, 0);
if (bh == NULL) {
#if ENABLE_SERIAL_LOG
serial_log(0, "Serial%d unable to link to '%s' !\n", port, arg);
#endif
return(-1);
}
sp->bh = bh;
@@ -661,7 +648,7 @@ serial_attach(int port, void *func, void *arg)
SERIAL *sp;
/* Grab the desired port block. */
sp = (port == 2) ? &serial2 : &serial1;
sp = &ports[port-1];
/* Set up callback info. */
sp->rts_callback = func;