aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/puc/puc.c74
-rw-r--r--sys/dev/puc/pucdata.c66
-rw-r--r--sys/dev/puc/pucvar.h9
-rw-r--r--sys/dev/sio/sio.c34
4 files changed, 144 insertions, 39 deletions
diff --git a/sys/dev/puc/puc.c b/sys/dev/puc/puc.c
index 18d2fbabc0f5..fedf9bb073cf 100644
--- a/sys/dev/puc/puc.c
+++ b/sys/dev/puc/puc.c
@@ -130,6 +130,35 @@ puc_port_bar_index(struct puc_softc *sc, int bar)
return (i);
}
+static int
+puc_probe_ilr(struct puc_softc *sc, struct resource *res)
+{
+ u_char t1, t2;
+ int i;
+
+ switch (sc->sc_desc->ilr_type) {
+ case PUC_ILR_TYPE_DIGI:
+ sc->ilr_st = rman_get_bustag(res);
+ sc->ilr_sh = rman_get_bushandle(res);
+ for (i = 0; i < 2; i++) {
+ t1 = bus_space_read_1(sc->ilr_st, sc->ilr_sh,
+ sc->sc_desc->ilr_offset[i]);
+ t1 = ~t1;
+ bus_space_write_1(sc->ilr_st, sc->ilr_sh,
+ sc->sc_desc->ilr_offset[i], t1);
+ t2 = bus_space_read_1(sc->ilr_st, sc->ilr_sh,
+ sc->sc_desc->ilr_offset[i]);
+ if (t2 == t1)
+ return (0);
+ }
+ return (1);
+
+ default:
+ break;
+ }
+ return (0);
+}
+
int
puc_attach(device_t dev, const struct puc_device_description *desc)
{
@@ -195,6 +224,14 @@ puc_attach(device_t dev, const struct puc_device_description *desc)
}
sc->sc_bar_mappings[bidx].type = type;
sc->sc_bar_mappings[bidx].res = res;
+
+ if (sc->sc_desc->ilr_type != PUC_ILR_TYPE_NONE) {
+ sc->ilr_enabled = puc_probe_ilr(sc, res);
+ if (sc->ilr_enabled)
+ device_printf(dev, "ILR enabled\n");
+ else
+ device_printf(dev, "ILR disabled\n");
+ }
#ifdef PUC_DEBUG
printf("%s rid %d bst %x, start %x, end %x\n",
(type == SYS_RES_MEMORY) ? "memory" : "port", rid,
@@ -307,22 +344,47 @@ puc_attach(device_t dev, const struct puc_device_description *desc)
return (0);
}
+static u_int32_t
+puc_ilr_read(struct puc_softc *sc)
+{
+ u_int32_t mask;
+ int i;
+
+ mask = 0;
+ switch (sc->sc_desc->ilr_type) {
+ case PUC_ILR_TYPE_DIGI:
+ for (i = 1; i >= 0; i--) {
+ mask = (mask << 8) | (bus_space_read_1(sc->ilr_st,
+ sc->ilr_sh, sc->sc_desc->ilr_offset[i]) & 0xff);
+ }
+ break;
+
+ default:
+ mask = 0xffffffff;
+ break;
+ }
+ return (mask);
+}
+
/*
- * This is just a brute force interrupt handler. It just calls all the
- * registered handlers sequencially.
- *
- * Later on we should maybe have a different handler for boards that can
- * tell us which device generated the interrupt.
+ * This is an interrupt handler. For boards that can't tell us which
+ * device generated the interrupt it just calls all the registered
+ * handlers sequencially, but for boards that can tell us which
+ * device(s) generated the interrupt it calls only handlers for devices
+ * that actually generated the interrupt.
*/
static void
puc_intr(void *arg)
{
int i;
+ u_int32_t ilr_mask;
struct puc_softc *sc;
sc = (struct puc_softc *)arg;
+ ilr_mask = sc->ilr_enabled ? puc_ilr_read(sc) : 0xffffffff;
for (i = 0; i < PUC_MAX_PORTS; i++)
- if (sc->sc_ports[i].ihand != NULL)
+ if (sc->sc_ports[i].ihand != NULL &&
+ ((ilr_mask >> i) & 0x00000001))
(sc->sc_ports[i].ihand)(sc->sc_ports[i].ihandarg);
}
diff --git a/sys/dev/puc/pucdata.c b/sys/dev/puc/pucdata.c
index e55621502b6e..7e65aa775a15 100644
--- a/sys/dev/puc/pucdata.c
+++ b/sys/dev/puc/pucdata.c
@@ -1000,23 +1000,24 @@ const struct puc_device_description puc_devices[] = {
{ 0xb00c, 0x091c, 0, 0 },
{ 0xffff, 0xffff, 0, 0 },
{
- { PUC_PORT_TYPE_COM, 0x10, 0x00, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x08, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x10, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x18, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x20, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x28, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x30, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x38, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x40, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x48, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x50, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x58, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x60, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x68, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x70, COM_FREQ * 4 },
- { PUC_PORT_TYPE_COM, 0x10, 0x78, COM_FREQ * 4 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x00, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x08, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x10, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x18, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x20, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x28, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x30, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x38, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x40, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x48, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x50, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x58, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x60, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x68, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x70, COM_FREQ },
+ { PUC_PORT_TYPE_COM, 0x10, 0x78, COM_FREQ },
},
+ PUC_ILR_TYPE_DIGI, { 0x07, 0x47 },
},
{ "IC Book Labs Dreadnought x16 Pro",
@@ -1024,23 +1025,24 @@ const struct puc_device_description puc_devices[] = {
{ 0xb00c, 0x081c, 0, 0 },
{ 0xffff, 0xffff, 0, 0 },
{
- { PUC_PORT_TYPE_COM, 0x10, 0x00, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x08, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x10, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x18, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x20, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x28, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x30, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x38, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x40, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x48, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x50, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x58, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x60, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x68, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x70, COM_FREQ * 8 },
- { PUC_PORT_TYPE_COM, 0x10, 0x78, COM_FREQ * 8 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x00, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x08, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x10, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x18, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x20, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x28, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x30, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x38, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x40, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x48, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x50, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x58, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x60, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x68, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x70, COM_FREQ * 8, 0x200000 },
+ { PUC_PORT_TYPE_COM, 0x10, 0x78, COM_FREQ * 8, 0x200000 },
},
+ PUC_ILR_TYPE_DIGI, { 0x07, 0x47 },
},
{ 0 }
diff --git a/sys/dev/puc/pucvar.h b/sys/dev/puc/pucvar.h
index fcbb0eb86b66..9bb3928340de 100644
--- a/sys/dev/puc/pucvar.h
+++ b/sys/dev/puc/pucvar.h
@@ -80,6 +80,8 @@ struct puc_device_description {
u_int serialfreq;
u_int flags;
} ports[PUC_MAX_PORTS];
+ uint32_t ilr_type;
+ uint32_t ilr_offset[2];
};
#define PUC_REG_VEND 0
@@ -91,6 +93,10 @@ struct puc_device_description {
#define PUC_PORT_TYPE_COM 1
#define PUC_PORT_TYPE_LPT 2
+/* Interrupt Latch Register (ILR) types */
+#define PUC_ILR_TYPE_NONE 0
+#define PUC_ILR_TYPE_DIGI 1
+
#define PUC_FLAGS_MEMORY 0x0001 /* Use memory mapped I/O. */
#define PUC_PORT_VALID(desc, port) \
@@ -126,6 +132,9 @@ struct puc_softc {
int irqrid;
struct resource *irqres;
void *intr_cookie;
+ int ilr_enabled;
+ bus_space_tag_t ilr_st;
+ bus_space_handle_t ilr_sh;
struct {
int used;
diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c
index f5e7363601eb..dcfd46a781f7 100644
--- a/sys/dev/sio/sio.c
+++ b/sys/dev/sio/sio.c
@@ -120,6 +120,7 @@
#define COM_C_IIR_TXRDYBUG (0x80000)
#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
#define COM_NOSCR(flags) ((flags) & 0x100000)
+#define COM_TI16754(flags) ((flags) & 0x200000)
#define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24)
#define sio_getreg(com, off) \
@@ -605,6 +606,33 @@ sioprobe(dev, xrid, rclk, noprobe)
/* EXTRA DELAY? */
/*
+ * For the TI16754 chips set prescaler to 1 (4 is often the
+ * default after-reset value), otherwise it's impossible to
+ * get highest baudrates.
+ */
+ if (COM_TI16754(flags)) {
+ u_char t1, t2;
+
+ /* Save LCR */
+ t1 = sio_getreg(com, com_lctl);
+ /* Enable EFR */
+ sio_setreg(com, com_lctl, 0xbf);
+ /* Save EFR */
+ t2 = sio_getreg(com, com_iir);
+ /* Unlock MCR[7] */
+ sio_setreg(com, com_iir, t2 | 0x10);
+ /* Disable EFR */
+ sio_setreg(com, com_lctl, 0);
+ /* Set prescaler to 1 */
+ sio_setreg(com, com_mcr, sio_getreg(com, com_mcr) & 0x7f);
+ /* Enable EFR */
+ sio_setreg(com, com_lctl, 0xbf);
+ /* Restore EFR */
+ sio_setreg(com, com_iir, t2);
+ /* Restore LCR */
+ sio_setreg(com, com_lctl, t1);
+ }
+ /*
* Initialize the speed and the word size and wait long enough to
* drain the maximum of 16 bytes of junk in device output queues.
* The speed is undefined after a master reset and must be set
@@ -731,6 +759,7 @@ sioprobe(dev, xrid, rclk, noprobe)
failures[0] = sio_getreg(com, com_cfcr) - CFCR_8BITS;
failures[1] = sio_getreg(com, com_ier) - IER_ETXRDY;
failures[2] = (sio_getreg(com, com_mcr) & 0x7f) - mcr_image;
+ failures[2] = sio_getreg(com, com_mcr) - mcr_image;
DELAY(10000); /* Some internal modems need this time */
irqmap[1] = isa_irq_pending();
failures[4] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_TXRDY;
@@ -1007,6 +1036,9 @@ sioattach(dev, xrid, rclk)
com->st16650a = 1;
com->tx_fifo_size = 32;
printf(" ST16650A");
+ } else if (COM_TI16754(flags)) {
+ com->tx_fifo_size = 64;
+ printf(" TI16754");
} else {
com->tx_fifo_size = COM_FIFOSIZE(flags);
printf(" 16550A");
@@ -1019,7 +1051,7 @@ sioattach(dev, xrid, rclk)
break;
}
#endif
- if (!com->st16650a) {
+ if (!com->st16650a && !COM_TI16754(flags)) {
if (!com->tx_fifo_size)
com->tx_fifo_size = 16;
else