Module Name:    src
Committed By:   hauke
Date:           Tue Jan 31 22:13:20 UTC 2012

Modified Files:
        src/sys/arch/mac68k/conf: GENERIC
        src/sys/arch/mac68k/nubus: cpi_nubus.c cpi_nubusvar.h
        src/sys/dev/ic: z8536reg.h

Log Message:
Employ the two free 16 bit timers of the Hurdler Centronics Parallel
Interface card's Z8536 CIO for Timecounter support.

Builds, should work, but not testable yet because of pmap breakage.


To generate a diff of this commit:
cvs rdiff -u -r1.204 -r1.205 src/sys/arch/mac68k/conf/GENERIC
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/mac68k/nubus/cpi_nubus.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/mac68k/nubus/cpi_nubusvar.h
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/ic/z8536reg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/mac68k/conf/GENERIC
diff -u src/sys/arch/mac68k/conf/GENERIC:1.204 src/sys/arch/mac68k/conf/GENERIC:1.205
--- src/sys/arch/mac68k/conf/GENERIC:1.204	Sun Dec 18 05:49:29 2011
+++ src/sys/arch/mac68k/conf/GENERIC	Tue Jan 31 22:13:20 2012
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.204 2011/12/18 05:49:29 dholland Exp $
+# $NetBSD: GENERIC,v 1.205 2012/01/31 22:13:20 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.204 $"
+#ident 		"GENERIC-$Revision: 1.205 $"
 
 maxusers	16		# estimated number of users
 
@@ -234,7 +234,8 @@ wsmouse* at ams?
 # Centronics printer port
 
 # CSI Hurdler Centronics Parallel Interface
-cpi*	at nubus?
+# CPI_CTC12_IS_TIMECOUNTER	0x01	Run counters 1+2 as timecounter	
+cpi*	at nubus? flags 0x1
 
 
 # Serial Devices

Index: src/sys/arch/mac68k/nubus/cpi_nubus.c
diff -u src/sys/arch/mac68k/nubus/cpi_nubus.c:1.5 src/sys/arch/mac68k/nubus/cpi_nubus.c:1.6
--- src/sys/arch/mac68k/nubus/cpi_nubus.c:1.5	Fri May 13 22:35:50 2011
+++ src/sys/arch/mac68k/nubus/cpi_nubus.c	Tue Jan 31 22:13:20 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpi_nubus.c,v 1.5 2011/05/13 22:35:50 rmind Exp $	*/
+/*	$NetBSD: cpi_nubus.c,v 1.6 2012/01/31 22:13:20 hauke Exp $	*/
 
 /*-
  * Copyright (c) 2008 Hauke Fath
@@ -25,8 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpi_nubus.c,v 1.5 2011/05/13 22:35:50 rmind Exp $");
-
+__KERNEL_RCSID(0, "$NetBSD: cpi_nubus.c,v 1.6 2012/01/31 22:13:20 hauke Exp $");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
@@ -40,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: cpi_nubus.c,
 #include <sys/ioctl.h>
 #include <sys/tty.h>
 #include <sys/time.h>
+#include <sys/timetc.h>
 #include <sys/kernel.h>
 #include <sys/syslog.h>
 #include <sys/errno.h>
@@ -71,6 +71,7 @@ __KERNEL_RCSID(0, "$NetBSD: cpi_nubus.c,
 #define M_TRACE_WRITE	0x0010
 #define M_TRACE_IOCTL	0x0020
 #define M_TRACE_STATUS	0x0040
+#define M_TRACE_TCNTR	0x0080
 #define M_TRACE_ALL	0xFFFF
 #define M_TRACE_NONE	0x0000
 
@@ -81,12 +82,12 @@ __KERNEL_RCSID(0, "$NetBSD: cpi_nubus.c,
 #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_TCNTR	(cpi_debug_mask & M_TRACE_TCNTR)
 #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
+uint32_t cpi_debug_mask = M_TRACE_NONE /* | M_TRACE_TCNTR | M_TRACE_WRITE */ ;
+#else /* CPI_DEBUG */
 #define TRACE_CONFIG	0
 #define TRACE_OPEN	0
 #define TRACE_CLOSE	0
