From 084254f80770c2c3fd71da3a2fe223b8d4b8b102 Mon Sep 17 00:00:00 2001 From: Maxim Sobolev Date: Sat, 15 Mar 2003 16:25:40 +0000 Subject: - Add minimal support for TI16754 4xUART chip into sio(4) driver and remove now unnecessary hack from the previous commit; - Add support for Interrupt Latch Register (ILR) into puc(4). So far only ILRs compatible with specifications from Digi International are supported. Support for other types of ILRs could be easily added later; - Correct clock frequency for IC Book Labs Dreadnought x16 Lite board; - Enable ILR detection/usage for IC Book Labs Dreadnought x16 boards. Sponsored by: IC Book Labs MFC after: 2 weeks --- sys/dev/puc/puc.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++----- sys/dev/puc/pucdata.c | 70 +++++++++++++++++++++++++----------------------- sys/dev/puc/pucvar.h | 9 +++++++ 3 files changed, 113 insertions(+), 40 deletions(-) (limited to 'sys/dev/puc') 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; -- cgit v1.3