PERFORCE change 123985 for review

Christopher Davis loafier at FreeBSD.org
Mon Jul 23 23:39:06 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=123985

Change 123985 by loafier at chrisdsoc on 2007/07/23 23:38:49

	Use bus_alloc_resources(), pci_enable_busmaster(), etc.
	The driver was missing detach, suspend and resume methods.
	I added detatch method here, but I don't know what to send 
	to the card to shut it down.
	Haven't tested this.

Affected files ...

.. //depot/projects/soc2007/loafier_busalloc/src/sys/dev/sound/pci/aureal.c#2 edit

Differences ...

==== //depot/projects/soc2007/loafier_busalloc/src/sys/dev/sound/pci/aureal.c#2 (text+ko) ====

@@ -66,12 +66,31 @@
 	int dir;
 };
 
+/* XXX: seems like the driver only makes use of one port */
+
+enum {
+	RES_P0,
+	RES_IRQ,
+	RES_SZ
+};
+
+static struct resource_spec au_res_spec_mem[] = {
+	{SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE},
+	{SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHARABLE}
+};
+
+static struct resource_spec au_res_spec_io[] = {
+	{SYS_RES_IOPORT, PCIR_BAR(0), RF_ACTIVE},
+	{SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHARABLE}
+};
+
 struct au_info {
 	int unit;
+	
+	struct resource_spec *spec;
+	struct resource *res[RES_SZ];
+	void *ih;
 
-	bus_space_tag_t st[3];
-	bus_space_handle_t sh[3];
-
 	bus_dma_tag_t	parent_dmat;
 	struct mtx *lock;
 
@@ -86,36 +105,13 @@
 
 /* -------------------------------------------------------------------- */
 
-static u_int32_t
-au_rd(struct au_info *au, int mapno, int regno, int size)
-{
-	switch(size) {
-	case 1:
-		return bus_space_read_1(au->st[mapno], au->sh[mapno], regno);
-	case 2:
-		return bus_space_read_2(au->st[mapno], au->sh[mapno], regno);
-	case 4:
-		return bus_space_read_4(au->st[mapno], au->sh[mapno], regno);
-	default:
-		return 0xffffffff;
-	}
-}
+#define au_rd1(_sc, _reg) bus_read_1((_sc)->res[RES_P0], _reg)
+#define au_rd2(_sc, _reg) bus_read_2((_sc)->res[RES_P0], _reg)
+#define au_rd4(_sc, _reg) bus_read_4((_sc)->res[RES_P0], _reg)
 
-static void
-au_wr(struct au_info *au, int mapno, int regno, u_int32_t data, int size)
-{
-	switch(size) {
-	case 1:
-		bus_space_write_1(au->st[mapno], au->sh[mapno], regno, data);
-		break;
-	case 2:
-		bus_space_write_2(au->st[mapno], au->sh[mapno], regno, data);
-		break;
-	case 4:
-		bus_space_write_4(au->st[mapno], au->sh[mapno], regno, data);
-		break;
-	}
-}
+#define au_wr1(_sc, _reg, _val) bus_write_1((_sc)->res[RES_P0], _reg, _val)
+#define au_wr2(_sc, _reg, _val) bus_write_2((_sc)->res[RES_P0], _reg, _val)
+#define au_wr4(_sc, _reg, _val) bus_write_4((_sc)->res[RES_P0], _reg, _val)
 
 /* -------------------------------------------------------------------- */
 
@@ -126,9 +122,9 @@
 	int i=0, j=0;
 
 	regno<<=16;
-	au_wr(au, 0, AU_REG_CODECIO, regno, 4);
+	au_wr4(au, AU_REG_CODECIO, regno);
 	while (j<50) {
-		i=au_rd(au, 0, AU_REG_CODECIO, 4);
+		i=au_rd4(au, AU_REG_CODECIO);
 		if ((i & 0x00ff0000) == (regno | 0x00800000)) break;
 		DELAY(j * 200 + 2000);
 		j++;
@@ -146,13 +142,13 @@
 	i=j=tries=0;
 	do {
 		while (j<50 && (i & AU_CDC_WROK) == 0) {
-			i=au_rd(au, 0, AU_REG_CODECST, 4);
+			i=au_rd4(au, AU_REG_CODECST);
 			DELAY(2000);
 			j++;
 		}
 		if (j==50) printf("codec timeout during write of register %x, data %x\n",
 				  regno, data);
-		au_wr(au, 0, AU_REG_CODECIO, (regno<<16) | AU_CDC_REGSET | data, 4);
+		au_wr4(au, AU_REG_CODECIO, (regno<<16) | AU_CDC_REGSET | data);
 /*		DELAY(20000);
 		i=au_rdcd(au, regno);
 */		tries++;
@@ -188,8 +184,8 @@
 	int j = 0x1099c+(a<<2);
 	if (au->x[a] != a+0x67) j = AU_REG_RTBASE+(au->x[a]<<2);
 
-	au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xffffffff, 4);
- 	au_wr(au, 0, j, route | (b<<7), 4);
+	au_wr4(au, AU_REG_RTBASE+(route<<2), 0xffffffff);
+ 	au_wr4(au, j, route | (b<<7));
 	au->y[route]=au->x[a];
 	au->x[a]=route;
 	au->z[route]=a & 0x000000ff;
@@ -204,10 +200,10 @@
 
 	au_setbit(au->routes, route, 0);
 	au->z[route]=0x1f;
-	i=au_rd(au, 0, AU_REG_RTBASE+(route<<2), 4);
-	au_wr(au, 0, AU_REG_RTBASE+(au->y[route]<<2), i, 4);
+	i=au_rd4(au, AU_REG_RTBASE+(route<<2));
+	au_wr4(au, AU_REG_RTBASE+(au->y[route]<<2), i);
 	au->y[i & 0x7f]=au->y[route];
-	au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xfffffffe, 4);
+	au_wr4(au, AU_REG_RTBASE+(route<<2), 0xfffffffe);
 	if (au->x[j] == route) au->x[j]=au->y[route];
 	au->y[route]=0x7f;
 }
