summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJason Downs <downsj@cvs.openbsd.org>1999-10-26 13:08:45 +0000
committerJason Downs <downsj@cvs.openbsd.org>1999-10-26 13:08:45 +0000
commit546bd01ecd535d31fba12e781b61ee5fb6ecb07f (patch)
treec3a501480efa586e1ff9bfe4859b262e85356df2 /sys
parent77eca97247ae8ee00f39dc9a83c7bcbb00c73540 (diff)
Add com/pccom driver for puc.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/puc/com_puc.c272
-rw-r--r--sys/dev/puc/files.puc7
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