@@ -94,11 +95,10 @@ uint32_t cpi_debug_mask = M_TRACE_NONE /
 #define TRACE_WRITE	0
 #define TRACE_IOCTL	0
 #define TRACE_STATUS	0
+#define TRACE_TCNTR	0
 #define TRACE_ALL	0
 #define TRACE_NONE	0
-#endif
-
-#undef USE_CIO_TIMERS		/* TBD */
+#endif /* CPI_DEBUG */
 
 /* autoconf interface */
 int cpi_nubus_match(device_t, cfdata_t, void *);
@@ -126,14 +126,13 @@ 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,
+static void cpi_tc_initclock(struct cpi_softc *);
+static uint cpi_get_timecount(struct timecounter *);
+static uint z8536_read_counter1(bus_space_tag_t, bus_space_handle_t);
+static uint z8536_read_counter2(bus_space_tag_t, bus_space_handle_t);
+static 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,
+static uint8_t z8536_reg_get(bus_space_tag_t, bus_space_handle_t,
     uint8_t);
 
 
@@ -191,19 +190,6 @@ const uint8_t cio_init[] = {
 	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.
 	 *
@@ -215,18 +201,19 @@ const uint8_t cio_init[] = {
 	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,
+	/* Enable ports A+B+C+CT3 */
+	Z8536_MCCR,	MCCR_PAE | MCCR_PBE | MCCR_PC_CT3E,
+	
 	/* Master Interrupt Enable, Disable Lower Chain,
-	 * No Vector, port A+B+CT vectors include status */
+	 * No Interrupt 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 */
 };
 
+/* CPI default options */
+/* int	cpi_options = 0 | CPI_CTC12_IS_TIMECOUNTER; */
+
 
 /* 
  * Look for Creative Systems Inc. "Hurdler Centronics Parallel Interface"
@@ -254,13 +241,15 @@ cpi_nubus_attach(device_t parent, device
 	int err, ii;
 
 	sc = device_private(self);
+	sc->sc_options = (device_cfdata(self)->cf_flags & CPI_OPTIONS_MASK);
+
 	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
+	 * The CIO sits eight bit wide on the top byte lane of
 	 * Nubus, so map 16 byte.
 	 */
 	if (TRACE_CONFIG) {
@@ -287,7 +276,7 @@ cpi_nubus_attach(device_t parent, device
 		z8536_reg_set(sc->sc_bst, sc->sc_bsh, cio_reset[ii],
 		    cio_reset[ii + 1]);
 	
-	delay(1000);		/* Just in case */
+	delay(1000);		/* Give the CIO time to set itself up */
 	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]);
@@ -296,16 +285,13 @@ cpi_nubus_attach(device_t parent, device
 	if (TRACE_CONFIG)
 		printf("\tcpi_nubus_attach() done with 8536 CIO setup.\n");
 		
-	/* XXX Get the information strings from the card's ROM */
+	/* XXX Get information strings from the card 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 */
+	/* Attach CIO timers 1+2 as timecounter */
+	if (sc->sc_options & CPI_CTC12_IS_TIMECOUNTER) {
+		cpi_tc_initclock(sc);
+	}
 
 	callout_init(&sc->sc_wakeupchan, 0);	/* XXX */
 	
@@ -557,27 +543,12 @@ 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 */
 }
 
 
@@ -650,88 +621,245 @@ cpi_intr(void *arg)
 		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)
+cpi_tc_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
-	};
-
+	uint8_t reg;
+	
 	/*
-	 * Set up timers A and B as a single, free-running 32 bit counter
+	 * Set up c/t 1 and 2 as a single, free-running 32 bit counter
 	 */
 
-	/* Disable counters A and B */
+	/* Disable counters 1 and 2 */
 	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);
+	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_CTMSR1,
+	    CTMS_CSC | CTMS_DCS_PULSE);
 	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_CTMSR2,
+	    CTMS_CSC | CTMS_DCS_PULSE);
 	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 */