@@ -215,8 +211,8 @@
 static void
 au_encodec(struct au_info *au, char channel)
 {
-	au_wr(au, 0, AU_REG_CODECEN,
-	      au_rd(au, 0, AU_REG_CODECEN, 4) | (1 << (channel + 8)), 4);
+	au_wr4(au, AU_REG_CODECEN,
+	      au_rd4(au, AU_REG_CODECEN) | (1 << (channel + 8)));
 }
 
 static void
@@ -224,7 +220,7 @@
 {
 	u_int32_t i;
 
-	for (i=0; i<32; i++) au_wr(au, 0, AU_REG_FIFOBASE+(c<<7)+(i<<2), 0, 4);
+	for (i=0; i<32; i++) au_wr4(au, AU_REG_FIFOBASE+(c<<7)+(i<<2), 0);
 }
 
 static void
@@ -232,10 +228,10 @@
 {
 	int x;
 
-	x = au_rd(au, 0, AU_REG_ADB, 4);
+	x = au_rd4(au, AU_REG_ADB);
 	x &= ~(1 << c);
 	x |= (enable << c);
-	au_wr(au, 0, AU_REG_ADB, x, 4);
+	au_wr4(au, AU_REG_ADB, x);
 }
 
 static void
@@ -245,9 +241,9 @@
 	int i, stereo = (format & AFMT_STEREO)? 1 : 0;
 	u_int32_t baseaddr = sndbuf_getbufaddr(ch->buffer);
 
-	au_wr(au, 0, 0x1061c, 0, 4);
-	au_wr(au, 0, 0x10620, 0, 4);
-	au_wr(au, 0, 0x10624, 0, 4);
+	au_wr4(au, 0x1061c, 0);
+	au_wr4(au, 0x10620, 0);
+	au_wr4(au, 0x10624, 0);
 	switch(format & ~AFMT_STEREO) {
 		case 1:
 			i=0xb000;
@@ -264,28 +260,28 @@
 		default:
 			i=0x3000;
 	}
-	au_wr(au, 0, 0x10200, baseaddr, 4);
-	au_wr(au, 0, 0x10204, baseaddr+0x1000, 4);
-	au_wr(au, 0, 0x10208, baseaddr+0x2000, 4);
-	au_wr(au, 0, 0x1020c, baseaddr+0x3000, 4);
+	au_wr4(au, 0x10200, baseaddr);
+	au_wr4(au, 0x10204, baseaddr+0x1000);
+	au_wr4(au, 0x10208, baseaddr+0x2000);
+	au_wr4(au, 0x1020c, baseaddr+0x3000);
 
