Mercurial > ecos
diff packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c @ 161:ac086aa3217e
Merge from eCos master repository on 2001-06-08-21:11:51-BST
| author | jlarmour |
|---|---|
| date | Sun, 10 Jun 2001 19:35:23 +0000 |
| parents | b939e9cada46 |
| children | 0d2b193a635f |
line wrap: on
line diff
--- a/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c +++ b/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c @@ -50,7 +50,7 @@ #include <cyg/io/devtab.h> #include <cyg/io/serial.h> #include <cyg/infra/diag.h> - +#include <cyg/infra/cyg_ass.h> #include <cyg/hal/hal_io.h> // Only compile driver if an inline file with driver details was selected. @@ -110,17 +110,21 @@ #define LSR_FIE 0x80 // Modem Control Register -#define MCR_DTR 0x01 -#define MCR_RTS 0x02 -#define MCR_INT 0x08 // Enable interrupts +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_INT 0x08 // Enable interrupts +#define MCR_LOOP 0x10 // Loopback mode // Interrupt status Register -#define ISR_MS 0x00 -#define ISR_nIP 0x01 -#define ISR_Tx 0x02 -#define ISR_LS 0x06 -#define ISR_Rx 0x04 -#define ISR_RxTO 0x0C +#define ISR_MS 0x00 +#define ISR_nIP 0x01 +#define ISR_Tx 0x02 +#define ISR_Rx 0x04 +#define ISR_LS 0x06 +#define ISR_RxTO 0x0C +#define ISR_64BFIFO 0x20 +#define ISR_FIFOworks 0x40 +#define ISR_FIFOen 0x80 // Modem Status Register #define MSR_DCTS 0x01 @@ -172,6 +176,15 @@ typedef struct pc_serial_info { int int_num; cyg_interrupt serial_interrupt; cyg_handle_t serial_interrupt_handle; +#ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO + enum { + sNone = 0, + s8250, + s16450, + s16550, + s16550a + } deviceType; +#endif } pc_serial_info; static bool pc_serial_init(struct cyg_devtab_entry *tab); @@ -225,20 +238,61 @@ serial_config_port(serial_channel *chan, if (init) { #ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO unsigned char _fcr_thresh; + cyg_uint8 b; - switch(CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO_RX_THRESHOLD) { - default: - case 1: - _fcr_thresh=FCR_RT1; break; - case 4: - _fcr_thresh=FCR_RT4; break; - case 8: - _fcr_thresh=FCR_RT8; break; - case 14: - _fcr_thresh=FCR_RT14; break; + /* First, find out what kind of device it is. */ + ser_chan->deviceType = sNone; + HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP); // enable loopback mode + HAL_READ_UINT8(base+REG_msr, b); + if (0 == (b & 0xF0)) { // see if MSR had CD, RI, DSR or CTS set + HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP|MCR_DTR|MCR_RTS); + HAL_READ_UINT8(base+REG_msr, b); + if (0xF0 != (b & 0xF0)) // check that all of CD,RI,DSR and CTS set + ser_chan->deviceType = s8250; + } + HAL_WRITE_UINT8(base+REG_mcr, 0); // disable loopback mode + + if (ser_chan->deviceType == s8250) { + // Check for a scratch register; scratch register + // indicates 16450 or above. + HAL_WRITE_UINT8(base+REG_scr, 0x55); + HAL_READ_UINT8(base+REG_scr, b); + if (b == 0x55) { + HAL_WRITE_UINT8(base+REG_scr, 0xAA); + HAL_READ_UINT8(base+REG_scr, b); + if (b == 0xAA) + ser_chan->deviceType = s16450; + } } - _fcr_thresh|=FCR_FE|FCR_CRF|FCR_CTF; - HAL_WRITE_UINT8(base+REG_fcr, _fcr_thresh); // Enable and clear FIFO + + if (ser_chan->deviceType == s16450) { + // Check for a FIFO + HAL_WRITE_UINT8(base+REG_fcr, FCR_FE); + HAL_READ_UINT8(base+REG_isr, b); + if (b & ISR_FIFOen) + ser_chan->deviceType = s16550; // but FIFO doesn't + // necessarily work + if (b & ISR_FIFOworks) + ser_chan->deviceType = s16550a; // 16550a FIFOs work + } + + if (ser_chan->deviceType == s16550a) { + switch(CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO_RX_THRESHOLD) { + default: + case 1: + _fcr_thresh=FCR_RT1; break; + case 4: + _fcr_thresh=FCR_RT4; break; + case 8: + _fcr_thresh=FCR_RT8; break; + case 14: + _fcr_thresh=FCR_RT14; break; + } + _fcr_thresh|=FCR_FE|FCR_CRF|FCR_CTF; + HAL_WRITE_UINT8(base+REG_fcr, _fcr_thresh); // Enable and clear FIFO + } + else + HAL_WRITE_UINT8(base+REG_fcr, 0); // make sure it's disabled #endif if (chan->out_cbuf.len != 0) { _ier = IER_RCV; @@ -311,13 +365,12 @@ pc_serial_putc(serial_channel *chan, uns HAL_READ_UINT8(base+REG_lsr, _lsr); if (_lsr & LSR_THE) { -// Transmit buffer is empty + // Transmit buffer is empty HAL_WRITE_UINT8(base+REG_thr, c); return true; - } else { -// No space - return false; } + // No space + return false; } // Fetch a character from the device input buffer, waiting if necessary @@ -526,6 +579,11 @@ pc_serial_DSR(cyg_vector_t vector, cyg_u } break; #endif + default: + // Yes, this assertion may well not be visible. *But* + // if debugging, we may still successfully hit a breakpoint + // on cyg_assert_fail, which _is_ useful + CYG_FAIL("unhandled serial interrupt state"); } HAL_READ_UINT8(base+REG_isr, _isr);
