Subject: am7930 driver revisited...
To: None <tech-kern@netbsd.org>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: tech-kern
Date: 03/07/1999 21:53:11
i have some ~8-months old patches to start using the am79c30 attached
to the DEC ioctl asic on TC alphas and the Personal DECstation.

One of the big gotchtas is that sys/dev/ic/am7930.c frobs a device
struct directly. That doesn't work very well with the DMA-based ioctl
attachment, not to mention endian-ness issues.

At the time i hacked up some MD macros (see below); should we commit
this (modulo updates in the meantime), or frob the driver directly to
bus_space(9) and make all attachments pass in a bus-space tag?





--- /sys/dev/ic/am7930.c	Fri Aug 28 04:11:14 1998
+++ /sys/dev/ic/am7930subr.c	Sun Jun 21 23:05:16 1998
@@ -1,4 +1,4 @@
-/*	$NetBSD: am7930.c,v 1.40 1998/08/28 08:59:14 pk Exp $	*/
+/*	$NetBSD: am7930.c,v 1.33.2.1 1997/12/09 20:22:24 thorpej Exp $	*/
 
 /*
  * Copyright (c) 1995 Rolf Grossmann
@@ -53,13 +53,16 @@
 #include <dev/audio_if.h>
 
 #include <dev/ic/am7930reg.h>
+#include <machine/am7930_machdep.h>
 #include <dev/ic/am7930var.h>
 
 #define AUDIO_ROM_NAME "audio"
 
 #ifdef AUDIO_DEBUG
+extern void Dprintf __P((const char *, ...));
+
 int     am7930debug = 0;
-#define DPRINTF(x)      if (am7930debug) printf x
+#define DPRINTF(x)      if (am7930debug) Dprintf x
 #else
 #define DPRINTF(x)
 #endif
@@ -164,16 +167,20 @@
 	sc->sc_plevel = 128;
 	sc->sc_mlevel = 0;
 	sc->sc_out_port = SUNAUDIO_SPEAKER;
+/*XXX*/	printf("doing init_amd()\n");
 	init_amd(sc->sc_amd);
+/*XXX*/	printf("done init_amd()\n");
 }
 
 static void
 init_amd(amd)
 	register volatile struct am7930 *amd;
 {
+/*XXX*/	printf("in init_amd()\n");
 	/* disable interrupts */
-	amd->cr = AMDR_INIT;
-	amd->dr = AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE;
+	AM7930_WRITE_REG(amd, cr, AMDR_INIT);
+/*XXX*/	printf("in init_amd()\n");
+	AM7930_WRITE_REG(amd, dr, AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE);
 
 	/*
 	 * Initialize the mux unit.  We use MCR3 to route audio (MAP)
@@ -181,11 +188,11 @@
 	 * Setting the INT enable bit in MCR4 will generate an interrupt
 	 * on each converted audio sample.
 	 */
-	amd->cr = AMDR_MUX_1_4;
- 	amd->dr = 0;
-	amd->dr = 0;
-	amd->dr = (AMD_MCRCHAN_BB << 4) | AMD_MCRCHAN_BA;
-	amd->dr = AMD_MCR4_INT_ENABLE;
+	AM7930_WRITE_REG(amd, cr, AMDR_MUX_1_4);
+ 	AM7930_WRITE_REG(amd, dr, 0);
+	AM7930_WRITE_REG(amd, dr, 0);
+	AM7930_WRITE_REG(amd, dr, (AMD_MCRCHAN_BB << 4) | AMD_MCRCHAN_BA);
+	AM7930_WRITE_REG(amd, dr, AMD_MCR4_INT_ENABLE);
 }
 
 int
@@ -205,7 +212,7 @@
 	/* tell attach layer about open */
 	sc->sc_onopen(sc);
 
-	DPRINTF(("saopen: ok -> sc=%p\n", sc));
+	DPRINTF(("saopen: ok -> sc=0x%x\n",sc));
 
 	return (0);
 }