-	au_wr(au, 0, 0x10400, 0xdeffffff, 4);
-	au_wr(au, 0, 0x10404, 0xfcffffff, 4);
+	au_wr4(au, 0x10400, 0xdeffffff);
+	au_wr4(au, 0x10404, 0xfcffffff);
 
-	au_wr(au, 0, 0x10580, i, 4);
+	au_wr4(au, 0x10580, i);
 
-	au_wr(au, 0, 0x10210, baseaddr, 4);
-	au_wr(au, 0, 0x10214, baseaddr+0x1000, 4);
-	au_wr(au, 0, 0x10218, baseaddr+0x2000, 4);
-	au_wr(au, 0, 0x1021c, baseaddr+0x3000, 4);
+	au_wr4(au, 0x10210, baseaddr);
+	au_wr4(au, 0x10214, baseaddr+0x1000);
+	au_wr4(au, 0x10218, baseaddr+0x2000);
+	au_wr4(au, 0x1021c, baseaddr+0x3000);
 
-	au_wr(au, 0, 0x10408, 0x00fff000 | 0x56000000 | 0x00000fff, 4);
-	au_wr(au, 0, 0x1040c, 0x00fff000 | 0x74000000 | 0x00000fff, 4);
+	au_wr4(au, 0x10408, 0x00fff000 | 0x56000000 | 0x00000fff);
+	au_wr4(au, 0x1040c, 0x00fff000 | 0x74000000 | 0x00000fff);
 
-	au_wr(au, 0, 0x10584, i, 4);
+	au_wr4(au, 0x10584, i);
 
-	au_wr(au, 0, 0x0f800, stereo? 0x00030032 : 0x00030030, 4);
-	au_wr(au, 0, 0x0f804, stereo? 0x00030032 : 0x00030030, 4);
+	au_wr4(au, 0x0f800, stereo? 0x00030032 : 0x00030030);
+	au_wr4(au, 0x0f804, stereo? 0x00030032 : 0x00030030);
 
 	au_addroute(au, 0x11, 0, 0x58);
 	au_addroute(au, 0x11, stereo? 0 : 1, 0x59);
@@ -345,8 +341,8 @@
 	if (ch->dir == PCMDIR_PLAY) {
 		au_setadb(au, 0x11, (go)? 1 : 0);
 		if (go != PCMTRIG_START) {
-			au_wr(au, 0, 0xf800, 0, 4);
-			au_wr(au, 0, 0xf804, 0, 4);
+			au_wr4(au, 0xf800, 0);
+			au_wr4(au, 0xf804, 0);
 			au_delroute(au, 0x58);
 			au_delroute(au, 0x59);
 		}
@@ -361,7 +357,7 @@
 	struct au_chinfo *ch = data;
 	struct au_info *au = ch->parent;
 	if (ch->dir == PCMDIR_PLAY) {
-		return au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1);
+		return au_rd4(au, AU_REG_UNK2) & (AU_BUFFSIZE-1);
 	} else {
 		return 0;
 	}
@@ -395,21 +391,21 @@
 	u_int32_t	intsrc, i;
 
 	au->interrupts++;
-	intsrc=au_rd(au, 0, AU_REG_IRQSRC, 4);
+	intsrc=au_rd4(au, AU_REG_IRQSRC);
 	printf("pcm%d: interrupt with src %x\n", au->unit, intsrc);
 	if (intsrc & AU_IRQ_FATAL) printf("pcm%d: fatal error irq\n", au->unit);
 	if (intsrc & AU_IRQ_PARITY) printf("pcm%d: parity error irq\n", au->unit);
 	if (intsrc & AU_IRQ_UNKNOWN) {
-		(void)au_rd(au, 0, AU_REG_UNK1, 4);
-		au_wr(au, 0, AU_REG_UNK1, 0, 4);
-		au_wr(au, 0, AU_REG_UNK1, 0x10000, 4);
+		(void)au_rd4(au, AU_REG_UNK1);
+		au_wr4(au, AU_REG_UNK1, 0);
+		au_wr4(au, AU_REG_UNK1, 0x10000);
 	}
 	if (intsrc & AU_IRQ_PCMOUT) {
-	       	i=au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1);
+	       	i=au_rd4(au, AU_REG_UNK2) & (AU_BUFFSIZE-1);
 	       	chn_intr(au->pch.channel);
