diff options
author | Jason Downs <downsj@cvs.openbsd.org> | 1999-10-26 13:08:45 +0000 |
---|---|---|
committer | Jason Downs <downsj@cvs.openbsd.org> | 1999-10-26 13:08:45 +0000 |
commit | 546bd01ecd535d31fba12e781b61ee5fb6ecb07f (patch) | |
tree | c3a501480efa586e1ff9bfe4859b262e85356df2 /sys | |
parent | 77eca97247ae8ee00f39dc9a83c7bcbb00c73540 (diff) |
Add com/pccom driver for puc.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/puc/com_puc.c | 272 | ||||
-rw-r--r-- | sys/dev/puc/files.puc | 7 |
2 files changed, 279 insertions, 0 deletions
diff --git a/sys/dev/puc/com_puc.c b/sys/dev/puc/com_puc.c new file mode 100644 index 00000000000..8e935c81c3d --- /dev/null +++ b/sys/dev/puc/com_puc.c @@ -0,0 +1,272 @@ +/* $OpenBSD: com_puc.c,v 1.1 1999/10/26 13:08:44 downsj Exp $ */ + +/* + * Copyright (c) 1997 - 1999, Jason Downs. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name(s) of the author(s) nor the name OpenBSD + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/select.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/syslog.h> +#include <sys/types.h> +#include <sys/device.h> + +#include <machine/intr.h> +#include <machine/bus.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pucvar.h> + +#include <dev/isa/isavar.h> /* XXX */ + +#include "com.h" +#ifdef i386 +#include "pccom.h" +#endif + +#include <dev/ic/comreg.h> +#if NPCCOM > 0 +#include <i386/isa/pccomvar.h> +#endif +#if NCOM > 0 +#include <dev/ic/comvar.h> +#endif +#include <dev/ic/ns16550reg.h> + +#define com_lcr com_cfcr +#define SET(t, f) (t) |= (f) + +int com_puc_match __P((struct device *, void *, void *)); +void com_puc_attach __P((struct device *, struct device *, void *)); + +#if NCOM_PUC +struct cfattach com_puc_ca = { + sizeof(struct com_softc), com_puc_match, com_puc_attach +}; +#endif + +#if NPCCOM_PUC +struct cfattach pccom_puc_ca = { + sizeof(struct com_softc), com_puc_match, com_puc_attach +}; +#endif + +void com_puc_attach2 __P((struct com_softc *)); + +int +com_puc_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct puc_attach_args *pa = aux; + + if (pa->type == PUC_PORT_TYPE_COM) + return(1); + + return(0); +} + +void +com_puc_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct com_softc *sc = (void *)self; + struct puc_attach_args *pa = aux; + const char *intrstr; + + /* Grab a PCI interrupt. */ + intrstr = pci_intr_string(pa->pc, pa->intrhandle); + sc->sc_ih = pci_intr_establish(pa->pc, pa->intrhandle, + IPL_HIGH, comintr, sc, + sc->sc_dev.dv_xname); + if (sc->sc_ih == NULL) { + printf(": couldn't establish interrupt"); + if (intrstr != NULL) + printf(" at %s", intrstr); + printf("\n"); + return; + } + printf(" %s", intrstr); + + sc->sc_iot = pa->t; + sc->sc_ioh = pa->h; + sc->sc_iobase = pa->a; + + com_puc_attach2(sc); +} + +/* + * XXX This should be handled by a generic attach + */ +void +com_puc_attach2(sc) + struct com_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + u_int8_t lcr; + + sc->sc_hwflags = 0; + sc->sc_swflags = 0; + + /* + * Probe for all known forms of UART. + */ + lcr = bus_space_read_1(iot, ioh, com_lcr); + + bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + bus_space_write_1(iot, ioh, com_efr, 0); + bus_space_write_1(iot, ioh, com_lcr, 0); + + bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE); + delay(100); + + switch(bus_space_read_1(iot, ioh, com_iir) >> 6) { + case 0: + sc->sc_uarttype = COM_UART_16450; + break; + case 2: + sc->sc_uarttype = COM_UART_16550; + break; + case 3: + sc->sc_uarttype = COM_UART_16550A; + break; + default: + sc->sc_uarttype = COM_UART_UNKNOWN; + break; + } + + if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for ST16650s */ + bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); + if (bus_space_read_1(iot, ioh, com_efr) == 0) { + sc->sc_uarttype = COM_UART_ST16650; + } else { + bus_space_write_1(iot, ioh, com_lcr, LCR_EFR); + if (bus_space_read_1(iot, ioh, com_efr) == 0) + sc->sc_uarttype = COM_UART_ST16650V2; + } + } + +#if NPCCOM > 0 +#ifdef i386 + if (sc->sc_uarttype == COM_UART_ST16650V2) { /* Probe for XR16850s */ + u_int8_t dlbl, dlbh; + + /* Enable latch access and get the current values. */ + bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB); + dlbl = bus_space_read_1(iot, ioh, com_dlbl); + dlbh = bus_space_read_1(iot, ioh, com_dlbh); + + /* Zero out the latch divisors */ + bus_space_write_1(iot, ioh, com_dlbl, 0); + bus_space_write_1(iot, ioh, com_dlbh, 0); + + if (bus_space_read_1(iot, ioh, com_dlbh) == 0x10) { + sc->sc_uarttype = COM_UART_XR16850; + sc->sc_uartrev = bus_space_read_1(iot, ioh, com_dlbl); + } + + /* Reset to original. */ + bus_space_write_1(iot, ioh, com_dlbl, dlbl); + bus_space_write_1(iot, ioh, com_dlbh, dlbh); + } +#endif +#endif + + /* Reset the LCR (latch access is probably enabled). */ + bus_space_write_1(iot, ioh, com_lcr, lcr); + if (sc->sc_uarttype == COM_UART_16450) { /* Probe for 8250 */ + u_int8_t scr0, scr1, scr2; + + scr0 = bus_space_read_1(iot, ioh, com_scratch); + bus_space_write_1(iot, ioh, com_scratch, 0xa5); + scr1 = bus_space_read_1(iot, ioh, com_scratch); + bus_space_write_1(iot, ioh, com_scratch, 0x5a); + scr2 = bus_space_read_1(iot, ioh, com_scratch); + bus_space_write_1(iot, ioh, com_scratch, scr0); + + if ((scr1 != 0xa5) || (scr2 != 0x5a)) + sc->sc_uarttype = COM_UART_8250; + } + + /* + * Print UART type and initialize ourself. + */ + sc->sc_fifolen = 1; /* default */ + switch (sc->sc_uarttype) { + case COM_UART_UNKNOWN: + printf(": unknown uart\n"); + break; + case COM_UART_8250: + printf(": ns8250, no fifo\n"); + break; + case COM_UART_16450: + printf(": ns16450, no fifo\n"); + break; + case COM_UART_16550: + printf(": ns16550, no working fifo\n"); + break; + case COM_UART_16550A: + printf(": ns16550a, 16 byte fifo\n"); + SET(sc->sc_hwflags, COM_HW_FIFO); + sc->sc_fifolen = 16; + break; + case COM_UART_ST16650: + printf(": st16650, no working fifo\n"); + break; + case COM_UART_ST16650V2: + printf(": st16650, 32 byte fifo\n"); + SET(sc->sc_hwflags, COM_HW_FIFO); + sc->sc_fifolen = 32; + break; +#if NPCCOM > 0 +#ifdef i386 + case COM_UART_XR16850: + printf(": xr16850 (rev %d), 128 byte fifo\n", sc->sc_uartrev); + SET(sc->sc_hwflags, COM_HW_FIFO); + sc->sc_fifolen = 128; + break; +#endif +#endif + default: + panic("comattach: bad fifo type"); + } + + /* clear and disable fifo */ + bus_space_write_1(iot, ioh, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST); + (void)bus_space_read_1(iot, ioh, com_data); + bus_space_write_1(iot, ioh, com_fifo, 0); +} diff --git a/sys/dev/puc/files.puc b/sys/dev/puc/files.puc new file mode 100644 index 00000000000..237cb05b434 --- /dev/null +++ b/sys/dev/puc/files.puc @@ -0,0 +1,7 @@ +# $OpenBSD: files.puc,v 1.1 1999/10/26 13:08:44 downsj Exp $ +# +# Config file and device description for machine-independent PUC drivers. +# Requires PCI to be defined first. + +attach com at puc with com_puc +file dev/puc/com_puc.c com_puc | pccom_puc |