+	/* Link counters 1 and 2 */
+	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_CT1CT2);
+
+	/* Enable and counter pair */
 	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);
+	    reg | (MCCR_CT1E | MCCR_CT2E));
 
-	/* Start counters A and B */
+	/* Start c/t 1; c/t 2 gets started by c/t 1 pulse */
 	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);
+	    CTCSR_MASK(reg | CTCS_TCB | CTCS_GCB));
+
+	if (TRACE_TCNTR) {
+		printf("Before tc_init():\n");
+		reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1);
+		printf("Counter 1 CTCSR setup bits are 0x%03x\n", reg);
+		printf("Counter 1 (LSW) is now 0x%05x\n",
+		    z8536_read_counter1(sc->sc_bst, sc->sc_bsh));
+		reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2);
+		printf("Counter 2 CTCSR setup bits are 0x%03x\n", reg);
+		printf("Counter 2 (MSW) is now 0x%05x\n",
+		    z8536_read_counter2(sc->sc_bst, sc->sc_bsh));
+
+		delay(1000);
+	}
 	
-	tc_init(&cpi_timecounter);
+	sc->sc_timecounter.tc_get_timecount = cpi_get_timecount;
+	sc->sc_timecounter.tc_poll_pps      = 0;
+	sc->sc_timecounter.tc_counter_mask  = ~0u;
+	sc->sc_timecounter.tc_frequency     = CPI_CLK_FREQ;
+	sc->sc_timecounter.tc_name          = "Nubus CPI";
+	sc->sc_timecounter.tc_quality       = 1000;
+	/*
+	 * Squirrel away the device's sc so we can talk
+	 * to the CIO later
+	 */
+	sc->sc_timecounter.tc_priv          = sc;
+	sc->sc_timecounter.tc_next          = NULL;
+        
+        tc_init(&(sc->sc_timecounter));
+	
+	if (TRACE_TCNTR) {
+		delay(1000);
+
+		printf("After tc_init():\n");
+		reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR1);
+		printf("Counter 1 CTCSR setup bits are 0x%03x\n", reg);
+		printf("Counter 1 (LSW) is now 0x%05x\n",
+		    z8536_read_counter1(sc->sc_bst, sc->sc_bsh));
+		reg = z8536_reg_get(sc->sc_bst, sc->sc_bsh, Z8536_CTCSR2);
+		printf("Counter 2 CTCSR setup bits are 0x%03x\n", reg);
+		printf("Counter 2 (MSW) is now 0x%05x\n",
+		    z8536_read_counter2(sc->sc_bst, sc->sc_bsh));
+	}
 }
 
 static u_int
 cpi_get_timecount(struct timecounter *tc)
 {
-	uint8_t high, high2, low;
-	int s;
-
-	/*
-	 * Make the timer access atomic
+        int s;
+	uint msw, msw2, lsw;
+	uint8_t reg;
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+	
+	bst = ((struct cpi_softc *)tc->tc_priv)->sc_bst;
+	bsh = ((struct cpi_softc *)tc->tc_priv)->sc_bsh;
+	/*
+	 * We run CIO counters 1 and 2 in an internally coupled mode,
+	 * where the output of counter 1 (LSW) clocks counter 2 (MSW).
+	 * The counters are buffered, and the buffers have to be
+	 * locked before we can read out a consistent counter
+	 * value. Reading the LSB releases the buffer lock.
+	 *
+	 * Unfortunately, there is no such mechanism between MSW and
+	 * LSW of the coupled counter. To ensure a consistent
+	 * read-out, we read the MSW, then the LSW, then re-read the
+	 * MSW and compare with the old value. If we find that the MSW
+	 * has just been incremented, we re-read the LSW. This avoids
+	 * a race that could leave us with a new (just wrapped) LSW
+	 * and an old MSW value.
 	 *
-	 * XXX How expensive is this? And is it really necessary?
+	 * For simplicity, we roll the procedure into a loop - the
+	 * rollover case is rare.
 	 */
-	s = splhigh();
+	do {
+		
+#define delay(a)
+		
+		/* Guard HW timer access */
+		s = splhigh();
 
-	/* TBD */
+		/* Lock counter 2 latch in preparation for read-out */
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
+		delay(1);
+		reg = bus_space_read_1(bst, bsh, CIO_CTRL);
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
+		bus_space_write_1(bst, bsh, CIO_CTRL, CTCSR_MASK(reg | CTCS_RCC));
+		
+		/* Read out counter 2 MSB,then LSB (releasing the latch) */
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_MSB);
+		delay(1);
+		msw = bus_space_read_1(bst, bsh, CIO_CTRL) << 8;
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_LSB);
+		delay(1);
+		msw |= bus_space_read_1(bst, bsh, CIO_CTRL);
+		
+		/* Lock counter 1 latch in preparation for read-out */
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR1);
+		delay(1);
+		reg = bus_space_read_1(bst, bsh, CIO_CTRL);
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR1);
+		bus_space_write_1(bst, bsh, CIO_CTRL, CTCSR_MASK(reg |CTCS_RCC));
+		
+		/* Read out counter 1 MSB,then LSB (releasing the latch) */
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR1_MSB);
+		delay(1);
+		lsw = bus_space_read_1(bst, bsh, CIO_CTRL) << 8;
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR1_LSB);
+		delay(1);
+		lsw |= bus_space_read_1(bst, bsh, CIO_CTRL);
+		
+		/* Lock counter 2 latch in preparation for read-out */
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
+		delay(1);
+		reg = bus_space_read_1(bst, bsh, CIO_CTRL);
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
+		bus_space_write_1(bst, bsh, CIO_CTRL, CTCSR_MASK(reg | CTCS_RCC));
+		
+		/* Read out counter 2 MSB,then LSB (releasing the latch) */
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_MSB);
+		delay(1);
+		msw2 = bus_space_read_1(bst, bsh, CIO_CTRL) << 8;
+		bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_LSB);
+		delay(1);
+		msw2 |= bus_space_read_1(bst, bsh, CIO_CTRL);
+		
+		splx(s);
 
