Subject: cleanup todclock attachments (Re: CVS commit: src/sys/arch/sparc64)
To: None <mrg@eterna.com.au>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-sparc64
Date: 10/09/2006 15:18:16
In article <24097.1160369130@splode.eterna.com.au> on source-changes
mrg@eterna.com.au wrote:

>    > Modified Files:
>    > 	src/sys/arch/sparc64/conf: files.sparc64
>    > 	src/sys/arch/sparc64/sparc64: clock.c
>    > Added Files:
>    > 	src/sys/arch/sparc64/dev: rtc.c
>    > 
>    > Log Message:
>    > avoid bringing in mc146818 routines for kernels that do not have the
>    > 'rtc'-style clock linked in.  put the rtc code in it's own file and
>    > only link it in if it is actually configured.  fixes PR#23342.
>    
>    Is there further plan to separate mk48txx RTC stuff from clock.c
>    into dev/mkclock.c (or so) because clock and timer are independent?
>    (mcclock.c is better than rtc.c in that case?)
> 
> 
> sounds like an idea worth investigating.. i'm not attached to
> filenames, just that (a) the PR is closed and (b) my non-rtc
> using kernels are smaller now.

How about the attached patch?

I'm not sure it's worth to rename existing clock devices,
but this also makes kenrels smaller if you don't need the
Mostek TOD clock (for Netra etc).

(BTW I wonder if we need eeprom at sbus and clock at mainbus stuff)
---
Izumi Tsutsui


Index: conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/conf/GENERIC,v
retrieving revision 1.70
diff -u -r1.70 GENERIC
--- conf/GENERIC	6 Oct 2006 08:44:59 -0000	1.70
+++ conf/GENERIC	9 Oct 2006 06:11:24 -0000
@@ -260,11 +260,13 @@
 bpp*	at sbus? slot ? offset ?		# parallel port
 lpt*	at ebus?				# parallel port
 
-## Mostek clock found on 4/300, sun4c, sun4m and sun4u systems.
-## The Mostek clock NVRAM is the "eeprom" on sun4/300 systems.
-clock*	at sbus? slot ? offset ?
-clock*	at ebus?
-rtc*	at ebus?
+## Mostek clock found on sbus on Ultra-1,2 systems
+## and found on ebus on Ultra-5 and other systems.
+mkclock*	at sbus? slot ? offset ?
+mkclock*	at ebus?
+
+## DS1287 compatible clock found on ebus on Netra X1 and other systems.
+mcclock*	at ebus?
 
 ## Timer chip found on 4/300, sun4c, sun4m and (some) sun4u systems.
 timer*	at mainbus0				# sun4c
Index: conf/files.sparc64
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/conf/files.sparc64,v
retrieving revision 1.105
diff -u -r1.105 files.sparc64
--- conf/files.sparc64	9 Oct 2006 03:34:56 -0000	1.105
+++ conf/files.sparc64	9 Oct 2006 06:11:24 -0000
@@ -40,13 +40,14 @@
 attach ebus at pci
 file	arch/sparc64/dev/ebus.c			ebus
 
-device clock: mk48txx
-attach clock at mainbus, sbus with clock_sbus
-attach clock at ebus with clock_ebus
-
-device rtc: mc146818
-attach rtc at ebus with rtc_ebus
-file	arch/sparc64/dev/rtc.c			rtc
+device mkclock: mk48txx
+attach mkclock at sbus with mkclock_sbus
+attach mkclock at ebus with mkclock_ebus
+file	arch/sparc64/dev/mkclock.c		mkclock
+
+device mcclock: mc146818
+attach mcclock at ebus with mcclock_ebus
+file	arch/sparc64/dev/mcclock.c		mcclock
 
 device psm: sysmon_envsys, sysmon_power
 attach psm at ebus
@@ -55,10 +56,6 @@
 device timer
 attach timer at mainbus, sbus
 
-device eeprom
-attach eeprom at sbus, ebus
-file	arch/sparc64/sparc64/clock.c
-
 device power
 attach power at sbus, ebus
 file	arch/sparc64/dev/power.c		power