-		(void)au_rd(au, 0, AU_REG_UNK3, 4);
-		(void)au_rd(au, 0, AU_REG_UNK4, 4);
-		(void)au_rd(au, 0, AU_REG_UNK5, 4);
+		(void)au_rd4(au, AU_REG_UNK3);
+		(void)au_rd4(au, AU_REG_UNK4);
+		(void)au_rd4(au, AU_REG_UNK5);
 	}
 /* don't support midi
 	if (intsrc & AU_IRQ_MIDI) {
@@ -424,8 +420,8 @@
 		}
 	}
 */
-	au_wr(au, 0, AU_REG_IRQSRC, intsrc & 0x7ff, 4);
-	au_rd(au, 0, AU_REG_IRQSRC, 4);
+	au_wr4(au, AU_REG_IRQSRC, intsrc & 0x7ff);
+	au_rd4(au, AU_REG_IRQSRC);
 }
 
 
@@ -438,48 +434,48 @@
 {
 	u_int32_t	i, j;
 
-	au_wr(au, 0, AU_REG_IRQGLOB, 0xffffffff, 4);
+	au_wr4(au, AU_REG_IRQGLOB, 0xffffffff);
 	DELAY(100000);
 
 	/* init codec */
 	/* cold reset */
 	for (i=0; i<32; i++) {
-		au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4);
+		au_wr4(au, AU_REG_CODECCHN+(i<<2), 0);
 		DELAY(10000);
 	}
 	if (1) {
-		au_wr(au, 0, AU_REG_CODECST, 0x8068, 4);
+		au_wr4(au, AU_REG_CODECST, 0x8068);
 		DELAY(10000);
-		au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4);
+		au_wr4(au, AU_REG_CODECST, 0x00e8);
 		DELAY(10000);
 	} else {
-		au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4);
+		au_wr4(au, AU_REG_CODECST, 0x00a8);
  		DELAY(100000);
-		au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4);
+		au_wr4(au, AU_REG_CODECST, 0x80a8);
 		DELAY(100000);
-		au_wr(au, 0, AU_REG_CODECST, 0x80e8, 4);
+		au_wr4(au, AU_REG_CODECST, 0x80e8);
 		DELAY(100000);
-		au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4);
+		au_wr4(au, AU_REG_CODECST, 0x80a8);
 		DELAY(100000);
-		au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4);
+		au_wr4(au, AU_REG_CODECST, 0x00a8);
 		DELAY(100000);
-		au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4);
+		au_wr4(au, AU_REG_CODECST, 0x00e8);
 		DELAY(100000);
 	}
 
 	/* init */
 	for (i=0; i<32; i++) {
-		au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4);
+		au_wr4(au, AU_REG_CODECCHN+(i<<2), 0);
 		DELAY(10000);
 	}
-	au_wr(au, 0, AU_REG_CODECST, 0xe8, 4);
+	au_wr4(au, AU_REG_CODECST, 0xe8);
 	DELAY(10000);
-	au_wr(au, 0, AU_REG_CODECEN, 0, 4);
+	au_wr4(au, AU_REG_CODECEN, 0);
 
 	/* setup codec */
 	i=j=0;
 	while (j<100 && (i & AU_CDC_READY)==0) {
-		i=au_rd(au, 0, AU_REG_CODECST, 4);
+		i=au_rd4(au, AU_REG_CODECST);
 		DELAY(1000);
 		j++;
 	}
@@ -490,16 +486,16 @@
 	for (i=0; i<32;  i++) au->x[i]=i+0x67;
 	for (i=0; i<128; i++) au->y[i]=0x7f;
 	for (i=0; i<128; i++) au->z[i]=0x1f;
-	au_wr(au, 0, AU_REG_ADB, 0, 4);
-	for (i=0; i<124; i++) au_wr(au, 0, AU_REG_RTBASE+(i<<2), 0xffffffff, 4);
+	au_wr4(au, AU_REG_ADB, 0);
+	for (i=0; i<124; i++) au_wr4(au, AU_REG_RTBASE+(i<<2), 0xffffffff);
 
 	/* test */
-	i=au_rd(au, 0, 0x107c0, 4);
+	i=au_rd4(au, 0, 0x107c0);
  	if (i!=0xdeadbeef) device_printf(dev, "dma check failed: 0x%x\n", i);
 
 	/* install mixer */
