summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorhauke <hauke@NetBSD.org>2008-05-22 19:49:43 +0000
committerhauke <hauke@NetBSD.org>2008-05-22 19:49:43 +0000
commitf5ede5dc2e30f76dd40b9f82eeb4092957f2e30f (patch)
treebbcfa0a357e835b5393670e754309f9ea466ae9b /sys
parent1f2b983e85485198a6e39185c189883697583598 (diff)
Added driver for the Creative Systems Inc. Hurdler CPI parallel printer card.
Timecounter support for the Z8536 counters A + B is not complete, yet. Reviewed by Martin Husemann.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/mac68k/conf/GENERIC10
-rw-r--r--sys/arch/mac68k/conf/files.mac68k6
-rw-r--r--sys/arch/mac68k/conf/majors.mac68k3
-rw-r--r--sys/arch/mac68k/nubus/cpi_nubus.c770
-rw-r--r--sys/arch/mac68k/nubus/cpi_nubusvar.h88
-rw-r--r--sys/arch/macppc/stand/ofwboot/Makefile4
-rw-r--r--sys/arch/macppc/stand/ofwboot/ofdev.c23
-rw-r--r--sys/dev/ic/z8536reg.h244
8 files changed, 1134 insertions, 14 deletions
diff --git a/sys/arch/mac68k/conf/GENERIC b/sys/arch/mac68k/conf/GENERIC
index 7e1b4ae6aa4..45d8772020d 100644
--- a/sys/arch/mac68k/conf/GENERIC
+++ b/sys/arch/mac68k/conf/GENERIC
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.186 2007/12/31 15:31:58 ad Exp $
+# $NetBSD: GENERIC,v 1.187 2008/05/22 19:49:43 hauke Exp $
#
# GENERIC machine description file
#
@@ -22,7 +22,7 @@ include "arch/mac68k/conf/std.mac68k"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "GENERIC-$Revision: 1.186 $"
+#ident "GENERIC-$Revision: 1.187 $"
maxusers 16 # estimated number of users
@@ -227,6 +227,12 @@ wskbd* at akbd? console ?
wsmouse* at ams?
+# Centronics printer port
+
+# CSI Hurdler Centronics Parallel Interface
+cpi* at nubus?
+
+
# Serial Devices
# On-board serial interface
diff --git a/sys/arch/mac68k/conf/files.mac68k b/sys/arch/mac68k/conf/files.mac68k
index e79ae14d6a0..bcd4364c45f 100644
--- a/sys/arch/mac68k/conf/files.mac68k
+++ b/sys/arch/mac68k/conf/files.mac68k
@@ -1,4 +1,4 @@
-# $NetBSD: files.mac68k,v 1.121 2008/02/20 21:43:34 drochner Exp $
+# $NetBSD: files.mac68k,v 1.122 2008/05/22 19:49:43 hauke Exp $
# mac68k-specific configuration info
@@ -131,6 +131,10 @@ include "dev/ata/files.ata"
attach wdc at obio with wdc_obio
file arch/mac68k/obio/wdc_obio.c wdc_obio
+device cpi { }
+attach cpi at nubus
+file arch/mac68k/nubus/cpi_nubus.c cpi
+
device zsc { channel = -1 }
attach zsc at obio
file arch/mac68k/dev/zs.c zsc needs-flag
diff --git a/sys/arch/mac68k/conf/majors.mac68k b/sys/arch/mac68k/conf/majors.mac68k
index e979f1adb9f..e8804522dca 100644
--- a/sys/arch/mac68k/conf/majors.mac68k
+++ b/sys/arch/mac68k/conf/majors.mac68k
@@ -1,4 +1,4 @@
-# $NetBSD: majors.mac68k,v 1.19 2007/12/31 15:31:59 ad Exp $
+# $NetBSD: majors.mac68k,v 1.20 2008/05/22 19:49:43 hauke Exp $
#
# Device majors for mac68k
#
@@ -49,6 +49,7 @@ device-major wd char 49 block 22 wd
device-major cgd char 51 block 23 cgd
device-major ksyms char 52 ksyms
device-major wsfont char 53 wsfont
+device-major cpi char 54 cpi
device-major nsmb char 98 nsmb
diff --git a/sys/arch/mac68k/nubus/cpi_nubus.c b/sys/arch/mac68k/nubus/cpi_nubus.c
new file mode 100644
index 00000000000..616278d371b
--- /dev/null
+++ b/sys/arch/mac68k/nubus/cpi_nubus.c
@@ -0,0 +1,770 @@
+/* $NetBSD */
+
+/*-
+ * Copyright (c) 2008 Hauke Fath
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: cpi_nubus.c,v 1.1 2008/05/22 19:49:43 hauke Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/event.h>
+#include <sys/callout.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/errno.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/viareg.h>
+
+#include <dev/ic/z8536reg.h>
+#include <mac68k/nubus/nubus.h>
+#include <mac68k/nubus/cpi_nubusvar.h>
+
+#include "ioconf.h"
+
+#ifdef DEBUG
+#define CPI_DEBUG
+#endif
+
+/*
+ * Stuff taken from Egan/Teixeira ch 8: 'if(TRACE_FOO)' debug output
+ * statements don't break indentation, and when DEBUG is not defined,
+ * the compiler code optimizer drops them as dead code.
+ */
+#ifdef CPI_DEBUG
+#define M_TRACE_CONFIG 0x0001
+#define M_TRACE_OPEN 0x0002
+#define M_TRACE_CLOSE 0x0004
+#define M_TRACE_READ 0x0008
+#define M_TRACE_WRITE 0x0010
+#define M_TRACE_IOCTL 0x0020
+#define M_TRACE_STATUS 0x0040
+#define M_TRACE_ALL 0xFFFF
+#define M_TRACE_NONE 0x0000
+
+#define TRACE_CONFIG (cpi_debug_mask & M_TRACE_CONFIG)
+#define TRACE_OPEN (cpi_debug_mask & M_TRACE_OPEN)
+#define TRACE_CLOSE (cpi_debug_mask & M_TRACE_CLOSE)
+#define TRACE_READ (cpi_debug_mask & M_TRACE_READ)
+#define TRACE_WRITE (cpi_debug_mask & M_TRACE_WRITE)
+#define TRACE_IOCTL (cpi_debug_mask & M_TRACE_IOCTL)
+#define TRACE_STATUS (cpi_debug_mask & M_TRACE_STATUS)
+#define TRACE_ALL (cpi_debug_mask & M_TRACE_ALL)
+#define TRACE_NONE (cpi_debug_mask & M_TRACE_NONE)
+
+uint32_t cpi_debug_mask = M_TRACE_NONE /* | M_TRACE_WRITE */ ;
+
+#else
+#define TRACE_CONFIG 0
+#define TRACE_OPEN 0
+#define TRACE_CLOSE 0
+#define TRACE_READ 0
+#define TRACE_WRITE 0
+#define TRACE_IOCTL 0
+#define TRACE_STATUS 0
+#define TRACE_ALL 0
+#define TRACE_NONE 0
+#endif
+
+#undef USE_CIO_TIMERS /* TBD */
+
+/* autoconf interface */
+int cpi_nubus_match(device_t, cfdata_t, void *);
+void cpi_nubus_attach(device_t, device_t, void *);
+void cpi_nubus_intr(void *);
+
+CFATTACH_DECL(cpi, sizeof(struct cpi_softc),
+ cpi_nubus_match, cpi_nubus_attach, NULL, NULL);
+
+dev_type_open(cpi_open);
+dev_type_close(cpi_close);
+dev_type_read(cpi_read);
+dev_type_write(cpi_write);
+dev_type_ioctl(cpi_ioctl);
+
+const struct cdevsw cpi_cdevsw = {
+ cpi_open, cpi_close, noread, cpi_write, cpi_ioctl,
+ nostop, notty, nopoll, nommap, nokqfilter, D_OTHER
+};
+
+/* prototypes */
+static void cpi_lpreset(struct cpi_softc *);
+static int cpi_notready(struct cpi_softc *);
+static void cpi_wakeup(void *);
+static int cpi_flush(struct cpi_softc *);
+static void cpi_intr(void *);
+
+#ifdef USE_CIO_TIMERS
+static void cpi_initclock(struct cpi_softc *);
+static u_int cpi_get_timecount(struct timecounter *);
+#endif
+
+static inline void z8536_reg_set(bus_space_tag_t, bus_space_handle_t,
+ uint8_t, uint8_t);
+static inline uint8_t z8536_reg_get(bus_space_tag_t, bus_space_handle_t,
+ uint8_t);
+
+
+const uint8_t cio_reset[] = {
+ /* register value */
+ Z8536_MICR, 0x00,
+ Z8536_MICR, MICR_RESET,
+ Z8536_MICR, 0x00
+};
+
+const uint8_t cio_init[] = {
+ /* register value */
+
+ /* Interrupt vectors - clear all */
+ Z8536_IVRA, 0x00,
+ Z8536_IVRB, 0x00,
+ Z8536_IVRCT, 0x20 /* ??? Do we use this? */,
+
+ /*
+ * Port A specification - bit port, single buffered,
+ * latched output, pulsed handshake, all bits non-inverting
+ * non-special I/O
+ */
+ Z8536_PMSRA, PMSR_PTS_OUT | PMSR_LPM,
+ Z8536_PHSRA, PHSR_HTS_PUL,
+ Z8536_DPPRA, 0x00,
+ Z8536_DDRA, 0x00,
+ Z8536_SIOCRA, 0x00,
+
+ /*
+ * Port B specification - bit port, transparent output,
+ * pulsed handshake, all bits non-inverting
+ * bits 0, 4 output; bits 1-3, 5-8 input,
+ * non-special I/O
+ * Pattern matching: Bit 6 (BUSY) matching "1"
+ * Alternatively: Bit 3 (/ACK) matching "0"
+ */
+ Z8536_PMSRB, PMSR_PMS_OR_PEV,
+ Z8536_PHSRB, 0x00,
+ Z8536_DPPRB, 0x00,
+ Z8536_DDRB, 0xee /*11101110b*/,
+ Z8536_SIOCRB, 0x00,
+ Z8536_PPRB, 0x00,
+ Z8536_PTRB, 0x00,
+ Z8536_PMRB, 0x40 /*01000000b = PB6 */,
+
+ Z8536_PDRB, 0xFE, /* Assign printer -RESET */
+ Z8536_PCSRA, 0x00, /* Clear port A interrupt bits */
+
+ /*
+ * Port C specification - bit 3 out, bits 0-2 in,
+ * all 4 non-inverting, non-special I/O
+ */
+ Z8536_DDRC, 0x07 /*00000111b*/,
+ Z8536_DPPRC, 0x00,
+ Z8536_SIOCRC, 0x00,
+
+#ifdef USE_CIO_TIMERS
+ /*
+ * Counter/Timers 1+2 are joined to form a free-running
+ * 32 bit timecounter
+ */
+ Z8536_CTMSR1, CTMS_CSC,
+ Z8536_CTTCR1_MSB, 0x00,
+ Z8536_CTTCR1_LSB, 0x00,
+ Z8536_CTMSR2, CTMS_CSC,
+ Z8536_CTTCR2_MSB, 0x00,
+ Z8536_CTTCR2_LSB, 0x00,
+#endif /* USE_CIO_TIMERS */
+
+ /*
+ * We need Timer 3 for running port A in strobed mode.
+ *
+ * Counter/Timer 3 specification -- clear IP & IUS, trigger +
+ * gate command bit, one-shot operation
+ */
+ Z8536_CTCSR3, CTCS_CLR_IP_IUS | CTCS_GCB | CTCS_TCB,
+ Z8536_CTMSR3, CTMS_DCS_ONESHOT,
+ Z8536_CTTCR3_MSB, 0x00,
+ Z8536_CTTCR3_LSB, 0x03,
+
+ /*
+ * Enable ports A+B+C+CT3
+ * Set timer 1 to clock timer 2, but not yet enabled.
+ */
+ Z8536_MCCR, MCCR_PAE | MCCR_PBE | MCCR_CT1CT2 | MCCR_PC_CT3E,
+ /* Master Interrupt Enable, Disable Lower Chain,
+ * No Vector, port A+B+CT vectors include status */
+ Z8536_MICR, MICR_MIE | MICR_DLC | MICR_NV | MICR_PAVIS |
+ MICR_PBVIS | MICR_CTVIS,
+ Z8536_PDRB, 0xFE, /* Clear printer -RESET */
+};
+
+
+/*
+ * Look for Creative Systems Inc. "Hurdler Centronics Parallel Interface"
+ */
+int
+cpi_nubus_match(device_t parent, cfdata_t cf, void *aux)
+{
+ struct nubus_attach_args *na;
+
+ na = aux;
+ if ((na->category == NUBUS_CATEGORY_COMMUNICATIONS) &&
+ (na->type == NUBUS_TYPE_CENTRONICS) &&
+ (na->drsw == NUBUS_DRSW_CPI) &&
+ (na->drhw == NUBUS_DRHW_CPI))
+ return 1;
+ else
+ return 0;
+}
+
+void
+cpi_nubus_attach(device_t parent, device_t self, void *aux)
+{
+ struct cpi_softc *sc;
+ struct nubus_attach_args *na;
+ int err, ii;
+
+ sc = device_private(self);
+ na = aux;
+ sc->sc_bst = na->na_tag;
+ memcpy(&sc->sc_slot, na->fmt, sizeof(nubus_slot));
+ sc->sc_basepa = (bus_addr_t)NUBUS_SLOT2PA(na->slot);
+
+ /*
+ * The CIO sits on the MSB (top byte lane) of the 32 bit
+ * Nubus, so map 16 byte.
+ */
+ if (TRACE_CONFIG) {
+ printf("\n");
+ printf("\tcpi_nubus_attach() mapping 8536 CIO at 0x%lx.\n",
+ sc->sc_basepa + CIO_BASE_OFFSET);
+ }
+
+ err = bus_space_map(sc->sc_bst, sc->sc_basepa + CIO_BASE_OFFSET,
+ (Z8536_IOSIZE << 4), 0, &sc->sc_bsh);
+ if (err) {
+ aprint_normal(": failed to map memory space.\n");
+ return;
+ }
+
+ sc->sc_lpstate = LP_INITIAL;
+ sc->sc_intcount = 0;
+ sc->sc_bytestoport = 0;
+
+ if (TRACE_CONFIG)
+ printf("\tcpi_nubus_attach() about to set up 8536 CIO.\n");
+
+ for (ii = 0; ii < sizeof(cio_reset); ii += 2)
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, cio_reset[ii],
+ cio_reset[ii + 1]);
+
+ delay(1000); /* Just in case */
+ for (ii = 0; ii < sizeof(cio_init); ii += 2) {
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, cio_init[ii],
+ cio_init[ii + 1]);
+ }
+
+ if (TRACE_CONFIG)
+ printf("\tcpi_nubus_attach() done with 8536 CIO setup.\n");
+
+ /* XXX Get the information strings from the card's ROM */
+ aprint_normal(": CSI Hurdler II Centronics\n");
+
+#ifdef USE_CIO_TIMERS
+ /* Attach CIO timers as timecounters */
+ if (TRACE_CONFIG)
+ printf("\tcpi_nubus_attach() about to attach timers\n");
+
+ cpi_initclock(sc);
+#endif /* USE_CIO_TIMERS */
+
+ callout_init(&sc->sc_wakeupchan, 0); /* XXX */
+
+ /* make sure interrupts are vectored to us */
+ add_nubus_intr(na->slot, cpi_nubus_intr, sc);
+}
+
+void
+cpi_nubus_intr(void *arg)
+{
+ struct cpi_softc *sc;
+ int s;
+
+ sc = (struct cpi_softc *)arg;
+
+ s = spltty();
+
+ sc->sc_intcount++;
+
+ /* Check for interrupt source, and clear interrupt */
+
+ /*
+ * Clear port A interrupt
+ * Interrupt from register A, clear "pending"
+ * and set "under service"
+ */
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IE);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IUS);
+
+ cpi_intr(sc);
+
+ /* Interrupt from register A, mark serviced */
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IUS);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IE);
+
+ splx(s);
+}
+
+
+/* cpi nuts and bolts */
+
+int
+cpi_open(dev_t device, int flag, int mode, struct lwp *l)
+{
+ int lpunit;
+ int err, ii, s;
+ struct cpi_softc *sc;
+
+ if (TRACE_OPEN)
+ printf("\tcpi_open() called...\n");
+
+ /* Consistency checks: Valid unit number, softc, device state */
+ lpunit = CPI_UNIT(device);
+ if (lpunit >= cpi_cd.cd_ndevs) {
+ if (TRACE_OPEN)
+ printf("Tried to cpi_open() invalid unit (%d >= %d)\n",
+ lpunit, cpi_cd.cd_ndevs);
+ return ENXIO;
+ }
+ sc = device_lookup(&cpi_cd, lpunit);
+ if (NULL == sc) {
+ if (TRACE_OPEN)
+ printf("Tried to cpi_open() with NULL softc\n");
+ return ENXIO;
+ }
+ if (sc->sc_lpstate != LP_INITIAL) {
+ if (TRACE_OPEN)
+ printf("%s not in initial state (%x).\n",
+ sc->sc_dev.dv_xname, sc->sc_lpstate);
+ return EBUSY;
+ }
+ sc->sc_lpstate = LP_OPENING;
+
+ if (TRACE_OPEN)
+ printf("\tcpi_open() resetting the printer...\n");
+ cpi_lpreset(sc);
+
+ if (TRACE_OPEN)
+ printf("\tcpi_open() waiting for printer ready...\n");
+
+ /* Wait max 15 sec for printer to get ready */
+ for (ii = 15; cpi_notready(sc); ii--) {
+ if (0 == ii) {
+ sc->sc_lpstate = LP_INITIAL;
+ return EBUSY;
+ }
+ /* sleep for a second, unless we get a signal */
+ err = ltsleep(sc, PZERO | PCATCH, "cpi_open", hz, NULL);
+ if (err != EWOULDBLOCK) {
+ sc->sc_lpstate = LP_INITIAL;
+ return err;
+ }
+ }
+ if (TRACE_OPEN)
+ printf("\tcpi_open() allocating printer buffer...\n");
+
+ /* Allocate the driver's line buffer */
+ sc->sc_printbuf = malloc(CPI_BUFSIZE, M_DEVBUF, M_WAITOK);
+ sc->sc_bufbytes = 0;
+ sc->sc_lpstate = LP_OPEN;
+
+ /* Statistics */
+ sc->sc_intcount = 0;
+ sc->sc_bytestoport = 0;
+
+ /* Kick off transfer */
+ cpi_wakeup(sc);
+
+ /*
+ * Reset "interrupt {pending, under service}" bits, then
+ * enable Port A interrupts
+ */
+ s = spltty();
+
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP_IUS);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_SET_IE);
+ splx(s);
+
+ if (TRACE_OPEN)
+ printf("\tcpi_open() done...\n");
+
+ return 0;
+}
+
+int
+cpi_close(dev_t device, int flag, int mode, struct lwp *l)
+{
+ struct cpi_softc *sc;
+ int lpunit;
+
+ lpunit = CPI_UNIT(device);
+ sc = device_lookup(&cpi_cd, lpunit);
+
+ if (TRACE_CLOSE)
+ printf("\tcpi_close() called (%lu hard, %lu bytes to port)\n",
+ sc->sc_intcount, sc->sc_bytestoport);
+
+ /* Flush the remaining buffer content, ignoring any errors */
+ if (0 < sc->sc_bufbytes)
+ (void)cpi_flush(sc);
+
+ callout_stop(&sc->sc_wakeupchan);
+
+ /* Disable Port A interrupts */
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IE);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PCSRA, PCSR_CLR_IP_IUS);
+
+ sc->sc_lpstate = LP_INITIAL;
+ free(sc->sc_printbuf, M_DEVBUF);
+
+ return 0;
+}
+
+int
+cpi_write(dev_t device, struct uio *uio, int flags)
+{
+ int err;
+ size_t numbytes;
+ struct cpi_softc *sc;
+
+ err = 0;
+
+ if (TRACE_WRITE)
+ printf("\tcpi_write() called for %u bytes\n", uio->uio_resid);
+
+ sc = device_lookup(&cpi_cd, CPI_UNIT(device));
+
+ /* Send data to printer, a line buffer full at a time */
+ while (uio->uio_resid > 0) {
+ numbytes = min(CPI_BUFSIZE, uio->uio_resid);
+ sc->sc_cp = sc->sc_printbuf;
+ uiomove(sc->sc_cp, numbytes, uio);
+ sc->sc_bufbytes = numbytes;
+
+ if (TRACE_WRITE)
+ printf("\tQueuing %u bytes\n", numbytes);
+ err = cpi_flush(sc);
+ if (err) {
+ /* Failure; adjust residual counter */
+ if (TRACE_WRITE)
+ printf("\tQueuing failed with %d\n", err);
+ uio->uio_resid += sc->sc_bufbytes;
+ sc->sc_bufbytes = 0;
+ break;
+ }
+ }
+ return err;
+}
+
+int
+cpi_ioctl(dev_t device, unsigned long cmd, void *data,
+ int flag, struct lwp *l)
+{
+ int err;
+
+ err = 0;
+
+ if (TRACE_IOCTL)
+ printf("\tcpi_ioctl() called with %ld...\n", cmd);
+
+ switch (cmd) {
+ default:
+ if (TRACE_IOCTL)
+ printf("\tcpi_ioctl() unknown ioctl %ld\n", cmd);
+ err = ENODEV;
+ break;
+ }
+ return err;
+}
+
+/*
+ * Flush the print buffer that our top half uses to provide data to
+ * our bottom, interrupt-driven half.
+ */
+static int
+cpi_flush(struct cpi_softc *sc)
+{
+ int err, s;
+
+ err = 0;
+ while (0 < sc->sc_bufbytes) {
+ /* Feed the printer a char, if it's ready */
+ if ( !cpi_notready(sc)) {
+ if (TRACE_WRITE)
+ printf("\tcpi_flush() writes %u bytes "
+ "(%lu hard, %lu bytes to port)\n",
+ sc->sc_bufbytes, sc->sc_intcount,
+ sc->sc_bytestoport);
+ s = spltty();
+ cpi_intr(sc);
+ splx(s);
+ }
+ /* XXX Sure we want to wait forever for the printer? */
+ err = ltsleep((void *)sc, PZERO | PCATCH,
+ "cpi_flush", (60 * hz), NULL);
+ }
+ return err;
+}
+
+
+static void
+cpi_wakeup(void *param)
+{
+ struct cpi_softc *sc;
+ int s;
+
+ sc = param;
+
+ s = spltty();
+ cpi_intr(sc);
+ splx(s);
+
+ callout_reset(&sc->sc_wakeupchan, hz, cpi_wakeup, sc);
+}
+
+
+static void
+cpi_lpreset(struct cpi_softc *sc)
+{
+ uint8_t portb; /* Centronics -RESET is on port B, bit 0 */
+#ifdef DIRECT_PORT_ACCESS
+ int s;
+
+ s = spltty();
+
+ portb = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTB);
+ bus_space_write_1(sc->sc_bst, sc->sc_bsh,
+ CIO_PORTB, portb & ~CPI_RESET);
+ delay(100);
+ portb = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTB);
+ bus_space_write_1(sc->sc_bst, sc->sc_bsh,
+ CIO_PORTB, portb | CPI_RESET);
+
+ splx(s);
+#else
+ portb = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_PDRB);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PDRB, portb & ~CPI_RESET);
+ delay(100);
+ portb = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_PDRB);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_PDRB, portb | CPI_RESET);
+#endif /* DIRECT_PORT_ACCESS */
+}
+
+
+/*
+ * Centronics BUSY is on port B, bit 6
+ * SELECT is on Port B, bit 5
+ * /FAULT is on Port B, bit 1
+ * PAPER EMPTY is on Port C, bit 1
+ */
+static int
+cpi_notready(struct cpi_softc *sc)
+{
+ uint8_t portb, portc;
+ int is_busy, is_select, is_fault, is_paper_empty;
+
+ if (TRACE_STATUS)
+ printf("\tcpi_notready() checking printer status...\n");
+
+ portb = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTB);
+ if (TRACE_STATUS)
+ printf("\tPort B has 0x0%X\n", portb);
+
+ is_busy = CPI_BUSY & portb;
+ if (TRACE_STATUS)
+ printf("\t\tBUSY = %d\n", is_busy);
+
+ is_select = CPI_SELECT & portb;
+ if (TRACE_STATUS)
+ printf("\t\tSELECT = %d\n", is_select);
+
+ is_fault = CPI_FAULT & portb;
+ if (TRACE_STATUS)
+ printf("\t\t/FAULT = %d\n", is_fault);
+
+ portc = bus_space_read_1(sc->sc_bst, sc->sc_bsh, CIO_PORTC);
+ if (TRACE_STATUS)
+ printf("\tPort C has 0x0%X\n", portc);
+
+ is_paper_empty = CPI_PAPER_EMPTY & portc;
+ if (TRACE_STATUS)
+ printf("\t\tPAPER EMPTY = %d\n", is_paper_empty);
+
+ return (is_busy || !is_select || !is_fault || is_paper_empty);
+}
+
+static void
+cpi_intr(void *arg)
+{
+ struct cpi_softc *sc;
+
+ sc = arg;
+
+ /* Printer ready for output? */
+ if (cpi_notready(sc))
+ return;
+
+ if (0 && TRACE_WRITE)
+ printf("\tcpi_soft_intr() has %u bytes.\n", sc->sc_bufbytes);
+
+ /* Anything to print? */
+ if (sc->sc_bufbytes) {
+ /* Data byte */
+ bus_space_write_1(sc->sc_bst, sc->sc_bsh,
+ CIO_PORTA, *sc->sc_cp++);
+ sc->sc_bufbytes--;
+ sc->sc_bytestoport++;
+ }
+ if (0 == sc->sc_bufbytes)
+ /* line buffer empty, wake up our top half */
+ wakeup((void *)sc);
+}
+
+#ifdef USE_CIO_TIMERS
+/*
+ * Z8536 CIO timers 1 + 2 used for timecounter(9) support
+ */
+static void
+cpi_initclock(struct cpi_softc *sc)
+{
+ static struct timecounter cpi_timecounter = {
+ .tc_get_timecount = cpi_get_timecount,
+ .tc_poll_pps = 0,
+ .tc_counter_mask = 0x0ffffu,
+ .tc_frequency = CLK_FREQ,
+ .tc_name = "CPI Z8536 CIO",
+ .tc_quality = 50,
+ .tc_priv = NULL,
+ .tc_next = NULL
+ };
+
+ /*
+ * Set up timers A and B as a single, free-running 32 bit counter
+ */
+
+ /* Disable counters A and B */
+ reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_MCCR);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_MCCR,
+ reg & ~(MCCR_CT1E | MCCR_CT2E));
+
+ /* Make sure interrupt enable bits are cleared */
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1,
+ CTCS_CLR_IE);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2,
+ CTCS_CLR_IE);
+
+ /* Initialise counter start values, and set to continuous cycle */
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTMSR1, CTMS_CSC);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR1_MSB, 0x00);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR1_LSB, 0x00);
+
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTMSR2, CTMS_CSC);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR2_MSB, 0x00);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTTCR2_LSB, 0x00);
+
+ /* Re-enable counters A and B */
+ reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_MCCR);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_MCCR,
+ reg | MCCR_CT1E | MCCR_CT2E | MCCR_CT1CT2);
+
+ /* Start counters A and B */
+ reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1,
+ reg | CTCS_TCB);
+ reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2);
+ z8536_reg_set(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2,
+ reg | CTCS_TCB);
+
+ tc_init(&cpi_timecounter);
+}
+
+static u_int
+cpi_get_timecount(struct timecounter *tc)
+{
+ uint8_t high, high2, low;
+ int s;
+
+ /*
+ * Make the timer access atomic
+ *
+ * XXX How expensive is this? And is it really necessary?
+ */
+ s = splhigh();
+
+ /* TBD */
+
+}
+#endif /* USE_CIO_TIMERS */
+
+
+/*
+ * Z8536 CIO nuts and bolts
+ */
+
+static inline void
+z8536_reg_set(bus_space_tag_t bspace, bus_space_handle_t bhandle,
+ uint8_t reg, uint8_t val)
+{
+ int s;
+
+ s = splhigh();
+ bus_space_write_1(bspace, bhandle, CIO_CTRL, reg);
+ delay(1);
+ bus_space_write_1(bspace, bhandle, CIO_CTRL, val);
+ splx(s);
+}
+
+static inline uint8_t
+z8536_reg_get(bus_space_tag_t bspace, bus_space_handle_t bhandle, uint8_t reg)
+{
+ int s;
+ uint8_t val;
+
+ s = splhigh();
+ bus_space_write_1(bspace, bhandle, CIO_CTRL, reg);
+ delay(1);
+ val = bus_space_read_1(bspace, bhandle, CIO_CTRL);
+ splx(s);
+
+ return val;
+}
diff --git a/sys/arch/mac68k/nubus/cpi_nubusvar.h b/sys/arch/mac68k/nubus/cpi_nubusvar.h
new file mode 100644
index 00000000000..cb6670b7d79
--- /dev/null
+++ b/sys/arch/mac68k/nubus/cpi_nubusvar.h
@@ -0,0 +1,88 @@
+/* $NetBSD */
+
+/*-
+ * Copyright (c) 2008 Hauke Fath
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ */
+
+#ifndef CPI_NUBUSVAR_H
+#define CPI_NUBUSVAR_H
+
+/* Where we find the Z8536 CIO in Nubus slot space */
+#define CIO_BASE_OFFSET 0x060010
+
+/* Max. length of card name string */
+#define CPI_CARD_NAME_LEN 64
+
+/* The CIO lives on the top 8 bit of the 32 bit data bus. */
+enum cio_regs {
+ CIO_PORTC = 0x03,
+ CIO_PORTB = 0x07,
+ CIO_PORTA = 0x0b,
+ CIO_CTRL = 0x0f
+};
+
+#define CPI_UNIT(c) (minor(c) & 0x1f)
+
+enum lp_state {
+ LP_INITIAL = 0, /* device is closed */
+ LP_OPENING, /* device is about to be opened */
+ LP_OPEN, /* device is open */
+ LP_BUSY, /* busy with data output */
+ LP_ASLEEP, /* waiting for output completion */
+};
+
+/* Bit masks for Centronics status + handshake lines */
+enum hsk_lines {
+ CPI_RESET = 0x01, /* PB0 */
+ CPI_STROBE = 0x08, /* PC3 */
+ CPI_BUSY = 0x40, /* PC0 */
+ CPI_SELECT = 0x20, /* PB5 */
+ CPI_FAULT = 0x02, /* PB1 */
+ CPI_PAPER_EMPTY = 0x02, /* PC1 */
+ CPI_ACK = 0x04 /* PC2 */
+};
+
+struct cpi_softc {
+ struct device sc_dev;
+
+ nubus_slot sc_slot; /* Nubus slot number */
+ char cardname[CPI_CARD_NAME_LEN];
+
+ bus_addr_t sc_basepa; /* base physical address */
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+
+ ulong sc_intcount; /* Hard interrupts */
+ ulong sc_bytestoport; /* Bytes written to port */
+
+ struct callout sc_wakeupchan;
+
+#define CPI_BUFSIZE 0x0800
+ char *sc_printbuf; /* Driver's print buffer */
+ size_t sc_bufbytes; /* # of bytes in buffer */
+ u_char *sc_cp; /* Next byte to send */
+
+ u_char sc_lpstate;
+};
+
+#endif /* CPI_NUBUSVAR_H */
diff --git a/sys/arch/macppc/stand/ofwboot/Makefile b/sys/arch/macppc/stand/ofwboot/Makefile
index 33def8ab4e9..af49707b081 100644
--- a/sys/arch/macppc/stand/ofwboot/Makefile
+++ b/sys/arch/macppc/stand/ofwboot/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.45 2005/12/11 12:18:06 christos Exp $
+# $NetBSD: Makefile,v 1.46 2008/05/22 19:49:43 hauke Exp $
S= ${.CURDIR}/../../../..
@@ -34,7 +34,7 @@ BINMODE= 444
.if !defined(TOOL_MACPPCFIXCOFF)
TOOL_MACPPCFIXCOFFDIR!= cd ${.CURDIR}/../fixcoff && ${PRINTOBJDIR}
-TOOL_MACPPCFIXCOFF= ${FIXCOFFDIR}/fixcoff
+TOOL_MACPPCFIXCOFF= ${TOOL_MACPPCFIXCOFFDIR}/fixcoff
.endif
.endif
diff --git a/sys/arch/macppc/stand/ofwboot/ofdev.c b/sys/arch/macppc/stand/ofwboot/ofdev.c
index b6957cd3885..b0df2f4b868 100644
--- a/sys/arch/macppc/stand/ofwboot/ofdev.c
+++ b/sys/arch/macppc/stand/ofwboot/ofdev.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ofdev.c,v 1.19 2006/05/24 21:24:25 mrg Exp $ */
+/* $NetBSD: ofdev.c,v 1.20 2008/05/22 19:49:43 hauke Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -50,6 +50,7 @@
#include <lib/libsa/cd9660.h>
#include <lib/libsa/nfs.h>
#include <lib/libsa/ufs.h>
+#include <lib/libsa/lfs.h>
#include <lib/libsa/ustarfs.h>
#include "hfs.h"
@@ -157,13 +158,16 @@ static struct devsw of_devsw[1] = {
};
int ndevs = sizeof of_devsw / sizeof of_devsw[0];
-static struct fs_ops file_system_ufs = FS_OPS(ufs);
+static struct fs_ops file_system_ffsv1 = FS_OPS(ffsv1);
+static struct fs_ops file_system_ffsv2 = FS_OPS(ffsv2);
+static struct fs_ops file_system_lfsv1 = FS_OPS(lfsv1);
+static struct fs_ops file_system_lfsv2 = FS_OPS(lfsv2);
static struct fs_ops file_system_hfs = FS_OPS(hfs);
static struct fs_ops file_system_ustarfs = FS_OPS(ustarfs);
static struct fs_ops file_system_cd9660 = FS_OPS(cd9660);
static struct fs_ops file_system_nfs = FS_OPS(nfs);
-struct fs_ops file_system[4];
+struct fs_ops file_system[8];
int nfsys;
static struct of_dev ofdev = {
@@ -331,11 +335,14 @@ devopen(struct open_file *of, const char *name, char **file)
of->f_dev = of_devsw;
of->f_devdata = &ofdev;
- file_system[0] = file_system_ufs;
- file_system[1] = file_system_ustarfs;
- file_system[2] = file_system_cd9660;
- file_system[3] = file_system_hfs;
- nfsys = 4;
+ file_system[0] = file_system_ffsv1;
+ file_system[1] = file_system_ffsv2;
+ file_system[2] = file_system_lfsv1;
+ file_system[3] = file_system_lfsv2;
+ file_system[4] = file_system_ustarfs;
+ file_system[5] = file_system_cd9660;
+ file_system[6] = file_system_hfs;
+ nfsys = 7;
return 0;
}
if (!strcmp(buf, "network")) {
diff --git a/sys/dev/ic/z8536reg.h b/sys/dev/ic/z8536reg.h
new file mode 100644
index 00000000000..dd783aacb2f
--- /dev/null
+++ b/sys/dev/ic/z8536reg.h
@@ -0,0 +1,244 @@
+/* $NetBSD */
+
+/*-
+ * Copyright (c) 2008 Hauke Fath
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ */
+
+/*
+ * Zilog Z8536 CIO (Counter/Timer and Parallel I/O Unit)
+ * Register Definitions
+ *
+ * The CIO has four registers: One control register, and three data
+ * registers for ports A/B/C. To set up the CIO through the control
+ * register, first write the number of the internal register to it,
+ * then access or set the selected register contents. Once selected,
+ * an internal register can be polled continuously by reading out the
+ * control port.
+ *
+ * Internal registers are read-writable, except where noted.
+ */
+#define Z8536_IOSIZE 0x04
+
+#define Z8536_MICR 0x00 /* Master Interrupt Control Register */
+#define MICR_RESET 0x01 /* Chip Reset */
+#define MICR_RJA 0x02 /* Only z8036 (ZBUS version) */
+#define MICR_CTVIS 0x04 /* CT vector includes status */
+#define MICR_PBVIS 0x08 /* Port B vector includes status */
+#define MICR_PAVIS 0x10 /* Port A vector includes status */
+#define MICR_NV 0x20 /* No Vector (NV) */
+#define MICR_DLC 0x40 /* Disable Lower Chain (DLC) */
+#define MICR_MIE 0x80 /* Master Interrupt Enable (MIE) */
+
+#define Z8536_MCCR 0x01 /* Master Configuration Register */
+#define MCCR_CTINDPT 0x00 /* Counter/Timers Independent */
+#define MCCR_CT1GT2 0x01 /* CT 1 /OUTPUT gates CT 2 */
+#define MCCR_CT1TR2 0x02 /* CT 1 /OUTPUT triggers CT 2 */
+#define MCCR_CT1CT2 0x03 /* CT 1 /OUTPUT is CT 2's COUNT */
+#define MCCR_PAE 0x04 /* Port A Enable */
+#define MCCR_PLC 0x08 /* Port Link Control (A/B) */
+#define MCCR_PC_CT3E 0x10 /* Counter/Timer 3 + Port C Enable */
+#define MCCR_CT2E 0x20 /* Counter/Timer 2 Enable */
+#define MCCR_CT1E 0x40 /* Counter/Timer 1 Enable */
+#define MCCR_PBE 0x80 /* Port B Enable */
+
+/* Interrupt Vector Registers */
+#define Z8536_IVRA 0x02 /* Port A Interrupt Vector */
+#define Z8536_IVRB 0x03 /* Port B Interrupt Vector */
+#define Z8536_IVRCT 0x04 /* Counter/Timer Interrupt Vector */
+
+/* Port C setup */
+#define Z8536_DPPRC 0x05 /* Port C Data Path Polarity */
+#define Z8536_DDRC 0x06 /* Port C Data Direction */
+#define Z8536_SIOCRC 0x07 /* Port C Special I/O Control */
+
+#define Z8536_PCSRA 0x08 /* Port A Command and Status */
+#define Z8536_PCSRB 0x09 /* Port B Command and Status */
+
+/* Z8536_PCSRA + Z8536_PCSRB command and status bits */
+#define PCSR_IOE 0x01 /* Interrupt on error */
+#define PCSR_PMF 0x02 /* Pattern match flag (RO) */
+#define PCSR_IRF 0x04 /* Input register full (RO) */
+#define PCSR_ORE 0x08 /* Output register empty (RO) */
+#define PCSR_ERR 0x10 /* Interrupt error */
+#define PCSR_IP 0x20 /* Interrupt pending */
+#define PCSR_IE 0x40 /* Interrupt enable */
+#define PCSR_IUS 0x80 /* Interrupt under service */
+/* PCSR{A,B} interrupt bits: IUS/IE/IP */
+#define PCSR_NULL 0x00 /* Null Code */
+#define PCSR_CLR_IP_IUS 0x20 /* Clear IP and IUS */
+#define PCSR_SET_IUS 0x40 /* Set Interrupt Under Service */
+#define PCSR_CLR_IUS 0x60 /* Clear Interrupt Under Service */
+#define PCSR_SET_IP 0x80 /* Set Interrupt Pending */
+#define PCSR_CLR_IP 0xA0 /* Clear Interrupt Pending */
+#define PCSR_SET_IE 0xC0 /* Set Interrupt Enable */
+#define PCSR_CLR_IE 0xE0 /* Clear Interrupt Enable */
+
+/* Counter/Timer 1..3 Command and Status Registers */
+#define Z8536_CTCSR1 0x0A /* CT 1 Command and Status */
+#define Z8536_CTCSR2 0x0B /* CT 2 Command and Status */
+#define Z8536_CTCSR3 0x0C /* CT 3 Command and Status */
+
+/* CTCSR setup bits */
+#define CTCS_CIP 0x01 /* Count in Progress (RO) */
+#define CTCS_TCB 0x02 /* Trigger Command Bit (WO) */
+#define CTCS_GCB 0x04 /* Gate Command Bit */
+#define CTCS_RCC 0x08 /* Read Counter Control */
+#define CTCS_ERR 0x10 /* Interrupt Error (RO) */
+#define CTCS_IP 0x20 /* Interrupt Pending */
+#define CTCS_IE 0x40 /* Interrupt Enable */
+#define CTCS_IUS 0x80 /* Interrupt Under Service */
+
+/* CTCSR interrupt bits: IUS/IE/IP */
+#define CTCS_NULL 0x00 /* Null Code */
+#define CTCS_CLR_IP_IUS 0x20 /* Clear IP and IUS */
+#define CTCS_SET_IUS 0x40 /* Set Interrupt Under Service */
+#define CTCS_CLR_IUS 0x60 /* Clear Interrupt Under Service */
+#define CTCS_SET_IP 0x80 /* Set Interrupt Pending */
+#define CTCS_CLR_IP 0xA0 /* Clear Interrupt Pending */
+#define CTCS_SET_IE 0xC0 /* Set Interrupt Enable */
+#define CTCS_CLR_IE 0xE0 /* Clear Interrupt Enable */
+
+/* The port data registers are directly accessible at their own IO address */
+#define Z8536_PDRA 0x0D /* Port A Data Register */
+#define Z8536_PDRB 0x0E /* Port B Data Register */
+#define Z8536_PDRC 0x0F /* Port C Data Register */
+
+/* Bytewise access to current count registers (read-only) */
+#define Z8536_CTCCR1_MSB 0x10 /* CT 1 Current Count MSB */
+#define Z8536_CTCCR1_LSB 0x11 /* CT 1 Current Count LSB */
+#define Z8536_CTCCR2_MSB 0x12 /* CT 2 Current Count MSB */
+#define Z8536_CTCCR2_LSB 0x13 /* CT 2 Current Count LSB */
+#define Z8536_CTCCR3_MSB 0x14 /* CT 3 Current Count MSB */
+#define Z8536_CTCCR3_LSB 0x15 /* CT 3 Current Count LSB */
+
+/* Bytewise access to time constant registers */
+#define Z8536_CTTCR1_MSB 0x16 /* CT 1 Time Constant MSB */
+#define Z8536_CTTCR1_LSB 0x17 /* CT 1 Time Constant LSB */
+#define Z8536_CTTCR2_MSB 0x18 /* CT 2 Time Constant MSB */
+#define Z8536_CTTCR2_LSB 0x19 /* CT 2 Time Constant LSB */
+#define Z8536_CTTCR3_MSB 0x1A /* CT 3 Time Constant MSB */
+#define Z8536_CTTCR3_LSB 0x1B /* CT 3 Time Constant LSB */
+
+/* Counter/Timer Mode specification */
+#define Z8536_CTMSR1 0x1C /* CT 1 Mode Specification */
+#define Z8536_CTMSR2 0x1D /* CT 2 Mode Specification */
+#define Z8536_CTMSR3 0x1E /* CT 3 Mode Specification */
+#define CTMS_DCS_PULSE 0x00 /* Pulse Output */
+#define CTMS_DCS_ONESHOT 0x01 /* One-Shot Output */
+#define CTMS_DCS_SQUARE 0x02 /* Square Wave Output */
+#define CTMS_REB 0x04 /* Retrigger Enable */
+#define CTMS_EGE 0x08 /* External Gate Enable */
+#define CTMS_ETE 0x10 /* External Trigger Enable */
+#define CTMS_ECE 0x20 /* External Count Enable */
+#define CTMS_EOE 0x40 /* External Output Enable */
+#define CTMS_CSC 0x80 /* Continuous / Single Cycle */
+
+#define Z8536_CVR 0x1F /* Current Interrupt Vector (RO) */
+
+/* Port A specification registers */
+#define Z8536_PMSRA 0x20 /* Port A Mode Specification */
+#define Z8536_PHSRA 0x21 /* Port A Handshake Specification */
+#define Z8536_DPPRA 0x22 /* Port A Data Path Polarity */
+#define Z8536_DDRA 0x23 /* Port A Data Direction */
+#define Z8536_SIOCRA 0x24 /* Port A Special I/O Control */
+#define Z8536_PPRA 0x25 /* Port A Pattern Polarity */
+#define Z8536_PTRA 0x26 /* Port A Pattern Transition */
+#define Z8536_PMRA 0x27 /* Port A Pattern Mask */
+
+/* Port B specification registers */
+#define Z8536_PMSRB 0x28 /* Port B Mode Specification */
+#define Z8536_PHSRB 0x29 /* Port B Handshake Specification */
+#define Z8536_DPPRB 0x2A /* Port B Data Path Polarity */
+#define Z8536_DDRB 0x2B /* Port B Data Direction */
+#define Z8536_SIOCRB 0x2C /* Port B Special I/O Control */
+#define Z8536_PPRB 0x2D /* Port B Pattern Polarity */
+#define Z8536_PTRB 0x2E /* Port B Pattern Transition */
+#define Z8536_PMRB 0x2F /* Port B Pattern Mask */
+
+/* Bit definitions, common to ports A and B */
+
+/* Z8536_PMSRA + Z8536_PMSRB port mode specification bits */
+#define PMSR_LPM 0x01 /* Bit mode: latched */
+#define PMSR_DTE 0x01 /* Hsk mode: deskew timer enable */
+/*
+ * PMS1 PMS0 Pattern mode specification
+ * 0 0 disable pattern match
+ * 0 1 "and" mode, transition-triggered interrupt
+ * 1 0 "or" mode, transition-triggered interrupt
+ * 1 1 "or-priority encoded vector" mode, level-
+ * triggered interrupt (only transparent LPM mode)
+ */
+#define PMSR_PMS0 0x02
+#define PMSR_PMS1 0x04
+#define PMSR_PMS_OFF 0x00 /* Disable pattern match */
+#define PMSR_PMS_AND 0x02 /* "and" mode, transition-triggered */
+#define PMSR_PMS_OR 0x04 /* "or" mode, transition-triggered */
+/*
+ * "or-priority encoded vector" mode, level-triggered interrupt
+ * (only in transparent LPM mode)
+ */
+#define PMSR_PMS_OR_PEV 0x06
+#define PMSR_IMO 0x08 /* Interrupt on match only */
+#define PMSR_SB 0x10 /* Single buffered mode */
+#define PMSR_ITB 0x20 /* Interrupt on two bytes */
+/*
+ * PTS1 PTS0 Port type selects
+ * 0 0 bit port
+ * 0 1 input port
+ * 1 0 output port
+ * 1 1 bidirectional port
+ */
+#define PMSR_PTS0 0x40
+#define PMSR_PTS1 0x80
+#define PMSR_PTS_BIT 0x00
+#define PMSR_PTS_IN 0x40
+#define PMSR_PTS_OUT 0x80
+#define PMSR_PTS_BIDI 0xC0
+/*
+ * Z8536_PHSRA + Z8536_PHSRB port handshake specification bits
+ * Bits 0-2 set deskew timer for output ports
+ *
+ * RWS2 RWS1 RWS0 Status signals on port C
+ * 0 0 0 REQUEST/-WAIT disabled
+ * 0 0 1 output -WAIT
+ * 0 1 1 input -WAIT
+ * 1 0 0 special REQUEST
+ * 1 0 1 output REQUEST
+ * 1 1 1 input REQUEST
+ */
+#define PHSR_RWS0 0x08
+#define PHSR_RWS1 0x10
+#define PHSR_RWS2 0x20
+/*
+ * HTS1 HTS0 Handshake type specification
+ * 0 0 interlocked handshake
+ * 0 1 strobed handshake
+ * 1 0 pulsed handshake
+ * 1 1 three-wire-handshake
+ */
+#define PHSR_HTS0 0x40
+#define PHSR_HTS1 0x80
+#define PHSR_HTS_INT 0x00
+#define PHSR_HTS_STR 0x40
+#define PHSR_HTS_PUL 0x80
+#define PHSR_HTS_TWI 0xC0