@@ -173,6 +170,7 @@
 
 file	arch/sparc/sparc/promlib.c
 file	arch/sparc64/sparc64/autoconf.c
+file	arch/sparc64/sparc64/clock.c
 file	arch/sparc64/sparc64/emul.c
 file	arch/sparc64/sparc64/in_cksum.S
 file	arch/sparc64/sparc64/in4_cksum.c	inet
Index: sparc64/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/clock.c,v
retrieving revision 1.81
diff -u -r1.81 clock.c
--- sparc64/clock.c	9 Oct 2006 03:34:56 -0000	1.81
+++ sparc64/clock.c	9 Oct 2006 06:11:25 -0000
@@ -87,10 +87,6 @@
 #include <machine/cpu.h>
 #include <machine/cpu_counter.h>
 
-#include <dev/clock_subr.h>
-#include <dev/ic/mk48txxreg.h>
-#include <dev/ic/mk48txxvar.h>
-
 #include <sparc64/sparc64/intreg.h>
 #include <sparc64/sparc64/timerreg.h>
 #include <sparc64/dev/iommureg.h>
@@ -121,24 +117,6 @@
 static struct intrhand level14 = { statintr };
 static struct intrhand schedint = { schedintr };
 
-/*
- * clock (eeprom) attaches at the sbus or the ebus (PCI)
- */
-static int	clockmatch_sbus(struct device *, struct cfdata *, void *);
-static void	clockattach_sbus(struct device *, struct device *, void *);
-static int	clockmatch_ebus(struct device *, struct cfdata *, void *);
-static void	clockattach_ebus(struct device *, struct device *, void *);
-static void	clockattach(struct mk48txx_softc *, int);
-
-
-CFATTACH_DECL(clock_sbus, sizeof(struct mk48txx_softc),
-    clockmatch_sbus, clockattach_sbus, NULL, NULL);
-
-CFATTACH_DECL(clock_ebus, sizeof(struct mk48txx_softc),
-    clockmatch_ebus, clockattach_ebus, NULL, NULL);
-
-extern struct cfdriver clock_cd;
-
 static int	timermatch(struct device *, struct cfdata *, void *);
 static void	timerattach(struct device *, struct device *, void *);
 
@@ -147,166 +125,11 @@
 CFATTACH_DECL(timer, sizeof(struct device),
     timermatch, timerattach, NULL, NULL);
 
-int clock_wenable(struct todr_chip_handle *, int);
 struct chiptime;
 void stopcounter(struct timer_4u *);
 
 int timerblurb = 10; /* Guess a value; used before clock is attached */
 