-	au_wr(au, 0, AU_REG_IRQGLOB,
-	      au_rd(au, 0, AU_REG_IRQGLOB, 4) | AU_IRQ_ENABLE, 4);
+	au_wr4(au, AU_REG_IRQGLOB,
+	      au_rd4(au, AU_REG_IRQGLOB) | AU_IRQ_ENABLE);
 	/* braindead but it's what the oss/linux driver does
 	 * for (i=0; i<0x80000000; i++) au_wr(au, 0, i<<2, 0, 4);
 	 */
@@ -512,9 +508,9 @@
 	au_encodec(au, 0);
 	au_encodec(au, 1);
 
-	for (i=0; i<48; i++) au_wr(au, 0, 0xf800+(i<<2), 0x20, 4);
-	for (i=2; i<6; i++) au_wr(au, 0, 0xf800+(i<<2), 0, 4);
-	au_wr(au, 0, 0xf8c0, 0x0843, 4);
+	for (i=0; i<48; i++) au_wr4(au, 0xf800+(i<<2), 0x20);
+	for (i=2; i<6; i++) au_wr4(au, 0xf800+(i<<2), 0);
+	au_wr4(au, 0xf8c0, 0x0843);
 	for (i=0; i<4; i++) au_clrfifo(au, i);
 
 	return (0);
@@ -523,15 +519,27 @@
 static int
 au_testirq(struct au_info *au)
 {
-	au_wr(au, 0, AU_REG_UNK1, 0x80001000, 4);
-	au_wr(au, 0, AU_REG_IRQEN, 0x00001030, 4);
-	au_wr(au, 0, AU_REG_IRQSRC, 0x000007ff, 4);
+	au_wr4(au, AU_REG_UNK1, 0x80001000);
+	au_wr4(au, AU_REG_IRQEN, 0x00001030);
+	au_wr4(au, AU_REG_IRQSRC, 0x000007ff);
 	DELAY(1000000);
 	if (au->interrupts==0) printf("pcm%d: irq test failed\n", au->unit);
 	/* this apparently generates an irq */
 	return 0;
 }
 