-}
-#endif /* USE_CIO_TIMERS */
+	} while (msw2 != msw);
 
+	/* timecounter expects an upward counter */
+	return ~0u - ((msw << 16) | lsw);
+}
 
 /*
- * Z8536 CIO nuts and bolts
+ * Z8536 CIO convenience atomic register getter/setter
  */
 
-static inline void
+static uint
+z8536_read_counter1(bus_space_tag_t bst, bus_space_handle_t bsh)
+{
+	uint8_t reg;
+	uint32_t lsw;
+	int s;
+
+	s = splhigh();
+	
+	/* Lock counter 1 latch in preparation for read-out */
+	bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR1);
+	delay(1);
+	reg = bus_space_read_1(bst, bsh, CIO_CTRL);
+	bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR1);
+	bus_space_write_1(bst, bsh, CIO_CTRL, CTCSR_MASK(reg | CTCS_RCC));
+		
+	/* Read out counter 1 MSB,then LSB (releasing the latch) */
+	bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR1_MSB);
+	delay(1);
+	lsw = bus_space_read_1(bst, bsh, CIO_CTRL) << 8;
+	bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR1_LSB);
+	delay(1);
+	lsw |= bus_space_read_1(bst, bsh, CIO_CTRL);
+
+	splx(s);
+
+	return lsw;
+}
+
+static uint
+z8536_read_counter2(bus_space_tag_t bst, bus_space_handle_t bsh)
+{
+	uint8_t reg;
+	uint32_t msw;
+	int s;
+
+	s = splhigh();
+
+	/* Lock counter 2 latch in preparation for read-out */
+	bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
+	delay(1);
+	reg = bus_space_read_1(bst, bsh, CIO_CTRL);
+	bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCSR2);
+	bus_space_write_1(bst, bsh, CIO_CTRL, CTCSR_MASK(reg | CTCS_RCC));
+
+	/* Read out counter 2 MSB,then LSB (releasing the latch) */
+	bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_MSB);
+	delay(1);
+	msw = bus_space_read_1(bst, bsh, CIO_CTRL) << 8;
+	bus_space_write_1(bst, bsh, CIO_CTRL, Z8536_CTCCR2_LSB);
+	delay(1);
+	msw |= bus_space_read_1(bst, bsh, CIO_CTRL);
+
+	splx(s);
+
+	return msw;
+}
+
+static void
 z8536_reg_set(bus_space_tag_t bspace, bus_space_handle_t bhandle,
     uint8_t reg, uint8_t val)
 {
@@ -744,7 +872,7 @@ z8536_reg_set(bus_space_tag_t bspace, bu
 	splx(s);
 }
 
-static inline uint8_t
+static uint8_t
 z8536_reg_get(bus_space_tag_t bspace, bus_space_handle_t bhandle, uint8_t reg)
 {
 	int s;

Index: src/sys/arch/mac68k/nubus/cpi_nubusvar.h
diff -u src/sys/arch/mac68k/nubus/cpi_nubusvar.h:1.2 src/sys/arch/mac68k/nubus/cpi_nubusvar.h:1.3
--- src/sys/arch/mac68k/nubus/cpi_nubusvar.h:1.2	Fri May 23 10:46:10 2008
+++ src/sys/arch/mac68k/nubus/cpi_nubusvar.h	Tue Jan 31 22:13:20 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpi_nubusvar.h,v 1.2 2008/05/23 10:46:10 hauke Exp $	*/
+/*	$NetBSD: cpi_nubusvar.h,v 1.3 2012/01/31 22:13:20 hauke Exp $	*/
 
 /*-
  * Copyright (c) 2008 Hauke Fath
@@ -62,11 +62,24 @@ enum hsk_lines {
 	CPI_ACK = 0x04		/* PC2 */
 };
 
+/*
+ * The CPI board glue logic divides the 10 MHz Nubus clock by 2, and
+ * feeds it to the 8536 CIO (pin 16). The CIO divides the PCLK clock
+ * by 2 internally before providing it to its counters.
+ */
+#define CPI_CLK_FREQ (10000000 / 4)
+
+/* CPI configuration options - we might grow more */
+enum cpi_cf_flags {
+	CPI_CTC12_IS_TIMECOUNTER = 0x01
+};
+#define CPI_OPTIONS_MASK	(CPI_CTC12_IS_TIMECOUNTER)
+
 struct cpi_softc {
         struct device  		sc_dev;
 
 	nubus_slot		sc_slot;	/* Nubus slot number */
-	char			cardname[CPI_CARD_NAME_LEN];
+	char			sc_cardname[CPI_CARD_NAME_LEN];
 
 	bus_addr_t		sc_basepa;	/* base physical address */
 	bus_space_tag_t		sc_bst;
@@ -83,6 +96,10 @@ struct cpi_softc {
         u_char          	*sc_cp;		/* Next byte to send */
 	
         u_char          	sc_lpstate;
+
+	ulong			sc_options;
+	
+	struct timecounter	sc_timecounter;
 };
 
 #endif /* CPI_NUBUSVAR_H */

Index: src/sys/dev/ic/z8536reg.h
diff -u src/sys/dev/ic/z8536reg.h:1.2 src/sys/dev/ic/z8536reg.h:1.3
--- src/sys/dev/ic/z8536reg.h:1.2	Fri May 23 10:46:53 2008
+++ src/sys/dev/ic/z8536reg.h	Tue Jan 31 22:13:19 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: z8536reg.h,v 1.2 2008/05/23 10:46:53 hauke Exp $	*/
+/*	$NetBSD: z8536reg.h,v 1.3 2012/01/31 22:13:19 hauke Exp $	*/
 
 /*-
  * Copyright (c) 2008 Hauke Fath
@@ -118,6 +118,9 @@
 #define       CTCS_SET_IE	0xC0  	/* Set Interrupt Enable */
 #define       CTCS_CLR_IE	0xE0  	/* Clear Interrupt Enable */
 
+/* Avoid changing intr bits unintendedly */
+#define	CTCSR_MASK(FLAGS)	((FLAGS) & 0x3f)
+
 /* 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 */

Reply via email to