@@ -216,7 +223,7 @@
 {
 	register struct am7930_softc *sc = addr;
 
-	DPRINTF(("sa_close: sc=%p\n", sc));
+	DPRINTF(("sa_close: sc=0x%x\n", sc));
 	/*
 	 * halt i/o, clear open flag, and done.
 	 */
@@ -303,18 +310,22 @@
 
 	s = splaudio();
 
-	amd->cr = AMDR_MAP_MMR1;
-	amd->dr = map->mr_mmr1;
-	amd->cr = AMDR_MAP_GX;
+	AM7930_WRITE_REG(amd, cr, AMDR_MAP_MMR1);
+	AM7930_WRITE_REG(amd, dr, map->mr_mmr1);
+	AM7930_WRITE_REG(amd, cr, AMDR_MAP_GX);
 	WAMD16(sc, amd, map->mr_gx);
-	amd->cr = AMDR_MAP_STG;
+
+	AM7930_WRITE_REG(amd, cr, AMDR_MAP_STG);
 	WAMD16(sc, amd, map->mr_stgr);
-	amd->cr = AMDR_MAP_GR;
+
+	AM7930_WRITE_REG(amd, cr, AMDR_MAP_GR);
 	WAMD16(sc, amd, map->mr_gr);
-	amd->cr = AMDR_MAP_GER;
+
+	AM7930_WRITE_REG(amd, cr, AMDR_MAP_GER);
 	WAMD16(sc, amd, map->mr_ger);
-	amd->cr = AMDR_MAP_MMR2;
-	amd->dr = map->mr_mmr2;
+
+	AM7930_WRITE_REG(amd, cr, AMDR_MAP_MMR2);
+	AM7930_WRITE_REG(amd, dr, map->mr_mmr2);
 
 	splx(s);
 	return(0);
@@ -328,8 +339,8 @@
 	register volatile struct am7930 *amd = sc->sc_amd;
 
 	/* XXX only halt, if input is also halted ?? */
-	amd->cr = AMDR_INIT;
-	amd->dr = AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE;
+	AM7930_WRITE_REG(amd, cr, AMDR_INIT);
+	AM7930_WRITE_REG(amd, dr, AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE);
 	sc->sc_locked = 0;
 
 	return(0);
@@ -343,8 +354,8 @@
 	register volatile struct am7930 *amd = sc->sc_amd;
 
 	/* XXX only halt, if output is also halted ?? */
-	amd->cr = AMDR_INIT;
-	amd->dr = AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE;
+	AM7930_WRITE_REG(amd, cr, AMDR_INIT);
+	AM7930_WRITE_REG(amd, dr, AMD_INIT_PMS_ACTIVE | AMD_INIT_INT_DISABLE);
 	sc->sc_locked = 0;
 
 	return(0);
--- /dev/null	Sun Mar  7 20:20:35 1999
+++ /sys/arch/pmax/include/am7930_machdep.h	Mon Jun 22 00:02:28 1998
@@ -0,0 +1,21 @@
+/*	$NetBSD: am7930_machdep.h,v 1.0 1998/06/20 20:22:24 jonathan Exp $	*/
+
+#ifndef _AM7930_MACHDEP_H_
+#define _AM7930_MACHDEP_H_
+
+#define AUDIO_C_HANDLER	/* use C code to move samples, byte by byte */
+
+#define AM7930_REGOFF(rreg) (offsetof(struct am7930, rreg) * (1 << 6))
+
+#define AM7930_WRITE_REG(amd, reg, val) \
+  do {((volatile u_char*)amd)[AM7930_REGOFF(reg)] = (val); tc_wmb();} while (0)
+
+#define AM7930_READ_REG(amd, reg) \
+	 ( ((u_char*)amd)[AM7930_REGOFF(reg)] )
+
+struct intrhand {
+	int (*ih_fun) __P((void*));
+	void * ih_arg;
+};
+
+#endif	/* _AM7930_MACHDEP_H_ */