+static void
+au_destroy(device_t dev, au_info *sc)
+{
+	if (!sc)
+		return;
+
+	if (sc->ih) 
+		bus_teardown_intr(dev, sc->res[RES_IRQ], sc->ih);
+	bus_release_resources(dev, sc->spec, sc->res);
+	free(sc, M_DEVBUF);
+}
+
 static int
 au_pci_probe(device_t dev)
 {
@@ -546,92 +554,49 @@
 static int
 au_pci_attach(device_t dev)
 {
-	u_int32_t	data;
-	struct au_info *au;
-	int		type[10];
-	int		regid[10];
-	struct resource *reg[10];
-	int		i, j, mapped = 0;
-	int		irqid;
-	struct resource *irq = 0;
-	void		*ih = 0;
+	struct au_info *sc;
 	struct ac97_info *codec;
 	char 		status[SND_STATUSLEN];
 
-	au = malloc(sizeof(*au), M_DEVBUF, M_WAITOK | M_ZERO);
-	au->unit = device_get_unit(dev);
+	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
+	if (sc == NULL) {
+		device_printf(dev, "cannot allocate softc\n");
+		return ENXIO;
+	}
+	sc->unit = device_get_unit(dev);
 
-	data = pci_read_config(dev, PCIR_COMMAND, 2);
-	data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
-	pci_write_config(dev, PCIR_COMMAND, data, 2);
-	data = pci_read_config(dev, PCIR_COMMAND, 2);
+	pci_enable_busmaster(dev);
+	pci_enable_io(dev, SYS_RES_IOPORT);
+	pci_enable_io(dev, SYS_RES_MEMORY);
 
-	j=0;
-	/* XXX dfr: is this strictly necessary? */
-	for (i=0; i<PCI_MAXMAPS_0; i++) {
-#if 0
-		/* Slapped wrist: config_id and map are private structures */
-		if (bootverbose) {
-			printf("pcm%d: map %d - allocating ", unit, i+1);
-			printf("0x%x bytes of ", 1<<config_id->map[i].ln2size);
-			printf("%s space ", (config_id->map[i].type & PCI_MAPPORT)?
-					    "io" : "memory");
-			printf("at 0x%x...", config_id->map[i].base);
+	sc->spec = au_res_spec_mem;
+	if (bus_alloc_resources(dev, sc->spec, sc->res) != 0) {
+		sc->spec = au_res_spec_io;
+		if (bus_alloc_resources(dev, sc->spec, sc->res) != 0) {
+			device_printf(dev, "unable to allocate resources\n");
+			goto bad;	
 		}
-#endif
-		regid[j] = PCIR_BAR(i);
-		type[j] = SYS_RES_MEMORY;
-		reg[j] = bus_alloc_resource_any(dev, type[j], &regid[j],
-						RF_ACTIVE);
-		if (!reg[j]) {
-			type[j] = SYS_RES_IOPORT;
-			reg[j] = bus_alloc_resource_any(dev, type[j], 
-							&regid[j], RF_ACTIVE);
-		}
-		if (reg[j]) {
-			au->st[i] = rman_get_bustag(reg[j]);
-			au->sh[i] = rman_get_bushandle(reg[j]);
-			mapped++;
-		}
-#if 0
-		if (bootverbose) printf("%s\n", mapped? "ok" : "failed");
-#endif
-		if (mapped) j++;
-		if (j == 10) {
-			/* XXX */
-			device_printf(dev, "too many resources");
-			goto bad;
-		}
-	}
+	}	
 
-#if 0
-	if (j < config_id->nummaps) {
-		printf("pcm%d: unable to map a required resource\n", unit);
-		free(au, M_DEVBUF);
-		return;
-	}
-#endif
-
-	au_wr(au, 0, AU_REG_IRQEN, 0, 4);
-
-	irqid = 0;
-	irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqid,
-				     RF_ACTIVE | RF_SHAREABLE);
-	if (!irq || snd_setup_intr(dev, irq, 0, au_intr, au, &ih)) {
+	au_wr4(sc, AU_REG_IRQEN, 0);
+	if (snd_setup_intr(dev, sc->res[RES_IRQ], 0, au_intr, sc, &sc->ih)) {
 		device_printf(dev, "unable to map interrupt\n");
 		goto bad;
 	}
 
-	if (au_testirq(au)) device_printf(dev, "irq test failed\n");
+	if (au_testirq(sc)) 
+		device_printf(dev, "irq test failed\n");
 
-	if (au_init(dev, au) == -1) {
+	if (au_init(dev, sc) == -1) {
 		device_printf(dev, "unable to initialize the card\n");
 		goto bad;
 	}
 
-	codec = AC97_CREATE(dev, au, au_ac97);
-	if (codec == NULL) goto bad;
-	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
+	codec = AC97_CREATE(dev, sc, au_ac97);
+	if (codec == NULL) 
+		goto bad;
+	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) 
+		goto bad;
 
 	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
 		/*boundary*/0,
@@ -646,29 +611,47 @@
 	}
 
 	snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
-		 (type[0] == SYS_RES_IOPORT)? "io" : "memory",
-		 rman_get_start(reg[0]), rman_get_start(irq),PCM_KLDSTRING(snd_aureal));
+		 (sc->spec == au_res_spec_io)? "io" : "memory",
+		 rman_get_start(sc->res[RES_P0]), 
+		 rman_get_start(sc->res[RES_IRQ]),
+		 PCM_KLDSTRING(snd_aureal));
 
-	if (pcm_register(dev, au, 1, 1)) goto bad;
+	if (pcm_register(dev, sc, 1, 1)) 
+		goto bad;
 	/* pcm_addchan(dev, PCMDIR_REC, &au_chantemplate, au); */
-	pcm_addchan(dev, PCMDIR_PLAY, &auchan_class, au);
+	pcm_addchan(dev, PCMDIR_PLAY, &auchan_class, sc);
 	pcm_setstatus(dev, status);
 
 	return 0;
 
  bad:
-	if (au) free(au, M_DEVBUF);
-	for (i = 0; i < j; i++)
-		bus_release_resource(dev, type[i], regid[i], reg[i]);
-	if (ih) bus_teardown_intr(dev, irq, ih);
-	if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq);
+	au_destroy(dev, sc);
 	return ENXIO;
 }
 
+static int 
+au_pci_detach(device_t dev)
+{
+	int ret;
+	struct au_info *sc;
+
+	ret = pcm_unregister(dev);
+	if (ret)
+		return ret;
+
+	sc = pcm_getdevinfo(dev);
+
+	/* XXX: how to shut down card?? */
+	au_destroy(dev, sc);
+
+	return 0;
+}
+
 static device_method_t au_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		au_pci_probe),
 	DEVMETHOD(device_attach,	au_pci_attach),
+	DEVMETHOD(device_detach,	au_pci_detach),
 
 	{ 0, 0 }
 };


More information about the p4-projects mailing list