-/*
- * The OPENPROM calls the clock the "eeprom", so we have to have our
- * own special match function to call it the "clock".
- */
-static int
-clockmatch_sbus(struct device *parent, struct cfdata *cf, void *aux)
-{
-	struct sbus_attach_args *sa = aux;
-
-	return (strcmp("eeprom", sa->sa_name) == 0);
-}
-
-static int
-clockmatch_ebus(struct device *parent, struct cfdata *cf, void *aux)
-{
-	struct ebus_attach_args *ea = aux;
-
-	return (strcmp("eeprom", ea->ea_name) == 0);
-}
-
-/*
- * Attach a clock (really `eeprom') to the sbus or ebus.
- *
- * We ignore any existing virtual address as we need to map
- * this read-only and make it read-write only temporarily,
- * whenever we read or write the clock chip.  The clock also
- * contains the ID ``PROM'', and I have already had the pleasure
- * of reloading the CPU type, Ethernet address, etc, by hand from
- * the console FORTH interpreter.  I intend not to enjoy it again.
- *
- * the MK48T02 is 2K.  the MK48T08 is 8K, and the MK48T59 is
- * supposed to be identical to it.
- *
- * This is *UGLY*!  We probably have multiple mappings.  But I do
- * know that this all fits inside an 8K page, so I'll just map in
- * once.
- *
- * What we really need is some way to record the bus attach args
- * so we can call *_bus_map() later with BUS_SPACE_MAP_READONLY
- * or not to write enable/disable the device registers.  This is
- * a non-trivial operation.  
- */
-
-/* ARGSUSED */
-static void
-clockattach_sbus(struct device *parent, struct device *self, void *aux)
-{
-	struct mk48txx_softc *sc = (void *)self;
-	struct sbus_attach_args *sa = aux;
-	int sz;
-
-	sc->sc_bst = sa->sa_bustag;
-
-	/* use sa->sa_regs[0].size? */
-	sz = 8192;
-
-	if (sbus_bus_map(sc->sc_bst,
-			 sa->sa_slot,
-			 (sa->sa_offset & ~(PAGE_SIZE - 1)),
-			 sz,
-			 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY,
-			 &sc->sc_bsh) != 0) {
-		printf("%s: can't map register\n", self->dv_xname);
-		return;
-	}
-	clockattach(sc, sa->sa_node);
-
-	/* Save info for the clock wenable call. */
-	sc->sc_handle.todr_setwen = clock_wenable;
-
-	todr_attach(&sc->sc_handle);
-}
-
-/*
- * Write en/dis-able clock registers.  We coordinate so that several
- * writers can run simultaneously.
- */
-int
-clock_wenable(struct todr_chip_handle *handle, int onoff)
-{
-	struct mk48txx_softc *sc;
-	vm_prot_t prot;
-	vaddr_t va;
-	int s, err = 0;
-	static int writers;
-
-	s = splhigh();
-	if (onoff)
-		prot = writers++ == 0 ? VM_PROT_READ|VM_PROT_WRITE : 0;
-	else
-		prot = --writers == 0 ? VM_PROT_READ : 0;
-	splx(s);
-	if (prot == VM_PROT_NONE) {
-		return 0;
-	}
-	sc = handle->cookie;
-	va = (vaddr_t)bus_space_vaddr(sc->sc_bst, sc->sc_bsh);
-	if (va == 0UL) {
-		printf("clock_wenable: WARNING -- cannot get va\n");
-		return EIO;
-	}
-	pmap_kprotect(va, prot);
-	return (err);
-}
-
-
-/* ARGSUSED */
-static void
-clockattach_ebus(struct device *parent, struct device *self, void *aux)
-{
-	struct mk48txx_softc *sc = (void *)self;
-	struct ebus_attach_args *ea = aux;
-	int sz;
-
-	sc->sc_bst = ea->ea_bustag;
-
-	/* hard code to 8K? */
-	sz = ea->ea_reg[0].size;
-
-	if (bus_space_map(sc->sc_bst,
-			 EBUS_ADDR_FROM_REG(&ea->ea_reg[0]),
-			 sz,
-			 BUS_SPACE_MAP_LINEAR,
-			 &sc->sc_bsh) != 0) {
-		printf("%s: can't map register\n", self->dv_xname);
-		return;
-	}
-	clockattach(sc, ea->ea_node);
-
-	/* Save info for the clock wenable call. */
-	sc->sc_handle.todr_setwen = clock_wenable;
-
-	todr_attach(&sc->sc_handle);
-}
-
-
-static void
-clockattach(struct mk48txx_softc *sc, int node)
-{
-
-	sc->sc_model = prom_getpropstring(node, "model");
-
-#ifdef DIAGNOSTIC
-	if (sc->sc_model == NULL)
-		panic("clockattach: no model property");
-#endif
-
-	/* Our TOD clock year 0 is 1968 */
-	sc->sc_year0 = 1968;
-	mk48txx_attach(sc);
-
-	printf("\n");
-}
-
 static u_int timer_get_timecount(struct timecounter *);
 
 /*
--- /dev/null	2006-10-09 14:51:44.000000000 +0900
+++ dev/mcclock.c	2006-10-09 14:09:30.000000000 +0900
@@ -0,0 +1,206 @@
+/*	$NetBSD: rtc.c,v 1.1 2006/10/09 03:34:56 mrg Exp $	*/
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1994 Gordon W. Ross
+ * Copyright (c) 1993 Adam Glass
+ * Copyright (c) 1996 Paul Kranenburg
+ * Copyright (c) 1996
+ * 	The President and Fellows of Harvard College. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by Harvard University.
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ *	This product includes software developed by Paul Kranenburg.
+ *	This product includes software developed by Harvard University.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ *	@(#)clock.c	8.1 (Berkeley) 6/11/93
+ * from: NetBSD: clock.c,v 1.80 2006/09/03 22:27:45 gdamore Exp
+ *
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: rtc.c,v 1.1 2006/10/09 03:34:56 mrg Exp $");
+
+/*
+ * Clock driver for 'mcclock' - mc146818 driver.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+
+#include <machine/bus.h>
+#include <machine/autoconf.h>
+
+#include <dev/clock_subr.h>
+#include <dev/ic/mc146818reg.h>
+#include <dev/ic/mc146818var.h>
+
+#include <dev/ebus/ebusreg.h>
+#include <dev/ebus/ebusvar.h>
+
+static int	mcclock_ebus_match(struct device *, struct cfdata *, void *);
+static void	mcclock_ebus_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(mcclock_ebus, sizeof(struct mc146818_softc),
+    mcclock_ebus_match, mcclock_ebus_attach, NULL, NULL);
+
+u_int rtc_read_reg(struct mc146818_softc *, u_int);
+void rtc_write_reg(struct mc146818_softc *, u_int, u_int);
+u_int rtc_getcent(struct mc146818_softc *);
+void rtc_setcent(struct mc146818_softc *, u_int);
+
+static int
+mcclock_ebus_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+	struct ebus_attach_args *ea = aux;
+
+	return (strcmp("rtc", ea->ea_name) == 0);
+}
+
+/*
+ * `rtc' is a ds1287 on an ebus (actually an isa bus, but we use the
+ * ebus driver for isa.)  So we can use ebus_wenable() but need to do
+ * different attach work and use different todr routines.  It does not
+ * incorporate an IDPROM.
+ */
+
+/*
+ * XXX the stupid ds1287 is not mapped directly but uses an address
+ * and a data reg so we cannot access the stuuupid thing w/o having
+ * write access to the registers.
+ *
+ * XXXX We really need to mutex register access!
+ */
+#define	RTC_ADDR	0
+#define	RTC_DATA	1
+u_int
+rtc_read_reg(struct mc146818_softc *sc, u_int reg)
+{
+
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, RTC_ADDR, reg);
+	return (bus_space_read_1(sc->sc_bst, sc->sc_bsh, RTC_DATA));
+}
+void 
+rtc_write_reg(struct mc146818_softc *sc, u_int reg, u_int val)
+{
+
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, RTC_ADDR, reg);
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, RTC_DATA, val);
+}
+
+/* ARGSUSED */
+static void
+mcclock_ebus_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct mc146818_softc *sc = (void *)self;
+	struct ebus_attach_args *ea = aux;
+	char *model;
+	int sz;
+
+	sc->sc_bst = ea->ea_bustag;
+
+	/* hard code to 8K? */
+	sz = ea->ea_reg[0].size;
+
+	if (bus_space_map(sc->sc_bst,
+			 EBUS_ADDR_FROM_REG(&ea->ea_reg[0]),
+			 sz,
+			 BUS_SPACE_MAP_LINEAR,
+			 &sc->sc_bsh) != 0) {
+		printf("%s: can't map register\n", self->dv_xname);
+		return;
+	}
+
+	model = prom_getpropstring(ea->ea_node, "model");
+#ifdef DIAGNOSTIC
+	if (model == NULL)
+		panic("clockattach_rtc: no model property");
+#endif
+
+	/* Our TOD clock year 0 is 0 */
+	sc->sc_year0 = 0;
+	sc->sc_flag = MC146818_NO_CENT_ADJUST;
+	sc->sc_mcread = rtc_read_reg;
+	sc->sc_mcwrite = rtc_write_reg;
+	sc->sc_getcent = rtc_getcent;
+	sc->sc_setcent = rtc_setcent;
+	mc146818_attach(sc);
+
+	printf(": %s\n", model);
+
+	/*
+	 * Turn interrupts off, just in case. (Although they shouldn't
+	 * be wired to an interrupt controller on sparcs).
+	 */
+	rtc_write_reg(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
+
+	/*
+	 * Apparently on some machines the TOD registers are on the same
+	 * physical page as the COM registers.  So we won't protect them.
+	 */
+	/*sc->sc_handle.todr_setwen = NULL;*/
+
+	todr_attach(&sc->sc_handle);
+}
+
+/*
+ * MD mc146818 RTC todr routines.
+ */
+
+/* Loooks like Sun stores the century info somewhere in CMOS RAM */
+#define MC_CENT 0x32
+
+u_int
+rtc_getcent(sc)
+	struct mc146818_softc *sc;
+{
+
+	return rtc_read_reg(sc, MC_CENT);
+}
+void 
+rtc_setcent(sc, cent)
+	struct mc146818_softc *sc;
+	u_int cent;
+{
+
+	rtc_write_reg(sc, MC_CENT, cent);
+}
--- /dev/null	2006-10-09 14:51:44.000000000 +0900
+++ dev/mkclock.c	2006-10-09 15:11:13.000000000 +0900
@@ -0,0 +1,258 @@
+/*	$NetBSD: clock.c,v 1.81 2006/10/09 03:34:56 mrg Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1994 Gordon W. Ross
+ * Copyright (c) 1993 Adam Glass
+ * Copyright (c) 1996 Paul Kranenburg
+ * Copyright (c) 1996
+ * 	The President and Fellows of Harvard College. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *	This product includes software developed by Harvard University.
+ *	This product includes software developed by the University of
+ *	California, Lawrence Berkeley Laboratory.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ *	This product includes software developed by Paul Kranenburg.
+ *	This product includes software developed by Harvard University.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ *	@(#)clock.c	8.1 (Berkeley) 6/11/93
+ *
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.81 2006/10/09 03:34:56 mrg Exp $");
+
+/*    
+ * Clock driver for 'mkclock' - Mostek MK48Txx TOD clock.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/autoconf.h>
+#include <machine/eeprom.h>
+#include <machine/cpu.h>
+
+#include <dev/clock_subr.h>
+#include <dev/ic/mk48txxreg.h>
+#include <dev/ic/mk48txxvar.h>
+
+#include <sparc64/dev/iommureg.h>
+#include <sparc64/dev/sbusreg.h>
+#include <dev/sbus/sbusvar.h>
+#include <dev/ebus/ebusreg.h>
+#include <dev/ebus/ebusvar.h>
+
+#include "ioconf.h"
+
+/*
+ * clock (eeprom) attaches at the sbus or the ebus (PCI)
+ */
+static int	mkclock_sbus_match(struct device *, struct cfdata *, void *);
+static void	mkclock_sbus_attach(struct device *, struct device *, void *);
+
+static int	mkclock_ebus_match(struct device *, struct cfdata *, void *);
+static void	mkclock_ebus_attach(struct device *, struct device *, void *);
+
+static void	mkclock_attach(struct mk48txx_softc *, int);
+
+static int	mkclock_wenable(struct todr_chip_handle *, int);
+
+
+CFATTACH_DECL(mkclock_sbus, sizeof(struct mk48txx_softc),
+    mkclock_sbus_match, mkclock_sbus_attach, NULL, NULL);
+
+CFATTACH_DECL(mkclock_ebus, sizeof(struct mk48txx_softc),
+    mkclock_ebus_match, mkclock_ebus_attach, NULL, NULL);
+
+/*
+ * The OPENPROM calls the clock the "eeprom", so we have to have our
+ * own special match function to call it the "clock".
+ */
+static int
+mkclock_sbus_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+	struct sbus_attach_args *sa = aux;
+
+	return (strcmp("eeprom", sa->sa_name) == 0);
+}
+
+static int
+mkclock_ebus_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+	struct ebus_attach_args *ea = aux;
+
+	return (strcmp("eeprom", ea->ea_name) == 0);
+}
+
+/*
+ * Attach a clock (really `eeprom') to the sbus or ebus.
+ *
+ * We ignore any existing virtual address as we need to map
+ * this read-only and make it read-write only temporarily,
+ * whenever we read or write the clock chip.  The clock also
+ * contains the ID ``PROM'', and I have already had the pleasure
+ * of reloading the CPU type, Ethernet address, etc, by hand from
+ * the console FORTH interpreter.  I intend not to enjoy it again.
+ *
+ * the MK48T02 is 2K.  the MK48T08 is 8K, and the MK48T59 is
+ * supposed to be identical to it.
+ *
+ * This is *UGLY*!  We probably have multiple mappings.  But I do
+ * know that this all fits inside an 8K page, so I'll just map in
+ * once.
+ *
+ * What we really need is some way to record the bus attach args
+ * so we can call *_bus_map() later with BUS_SPACE_MAP_READONLY
+ * or not to write enable/disable the device registers.  This is
+ * a non-trivial operation.  
+ */
+
+/* ARGSUSED */
+static void
+mkclock_sbus_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct mk48txx_softc *sc = (void *)self;
+	struct sbus_attach_args *sa = aux;
+	int sz;
+
+	sc->sc_bst = sa->sa_bustag;
+
+	/* use sa->sa_regs[0].size? */
+	sz = 8192;
+
+	if (sbus_bus_map(sc->sc_bst,
+			 sa->sa_slot,
+			 (sa->sa_offset & ~(PAGE_SIZE - 1)),
+			 sz,
+			 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY,
+			 &sc->sc_bsh) != 0) {
+		printf("%s: can't map register\n", self->dv_xname);
+		return;
+	}
+	mkclock_attach(sc, sa->sa_node);
+}
+
+
+/* ARGSUSED */
+static void
+mkclock_ebus_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct mk48txx_softc *sc = (void *)self;
+	struct ebus_attach_args *ea = aux;
+	int sz;
+
+	sc->sc_bst = ea->ea_bustag;
+
+	/* hard code to 8K? */
+	sz = ea->ea_reg[0].size;
+
+	if (bus_space_map(sc->sc_bst,
+			 EBUS_ADDR_FROM_REG(&ea->ea_reg[0]),
+			 sz,
+			 BUS_SPACE_MAP_LINEAR,
+			 &sc->sc_bsh) != 0) {
+		printf("%s: can't map register\n", self->dv_xname);
+		return;
+	}
+	mkclock_attach(sc, ea->ea_node);
+}
+
+
+static void
+mkclock_attach(struct mk48txx_softc *sc, int node)
+{
+
+	sc->sc_model = prom_getpropstring(node, "model");
+
+#ifdef DIAGNOSTIC
+	if (sc->sc_model == NULL)
+		panic("clockattach: no model property");
+#endif
+
+	/* Our TOD clock year 0 is 1968 */
+	sc->sc_year0 = 1968;
+	mk48txx_attach(sc);
+
+	printf("\n");
+
+	/* Save info for the clock wenable call. */
+	sc->sc_handle.todr_setwen = mkclock_wenable;
+
+	todr_attach(&sc->sc_handle);
+}
+
+/*
+ * Write en/dis-able clock registers.  We coordinate so that several
+ * writers can run simultaneously.
+ */
+static int
+mkclock_wenable(struct todr_chip_handle *handle, int onoff)
+{
+	struct mk48txx_softc *sc;
+	vm_prot_t prot;
+	vaddr_t va;
+	int s, err = 0;
+	static int writers;
+
+	s = splhigh();
+	if (onoff)
+		prot = writers++ == 0 ? VM_PROT_READ|VM_PROT_WRITE : 0;
+	else
+		prot = --writers == 0 ? VM_PROT_READ : 0;
+	splx(s);
+	if (prot == VM_PROT_NONE) {
+		return 0;
+	}
+	sc = handle->cookie;
+	va = (vaddr_t)bus_space_vaddr(sc->sc_bst, sc->sc_bsh);
+	if (va == 0UL) {
+		printf("clock_wenable: WARNING -- cannot get va\n");
+		return EIO;
+	}
+	pmap_kprotect(va, prot);
+	return (err);
+}