xref: /freebsd/sys/dev/sound/pci/csa.c (revision f259d7eed5f64e128da6505494c205221ce5299d)
1f259d7eeSSeigo Tanimura /*
2fe1a5d1cSSeigo Tanimura  * Copyright (c) 1999 Seigo Tanimura
3fe1a5d1cSSeigo Tanimura  * All rights reserved.
4fe1a5d1cSSeigo Tanimura  *
57012990aSSeigo Tanimura  * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
67012990aSSeigo Tanimura  * cwcealdr1.zip, the sample sources by Crystal Semiconductor.
77012990aSSeigo Tanimura  * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
87012990aSSeigo Tanimura  *
9fe1a5d1cSSeigo Tanimura  * Redistribution and use in source and binary forms, with or without
10fe1a5d1cSSeigo Tanimura  * modification, are permitted provided that the following conditions
11fe1a5d1cSSeigo Tanimura  * are met:
12fe1a5d1cSSeigo Tanimura  * 1. Redistributions of source code must retain the above copyright
13fe1a5d1cSSeigo Tanimura  *    notice, this list of conditions and the following disclaimer.
14fe1a5d1cSSeigo Tanimura  * 2. Redistributions in binary form must reproduce the above copyright
15fe1a5d1cSSeigo Tanimura  *    notice, this list of conditions and the following disclaimer in the
16fe1a5d1cSSeigo Tanimura  *    documentation and/or other materials provided with the distribution.
17fe1a5d1cSSeigo Tanimura  *
18fe1a5d1cSSeigo Tanimura  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19fe1a5d1cSSeigo Tanimura  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20fe1a5d1cSSeigo Tanimura  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21fe1a5d1cSSeigo Tanimura  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22fe1a5d1cSSeigo Tanimura  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23fe1a5d1cSSeigo Tanimura  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24fe1a5d1cSSeigo Tanimura  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25fe1a5d1cSSeigo Tanimura  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26fe1a5d1cSSeigo Tanimura  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27fe1a5d1cSSeigo Tanimura  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28fe1a5d1cSSeigo Tanimura  * SUCH DAMAGE.
29fe1a5d1cSSeigo Tanimura  *
30fe1a5d1cSSeigo Tanimura  * $FreeBSD$
31fe1a5d1cSSeigo Tanimura  */
32fe1a5d1cSSeigo Tanimura 
33fe1a5d1cSSeigo Tanimura #include "pci.h"
34fe1a5d1cSSeigo Tanimura 
35fe1a5d1cSSeigo Tanimura #include <sys/param.h>
36fe1a5d1cSSeigo Tanimura #include <sys/systm.h>
37fe1a5d1cSSeigo Tanimura #include <sys/kernel.h>
38fe1a5d1cSSeigo Tanimura #include <sys/bus.h>
39fe1a5d1cSSeigo Tanimura #include <sys/malloc.h>
40fe1a5d1cSSeigo Tanimura #include <sys/module.h>
41fe1a5d1cSSeigo Tanimura #include <machine/resource.h>
42fe1a5d1cSSeigo Tanimura #include <machine/bus.h>
43fe1a5d1cSSeigo Tanimura #include <machine/clock.h>
44fe1a5d1cSSeigo Tanimura #include <sys/rman.h>
45fe1a5d1cSSeigo Tanimura #include <sys/soundcard.h>
46fe1a5d1cSSeigo Tanimura #include <dev/sound/chip.h>
47fe1a5d1cSSeigo Tanimura #include <dev/sound/pci/csareg.h>
48fe1a5d1cSSeigo Tanimura #include <dev/sound/pci/csavar.h>
49fe1a5d1cSSeigo Tanimura 
50fe1a5d1cSSeigo Tanimura #if NPCI > 0
51fe1a5d1cSSeigo Tanimura #include <pci/pcireg.h>
52fe1a5d1cSSeigo Tanimura #include <pci/pcivar.h>
53fe1a5d1cSSeigo Tanimura #endif /* NPCI > 0 */
54fe1a5d1cSSeigo Tanimura 
55fe1a5d1cSSeigo Tanimura #include <dev/sound/pci/csaimg.h>
56fe1a5d1cSSeigo Tanimura 
57fe1a5d1cSSeigo Tanimura /* Here is the parameter structure per a device. */
58fe1a5d1cSSeigo Tanimura struct csa_softc {
59fe1a5d1cSSeigo Tanimura 	device_t dev; /* device */
60fe1a5d1cSSeigo Tanimura 	csa_res res; /* resources */
61fe1a5d1cSSeigo Tanimura 
62fe1a5d1cSSeigo Tanimura 	device_t pcm; /* pcm device */
63fe1a5d1cSSeigo Tanimura 	driver_intr_t* pcmintr; /* pcm intr */
64fe1a5d1cSSeigo Tanimura 	void *pcmintr_arg; /* pcm intr arg */
65125fdb98SSeigo Tanimura #if notyet
66fe1a5d1cSSeigo Tanimura 	device_t midi; /* midi device */
67fe1a5d1cSSeigo Tanimura 	driver_intr_t* midiintr; /* midi intr */
68fe1a5d1cSSeigo Tanimura 	void *midiintr_arg; /* midi intr arg */
69125fdb98SSeigo Tanimura #endif /* notyet */
70fe1a5d1cSSeigo Tanimura 	void *ih; /* cookie */
71f259d7eeSSeigo Tanimura 
72f259d7eeSSeigo Tanimura 	struct csa_bridgeinfo binfo; /* The state of this bridge. */
73fe1a5d1cSSeigo Tanimura };
74fe1a5d1cSSeigo Tanimura 
75fe1a5d1cSSeigo Tanimura typedef struct csa_softc *sc_p;
76fe1a5d1cSSeigo Tanimura 
77fe1a5d1cSSeigo Tanimura #if NPCI > 0
78fe1a5d1cSSeigo Tanimura static int csa_probe(device_t dev);
79fe1a5d1cSSeigo Tanimura static int csa_attach(device_t dev);
80fe1a5d1cSSeigo Tanimura #endif /* NPCI > 0 */
81fe1a5d1cSSeigo Tanimura static struct resource *csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
82fe1a5d1cSSeigo Tanimura 					      u_long start, u_long end, u_long count, u_int flags);
83fe1a5d1cSSeigo Tanimura static int csa_release_resource(device_t bus, device_t child, int type, int rid,
84fe1a5d1cSSeigo Tanimura 				   struct resource *r);
85f259d7eeSSeigo Tanimura static int csa_setup_intr(device_t bus, device_t child,
86f259d7eeSSeigo Tanimura 			  struct resource *irq, int flags,
87f259d7eeSSeigo Tanimura 			  driver_intr_t *intr, void *arg, void **cookiep);
88f259d7eeSSeigo Tanimura static int csa_teardown_intr(device_t bus, device_t child,
89f259d7eeSSeigo Tanimura 			     struct resource *irq, void *cookie);
90f259d7eeSSeigo Tanimura static driver_intr_t csa_intr;
91fe1a5d1cSSeigo Tanimura static int csa_initialize(sc_p scp);
92fe1a5d1cSSeigo Tanimura static void csa_resetdsp(csa_res *resp);
93fe1a5d1cSSeigo Tanimura static int csa_downloadimage(csa_res *resp);
94fe1a5d1cSSeigo Tanimura static int csa_transferimage(csa_res *resp, u_long *src, u_long dest, u_long len);
95fe1a5d1cSSeigo Tanimura 
96fe1a5d1cSSeigo Tanimura static devclass_t csa_devclass;
97fe1a5d1cSSeigo Tanimura 
98fe1a5d1cSSeigo Tanimura #if NPCI > 0
99fe1a5d1cSSeigo Tanimura static int
100fe1a5d1cSSeigo Tanimura csa_probe(device_t dev)
101fe1a5d1cSSeigo Tanimura {
102fe1a5d1cSSeigo Tanimura 	char *s;
103fe1a5d1cSSeigo Tanimura 
104fe1a5d1cSSeigo Tanimura 	s = NULL;
105fe1a5d1cSSeigo Tanimura 	switch (pci_get_devid(dev)) {
106fe1a5d1cSSeigo Tanimura 	case CS4610_PCI_ID:
107fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4610/4611 Audio accelerator";
108fe1a5d1cSSeigo Tanimura 		break;
109fe1a5d1cSSeigo Tanimura 	case CS4614_PCI_ID:
110fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4614/4622/4624 Audio accelerator/4280 Audio controller";
111fe1a5d1cSSeigo Tanimura 		break;
112fe1a5d1cSSeigo Tanimura 	case CS4615_PCI_ID:
113fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4615 Audio accelerator";
114fe1a5d1cSSeigo Tanimura 		break;
115fe1a5d1cSSeigo Tanimura 	case CS4281_PCI_ID:
116fe1a5d1cSSeigo Tanimura 		s = "Crystal Semiconductor CS4281 Audio controller";
117fe1a5d1cSSeigo Tanimura 		break;
118fe1a5d1cSSeigo Tanimura 	}
119fe1a5d1cSSeigo Tanimura 
120fe1a5d1cSSeigo Tanimura 	if (s != NULL) {
121fe1a5d1cSSeigo Tanimura 		device_set_desc(dev, s);
122fe1a5d1cSSeigo Tanimura 		return (0);
123fe1a5d1cSSeigo Tanimura 	}
124fe1a5d1cSSeigo Tanimura 
125fe1a5d1cSSeigo Tanimura 	return (ENXIO);
126fe1a5d1cSSeigo Tanimura }
127fe1a5d1cSSeigo Tanimura 
128fe1a5d1cSSeigo Tanimura static int
129fe1a5d1cSSeigo Tanimura csa_attach(device_t dev)
130fe1a5d1cSSeigo Tanimura {
131fe1a5d1cSSeigo Tanimura 	u_int32_t stcmd;
132fe1a5d1cSSeigo Tanimura 	sc_p scp;
133fe1a5d1cSSeigo Tanimura 	csa_res *resp;
134f259d7eeSSeigo Tanimura 	struct sndcard_func *func;
135fe1a5d1cSSeigo Tanimura 
136fe1a5d1cSSeigo Tanimura 	scp = device_get_softc(dev);
137fe1a5d1cSSeigo Tanimura 
138fe1a5d1cSSeigo Tanimura 	/* Fill in the softc. */
139fe1a5d1cSSeigo Tanimura 	bzero(scp, sizeof(*scp));
140fe1a5d1cSSeigo Tanimura 	scp->dev = dev;
141fe1a5d1cSSeigo Tanimura 
142fe1a5d1cSSeigo Tanimura 	/* Wake up the device. */
143fe1a5d1cSSeigo Tanimura 	stcmd = pci_read_config(dev, PCIR_COMMAND, 4);
144fe1a5d1cSSeigo Tanimura 	if ((stcmd & PCIM_CMD_MEMEN) == 0 || (stcmd & PCIM_CMD_BUSMASTEREN) == 0) {
145fe1a5d1cSSeigo Tanimura 		stcmd |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
146fe1a5d1cSSeigo Tanimura 		pci_write_config(dev, PCIR_COMMAND, 4, stcmd);
147fe1a5d1cSSeigo Tanimura 	}
148fe1a5d1cSSeigo Tanimura 
149fe1a5d1cSSeigo Tanimura 	/* Allocate the resources. */
150fe1a5d1cSSeigo Tanimura 	resp = &scp->res;
151fe1a5d1cSSeigo Tanimura 	resp->io_rid = CS461x_IO_OFFSET;
152fe1a5d1cSSeigo Tanimura 	resp->io = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->io_rid, 0, ~0, CS461x_IO_SIZE, RF_ACTIVE);
153fe1a5d1cSSeigo Tanimura 	if (resp->io == NULL)
154fe1a5d1cSSeigo Tanimura 		return (ENXIO);
155fe1a5d1cSSeigo Tanimura 	resp->mem_rid = CS461x_MEM_OFFSET;
156fe1a5d1cSSeigo Tanimura 	resp->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->mem_rid, 0, ~0, CS461x_MEM_SIZE, RF_ACTIVE);
157fe1a5d1cSSeigo Tanimura 	if (resp->mem == NULL) {
158fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
159fe1a5d1cSSeigo Tanimura 		return (ENXIO);
160fe1a5d1cSSeigo Tanimura 	}
161fe1a5d1cSSeigo Tanimura 	resp->irq_rid = 0;
162fe1a5d1cSSeigo Tanimura 	resp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &resp->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
163fe1a5d1cSSeigo Tanimura 	if (resp->irq == NULL) {
164fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
165fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
166fe1a5d1cSSeigo Tanimura 		return (ENXIO);
167fe1a5d1cSSeigo Tanimura 	}
168fe1a5d1cSSeigo Tanimura 
169f259d7eeSSeigo Tanimura 	/* Enable interrupt. */
170f259d7eeSSeigo Tanimura 	if (bus_setup_intr(dev, resp->irq, INTR_TYPE_TTY, csa_intr, scp, &scp->ih)) {
171f259d7eeSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
172f259d7eeSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
173f259d7eeSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
174f259d7eeSSeigo Tanimura 		return (ENXIO);
175f259d7eeSSeigo Tanimura 	}
176f259d7eeSSeigo Tanimura 	if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
177f259d7eeSSeigo Tanimura 		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
178f259d7eeSSeigo Tanimura 
179fe1a5d1cSSeigo Tanimura 	/* Initialize the chip. */
180fe1a5d1cSSeigo Tanimura 	if (csa_initialize(scp)) {
181fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
182fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
183fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
184fe1a5d1cSSeigo Tanimura 		return (ENXIO);
185fe1a5d1cSSeigo Tanimura 	}
186fe1a5d1cSSeigo Tanimura 
187fe1a5d1cSSeigo Tanimura 	/* Reset the Processor. */
188fe1a5d1cSSeigo Tanimura 	csa_resetdsp(resp);
189fe1a5d1cSSeigo Tanimura 
190fe1a5d1cSSeigo Tanimura 	/* Download the Processor Image to the processor. */
191fe1a5d1cSSeigo Tanimura 	if (csa_downloadimage(resp)) {
192fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
193fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
194fe1a5d1cSSeigo Tanimura 		bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
195fe1a5d1cSSeigo Tanimura 		return (ENXIO);
196fe1a5d1cSSeigo Tanimura 	}
197fe1a5d1cSSeigo Tanimura 
198f259d7eeSSeigo Tanimura 	/* Attach the children. */
199f259d7eeSSeigo Tanimura 
200f259d7eeSSeigo Tanimura 	/* PCM Audio */
201f259d7eeSSeigo Tanimura 	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
202f259d7eeSSeigo Tanimura 	if (func == NULL)
203f259d7eeSSeigo Tanimura 		return (ENOMEM);
204f259d7eeSSeigo Tanimura 	bzero(func, sizeof(*func));
205f259d7eeSSeigo Tanimura 	func->varinfo = &scp->binfo;
206f259d7eeSSeigo Tanimura 	func->func = SCF_PCM;
207f259d7eeSSeigo Tanimura 	scp->pcm = device_add_child(dev, "pcm", -1);
208f259d7eeSSeigo Tanimura 	device_set_ivars(scp->pcm, func);
209f259d7eeSSeigo Tanimura 
210f259d7eeSSeigo Tanimura #if notyet
211f259d7eeSSeigo Tanimura 	/* Midi Interface */
212f259d7eeSSeigo Tanimura 	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
213f259d7eeSSeigo Tanimura 	if (func == NULL)
214f259d7eeSSeigo Tanimura 		return (ENOMEM);
215f259d7eeSSeigo Tanimura 	bzero(func, sizeof(*func));
216f259d7eeSSeigo Tanimura 	func->varinfo = &scp->binfo;
217f259d7eeSSeigo Tanimura 	func->func = SCF_MIDI;
218f259d7eeSSeigo Tanimura 	scp->midi = device_add_child(dev, "midi", -1);
219f259d7eeSSeigo Tanimura 	device_set_ivars(scp->midi, func);
220f259d7eeSSeigo Tanimura #endif /* notyet */
221f259d7eeSSeigo Tanimura 
222fe1a5d1cSSeigo Tanimura 	bus_generic_attach(dev);
223fe1a5d1cSSeigo Tanimura 
224fe1a5d1cSSeigo Tanimura 	return (0);
225fe1a5d1cSSeigo Tanimura }
226fe1a5d1cSSeigo Tanimura #endif /* NPCI > 0 */
227fe1a5d1cSSeigo Tanimura 
228fe1a5d1cSSeigo Tanimura static struct resource *
229fe1a5d1cSSeigo Tanimura csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
230fe1a5d1cSSeigo Tanimura 		      u_long start, u_long end, u_long count, u_int flags)
231fe1a5d1cSSeigo Tanimura {
232fe1a5d1cSSeigo Tanimura 	sc_p scp;
233fe1a5d1cSSeigo Tanimura 	csa_res *resp;
234fe1a5d1cSSeigo Tanimura 	struct resource *res;
235fe1a5d1cSSeigo Tanimura 
236fe1a5d1cSSeigo Tanimura 	scp = device_get_softc(bus);
237fe1a5d1cSSeigo Tanimura 	resp = &scp->res;
238fe1a5d1cSSeigo Tanimura 	switch (type) {
239fe1a5d1cSSeigo Tanimura 	case SYS_RES_IRQ:
240fe1a5d1cSSeigo Tanimura 		if (*rid != 0)
241fe1a5d1cSSeigo Tanimura 			return (NULL);
242fe1a5d1cSSeigo Tanimura 		res = resp->irq;
243fe1a5d1cSSeigo Tanimura 		break;
244fe1a5d1cSSeigo Tanimura 	case SYS_RES_MEMORY:
245fe1a5d1cSSeigo Tanimura 		switch (*rid) {
246fe1a5d1cSSeigo Tanimura 		case CS461x_IO_OFFSET:
247fe1a5d1cSSeigo Tanimura 			res = resp->io;
248fe1a5d1cSSeigo Tanimura 			break;
249fe1a5d1cSSeigo Tanimura 		case CS461x_MEM_OFFSET:
250fe1a5d1cSSeigo Tanimura 			res = resp->mem;
251fe1a5d1cSSeigo Tanimura 			break;
252fe1a5d1cSSeigo Tanimura 		default:
253fe1a5d1cSSeigo Tanimura 			return (NULL);
254fe1a5d1cSSeigo Tanimura 		}
255fe1a5d1cSSeigo Tanimura 		break;
256fe1a5d1cSSeigo Tanimura 	default:
257fe1a5d1cSSeigo Tanimura 		return (NULL);
258fe1a5d1cSSeigo Tanimura 	}
259fe1a5d1cSSeigo Tanimura 
260fe1a5d1cSSeigo Tanimura 	return res;
261fe1a5d1cSSeigo Tanimura }
262fe1a5d1cSSeigo Tanimura 
263fe1a5d1cSSeigo Tanimura static int
264fe1a5d1cSSeigo Tanimura csa_release_resource(device_t bus, device_t child, int type, int rid,
265fe1a5d1cSSeigo Tanimura 			struct resource *r)
266fe1a5d1cSSeigo Tanimura {
267fe1a5d1cSSeigo Tanimura 	return (0);
268fe1a5d1cSSeigo Tanimura }
269fe1a5d1cSSeigo Tanimura 
270f259d7eeSSeigo Tanimura /*
271f259d7eeSSeigo Tanimura  * The following three functions deal with interrupt handling.
272f259d7eeSSeigo Tanimura  * An interrupt is primarily handled by the bridge driver.
273f259d7eeSSeigo Tanimura  * The bridge driver then determines the child devices to pass
274f259d7eeSSeigo Tanimura  * the interrupt. Certain information of the device can be read
275f259d7eeSSeigo Tanimura  * only once(eg the value of HISR). The bridge driver is responsible
276f259d7eeSSeigo Tanimura  * to pass such the information to the children.
277f259d7eeSSeigo Tanimura  */
278f259d7eeSSeigo Tanimura 
279f259d7eeSSeigo Tanimura static int
280f259d7eeSSeigo Tanimura csa_setup_intr(device_t bus, device_t child,
281f259d7eeSSeigo Tanimura 	       struct resource *irq, int flags,
282f259d7eeSSeigo Tanimura 	       driver_intr_t *intr, void *arg, void **cookiep)
283f259d7eeSSeigo Tanimura {
284f259d7eeSSeigo Tanimura 	sc_p scp;
285f259d7eeSSeigo Tanimura 	csa_res *resp;
286f259d7eeSSeigo Tanimura 	struct sndcard_func *func;
287f259d7eeSSeigo Tanimura 
288f259d7eeSSeigo Tanimura 	scp = device_get_softc(bus);
289f259d7eeSSeigo Tanimura 	resp = &scp->res;
290f259d7eeSSeigo Tanimura 
291f259d7eeSSeigo Tanimura 	/*
292f259d7eeSSeigo Tanimura 	 * Look at the function code of the child to determine
293f259d7eeSSeigo Tanimura 	 * the appropriate hander for it.
294f259d7eeSSeigo Tanimura 	 */
295f259d7eeSSeigo Tanimura 	func = device_get_ivars(child);
296f259d7eeSSeigo Tanimura 	if (func == NULL || irq != resp->irq)
297f259d7eeSSeigo Tanimura 		return (EINVAL);
298f259d7eeSSeigo Tanimura 
299f259d7eeSSeigo Tanimura 	switch (func->func) {
300f259d7eeSSeigo Tanimura 	case SCF_PCM:
301f259d7eeSSeigo Tanimura 		scp->pcmintr = intr;
302f259d7eeSSeigo Tanimura 		scp->pcmintr_arg = arg;
303f259d7eeSSeigo Tanimura 		break;
304f259d7eeSSeigo Tanimura 
305f259d7eeSSeigo Tanimura #if notyet
306f259d7eeSSeigo Tanimura 	case SCF_MIDI:
307f259d7eeSSeigo Tanimura 		scp->midiintr = intr;
308f259d7eeSSeigo Tanimura 		scp->midiintr_arg = arg;
309f259d7eeSSeigo Tanimura 		break;
310f259d7eeSSeigo Tanimura #endif /* notyet */
311f259d7eeSSeigo Tanimura 
312f259d7eeSSeigo Tanimura 	default:
313f259d7eeSSeigo Tanimura 		return (EINVAL);
314f259d7eeSSeigo Tanimura 	}
315f259d7eeSSeigo Tanimura 	*cookiep = scp;
316f259d7eeSSeigo Tanimura 	if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
317f259d7eeSSeigo Tanimura 		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
318f259d7eeSSeigo Tanimura 
319f259d7eeSSeigo Tanimura 	return (0);
320f259d7eeSSeigo Tanimura }
321f259d7eeSSeigo Tanimura 
322f259d7eeSSeigo Tanimura static int
323f259d7eeSSeigo Tanimura csa_teardown_intr(device_t bus, device_t child,
324f259d7eeSSeigo Tanimura 		  struct resource *irq, void *cookie)
325f259d7eeSSeigo Tanimura {
326f259d7eeSSeigo Tanimura 	sc_p scp;
327f259d7eeSSeigo Tanimura 	csa_res *resp;
328f259d7eeSSeigo Tanimura 	struct sndcard_func *func;
329f259d7eeSSeigo Tanimura 
330f259d7eeSSeigo Tanimura 	scp = device_get_softc(bus);
331f259d7eeSSeigo Tanimura 	resp = &scp->res;
332f259d7eeSSeigo Tanimura 
333f259d7eeSSeigo Tanimura 	/*
334f259d7eeSSeigo Tanimura 	 * Look at the function code of the child to determine
335f259d7eeSSeigo Tanimura 	 * the appropriate hander for it.
336f259d7eeSSeigo Tanimura 	 */
337f259d7eeSSeigo Tanimura 	func = device_get_ivars(child);
338f259d7eeSSeigo Tanimura 	if (func == NULL || irq != resp->irq || cookie != scp)
339f259d7eeSSeigo Tanimura 		return (EINVAL);
340f259d7eeSSeigo Tanimura 
341f259d7eeSSeigo Tanimura 	switch (func->func) {
342f259d7eeSSeigo Tanimura 	case SCF_PCM:
343f259d7eeSSeigo Tanimura 		scp->pcmintr = NULL;
344f259d7eeSSeigo Tanimura 		scp->pcmintr_arg = NULL;
345f259d7eeSSeigo Tanimura 		break;
346f259d7eeSSeigo Tanimura 
347f259d7eeSSeigo Tanimura #if notyet
348f259d7eeSSeigo Tanimura 	case SCF_MIDI:
349f259d7eeSSeigo Tanimura 		scp->midiintr = NULL;
350f259d7eeSSeigo Tanimura 		scp->midiintr_arg = NULL;
351f259d7eeSSeigo Tanimura 		break;
352f259d7eeSSeigo Tanimura #endif /* notyet */
353f259d7eeSSeigo Tanimura 
354f259d7eeSSeigo Tanimura 	default:
355f259d7eeSSeigo Tanimura 		return (EINVAL);
356f259d7eeSSeigo Tanimura 	}
357f259d7eeSSeigo Tanimura 
358f259d7eeSSeigo Tanimura 	return (0);
359f259d7eeSSeigo Tanimura }
360f259d7eeSSeigo Tanimura 
361f259d7eeSSeigo Tanimura /* The interrupt handler */
362f259d7eeSSeigo Tanimura static void
363f259d7eeSSeigo Tanimura csa_intr(void *arg)
364f259d7eeSSeigo Tanimura {
365f259d7eeSSeigo Tanimura 	sc_p scp = arg;
366f259d7eeSSeigo Tanimura 	csa_res *resp;
367f259d7eeSSeigo Tanimura 	u_int32_t hisr;
368f259d7eeSSeigo Tanimura 
369f259d7eeSSeigo Tanimura 	resp = &scp->res;
370f259d7eeSSeigo Tanimura 
371f259d7eeSSeigo Tanimura 	/* Is this interrupt for us? */
372f259d7eeSSeigo Tanimura 	hisr = csa_readio(resp, BA0_HISR);
373f259d7eeSSeigo Tanimura 	if ((hisr & ~HISR_INTENA) == 0) {
374f259d7eeSSeigo Tanimura 		/* Throw an eoi. */
375f259d7eeSSeigo Tanimura 		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
376f259d7eeSSeigo Tanimura 		return;
377f259d7eeSSeigo Tanimura 	}
378f259d7eeSSeigo Tanimura 
379f259d7eeSSeigo Tanimura 	/*
380f259d7eeSSeigo Tanimura 	 * Pass the value of HISR via struct csa_bridgeinfo.
381f259d7eeSSeigo Tanimura 	 * The children get access through their ivars.
382f259d7eeSSeigo Tanimura 	 */
383f259d7eeSSeigo Tanimura 	scp->binfo.hisr = hisr;
384f259d7eeSSeigo Tanimura 
385f259d7eeSSeigo Tanimura 	/* Invoke the handlers of the children. */
386f259d7eeSSeigo Tanimura 	if ((hisr & (HISR_VC0 | HISR_VC1)) != 0 && scp->pcmintr != NULL)
387f259d7eeSSeigo Tanimura 		scp->pcmintr(scp->pcmintr_arg);
388f259d7eeSSeigo Tanimura #if notyet
389f259d7eeSSeigo Tanimura 	if ((hisr & HISR_MIDI) != 0 && scp->midiintr != NULL)
390f259d7eeSSeigo Tanimura 		scp->midiintr(scp->midiintr_arg);
391f259d7eeSSeigo Tanimura #endif /* notyet */
392f259d7eeSSeigo Tanimura 
393f259d7eeSSeigo Tanimura 	/* Throw an eoi. */
394f259d7eeSSeigo Tanimura 	csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
395f259d7eeSSeigo Tanimura }
396f259d7eeSSeigo Tanimura 
397fe1a5d1cSSeigo Tanimura static int
398fe1a5d1cSSeigo Tanimura csa_initialize(sc_p scp)
399fe1a5d1cSSeigo Tanimura {
400fe1a5d1cSSeigo Tanimura 	int i;
401fe1a5d1cSSeigo Tanimura 	u_int32_t acsts, acisv;
402fe1a5d1cSSeigo Tanimura 	csa_res *resp;
403fe1a5d1cSSeigo Tanimura 
404fe1a5d1cSSeigo Tanimura 	resp = &scp->res;
405fe1a5d1cSSeigo Tanimura 
406fe1a5d1cSSeigo Tanimura 	/*
407fe1a5d1cSSeigo Tanimura 	 * First, blast the clock control register to zero so that the PLL starts
408fe1a5d1cSSeigo Tanimura 	 * out in a known state, and blast the master serial port control register
409fe1a5d1cSSeigo Tanimura 	 * to zero so that the serial ports also start out in a known state.
410fe1a5d1cSSeigo Tanimura 	 */
411fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, 0);
412fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERMC1, 0);
413fe1a5d1cSSeigo Tanimura 
414fe1a5d1cSSeigo Tanimura 	/*
415fe1a5d1cSSeigo Tanimura 	 * If we are in AC97 mode, then we must set the part to a host controlled
416fe1a5d1cSSeigo Tanimura 	 * AC-link.  Otherwise, we won't be able to bring up the link.
417fe1a5d1cSSeigo Tanimura 	 */
418fe1a5d1cSSeigo Tanimura #if 1
419fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_1_03); /* 1.03 codec */
420fe1a5d1cSSeigo Tanimura #else
421fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERACC, SERACC_HSP | SERACC_CODEC_TYPE_2_0); /* 2.0 codec */
422fe1a5d1cSSeigo Tanimura #endif /* 1 */
423fe1a5d1cSSeigo Tanimura 
424fe1a5d1cSSeigo Tanimura 	/*
425fe1a5d1cSSeigo Tanimura 	 * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
426fe1a5d1cSSeigo Tanimura 	 * spec) and then drive it high.  This is done for non AC97 modes since
427fe1a5d1cSSeigo Tanimura 	 * there might be logic external to the CS461x that uses the ARST# line
428fe1a5d1cSSeigo Tanimura 	 * for a reset.
429fe1a5d1cSSeigo Tanimura 	 */
430fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, 0);
431f7e00c54SSeigo Tanimura 	DELAY(100);
432fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_RSTN);
433fe1a5d1cSSeigo Tanimura 
434fe1a5d1cSSeigo Tanimura 	/*
435fe1a5d1cSSeigo Tanimura 	 * The first thing we do here is to enable sync generation.  As soon
436fe1a5d1cSSeigo Tanimura 	 * as we start receiving bit clock, we'll start producing the SYNC
437fe1a5d1cSSeigo Tanimura 	 * signal.
438fe1a5d1cSSeigo Tanimura 	 */
439fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
440fe1a5d1cSSeigo Tanimura 
441fe1a5d1cSSeigo Tanimura 	/*
442fe1a5d1cSSeigo Tanimura 	 * Now wait for a short while to allow the AC97 part to start
443fe1a5d1cSSeigo Tanimura 	 * generating bit clock (so we don't try to start the PLL without an
444fe1a5d1cSSeigo Tanimura 	 * input clock).
445fe1a5d1cSSeigo Tanimura 	 */
446fe1a5d1cSSeigo Tanimura 	DELAY(50000);
447fe1a5d1cSSeigo Tanimura 
448fe1a5d1cSSeigo Tanimura 	/*
449fe1a5d1cSSeigo Tanimura 	 * Set the serial port timing configuration, so that
450fe1a5d1cSSeigo Tanimura 	 * the clock control circuit gets its clock from the correct place.
451fe1a5d1cSSeigo Tanimura 	 */
452fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97);
453fe1a5d1cSSeigo Tanimura 
454fe1a5d1cSSeigo Tanimura 	/*
455fe1a5d1cSSeigo Tanimura 	 * Write the selected clock control setup to the hardware.  Do not turn on
456fe1a5d1cSSeigo Tanimura 	 * SWCE yet (if requested), so that the devices clocked by the output of
457fe1a5d1cSSeigo Tanimura 	 * PLL are not clocked until the PLL is stable.
458fe1a5d1cSSeigo Tanimura 	 */
459fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
460fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_PLLM, 0x3a);
461fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR2, CLKCR2_PDIVS_8);
462fe1a5d1cSSeigo Tanimura 
463fe1a5d1cSSeigo Tanimura 	/*
464fe1a5d1cSSeigo Tanimura 	 * Power up the PLL.
465fe1a5d1cSSeigo Tanimura 	 */
466fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, CLKCR1_PLLP);
467fe1a5d1cSSeigo Tanimura 
468fe1a5d1cSSeigo Tanimura 	/*
469fe1a5d1cSSeigo Tanimura 	 * Wait until the PLL has stabilized.
470fe1a5d1cSSeigo Tanimura 	 */
471fe1a5d1cSSeigo Tanimura 	DELAY(50000);
472fe1a5d1cSSeigo Tanimura 
473fe1a5d1cSSeigo Tanimura 	/*
474fe1a5d1cSSeigo Tanimura 	 * Turn on clocking of the core so that we can setup the serial ports.
475fe1a5d1cSSeigo Tanimura 	 */
476fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, csa_readio(resp, BA0_CLKCR1) | CLKCR1_SWCE);
477fe1a5d1cSSeigo Tanimura 
478fe1a5d1cSSeigo Tanimura 	/*
479fe1a5d1cSSeigo Tanimura 	 * Fill the serial port FIFOs with silence.
480fe1a5d1cSSeigo Tanimura 	 */
481fe1a5d1cSSeigo Tanimura 	csa_clearserialfifos(resp);
482fe1a5d1cSSeigo Tanimura 
483fe1a5d1cSSeigo Tanimura 	/*
484fe1a5d1cSSeigo Tanimura 	 * Set the serial port FIFO pointer to the first sample in the FIFO.
485fe1a5d1cSSeigo Tanimura 	 */
486fe1a5d1cSSeigo Tanimura #if notdef
487fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERBSP, 0);
488fe1a5d1cSSeigo Tanimura #endif /* notdef */
489fe1a5d1cSSeigo Tanimura 
490fe1a5d1cSSeigo Tanimura 	/*
491fe1a5d1cSSeigo Tanimura 	 *  Write the serial port configuration to the part.  The master
492fe1a5d1cSSeigo Tanimura 	 *  enable bit is not set until all other values have been written.
493fe1a5d1cSSeigo Tanimura 	 */
494fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
495fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
496fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
497fe1a5d1cSSeigo Tanimura 
498fe1a5d1cSSeigo Tanimura 	/*
499fe1a5d1cSSeigo Tanimura 	 * Wait for the codec ready signal from the AC97 codec.
500fe1a5d1cSSeigo Tanimura 	 */
501fe1a5d1cSSeigo Tanimura 	acsts = 0;
502fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 1000 ; i++) {
503fe1a5d1cSSeigo Tanimura 		/*
504fe1a5d1cSSeigo Tanimura 		 * First, lets wait a short while to let things settle out a bit,
505fe1a5d1cSSeigo Tanimura 		 * and to prevent retrying the read too quickly.
506fe1a5d1cSSeigo Tanimura 		 */
507f7e00c54SSeigo Tanimura 		DELAY(125);
508fe1a5d1cSSeigo Tanimura 
509fe1a5d1cSSeigo Tanimura 		/*
510fe1a5d1cSSeigo Tanimura 		 * Read the AC97 status register to see if we've seen a CODEC READY
511fe1a5d1cSSeigo Tanimura 		 * signal from the AC97 codec.
512fe1a5d1cSSeigo Tanimura 		 */
513fe1a5d1cSSeigo Tanimura 		acsts = csa_readio(resp, BA0_ACSTS);
514fe1a5d1cSSeigo Tanimura 		if ((acsts & ACSTS_CRDY) != 0)
515fe1a5d1cSSeigo Tanimura 			break;
516fe1a5d1cSSeigo Tanimura 	}
517fe1a5d1cSSeigo Tanimura 
518fe1a5d1cSSeigo Tanimura 	/*
519fe1a5d1cSSeigo Tanimura 	 * Make sure we sampled CODEC READY.
520fe1a5d1cSSeigo Tanimura 	 */
521fe1a5d1cSSeigo Tanimura 	if ((acsts & ACSTS_CRDY) == 0)
522fe1a5d1cSSeigo Tanimura 		return (ENXIO);
523fe1a5d1cSSeigo Tanimura 
524fe1a5d1cSSeigo Tanimura 	/*
525fe1a5d1cSSeigo Tanimura 	 * Assert the vaid frame signal so that we can start sending commands
526fe1a5d1cSSeigo Tanimura 	 * to the AC97 codec.
527fe1a5d1cSSeigo Tanimura 	 */
528fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
529fe1a5d1cSSeigo Tanimura 
530fe1a5d1cSSeigo Tanimura 	/*
531fe1a5d1cSSeigo Tanimura 	 * Wait until we've sampled input slots 3 and 4 as valid, meaning that
532fe1a5d1cSSeigo Tanimura 	 * the codec is pumping ADC data across the AC-link.
533fe1a5d1cSSeigo Tanimura 	 */
534fe1a5d1cSSeigo Tanimura 	acisv = 0;
535fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 1000 ; i++) {
536fe1a5d1cSSeigo Tanimura 		/*
537fe1a5d1cSSeigo Tanimura 		 * First, lets wait a short while to let things settle out a bit,
538fe1a5d1cSSeigo Tanimura 		 * and to prevent retrying the read too quickly.
539fe1a5d1cSSeigo Tanimura 		 */
540fe1a5d1cSSeigo Tanimura #if notdef
541fe1a5d1cSSeigo Tanimura 		DELAY(10000000L); /* clw */
542fe1a5d1cSSeigo Tanimura #else
543f7e00c54SSeigo Tanimura 		DELAY(1000);
544fe1a5d1cSSeigo Tanimura #endif /* notdef */
545fe1a5d1cSSeigo Tanimura 		/*
546fe1a5d1cSSeigo Tanimura 		 * Read the input slot valid register and see if input slots 3 and
547fe1a5d1cSSeigo Tanimura 		 * 4 are valid yet.
548fe1a5d1cSSeigo Tanimura 		 */
549fe1a5d1cSSeigo Tanimura 		acisv = csa_readio(resp, BA0_ACISV);
550fe1a5d1cSSeigo Tanimura 		if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
551fe1a5d1cSSeigo Tanimura 			break;
552fe1a5d1cSSeigo Tanimura 	}
553fe1a5d1cSSeigo Tanimura 	/*
554fe1a5d1cSSeigo Tanimura 	 * Make sure we sampled valid input slots 3 and 4.  If not, then return
555fe1a5d1cSSeigo Tanimura 	 * an error.
556fe1a5d1cSSeigo Tanimura 	 */
557fe1a5d1cSSeigo Tanimura 	if ((acisv & (ACISV_ISV3 | ACISV_ISV4)) != (ACISV_ISV3 | ACISV_ISV4))
558fe1a5d1cSSeigo Tanimura 		return (ENXIO);
559fe1a5d1cSSeigo Tanimura 
560fe1a5d1cSSeigo Tanimura 	/*
561fe1a5d1cSSeigo Tanimura 	 * Now, assert valid frame and the slot 3 and 4 valid bits.  This will
562fe1a5d1cSSeigo Tanimura 	 * commense the transfer of digital audio data to the AC97 codec.
563fe1a5d1cSSeigo Tanimura 	 */
564fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
565fe1a5d1cSSeigo Tanimura 
566fe1a5d1cSSeigo Tanimura 	/*
567fe1a5d1cSSeigo Tanimura 	 * Power down the DAC and ADC.  We will power them up (if) when we need
568fe1a5d1cSSeigo Tanimura 	 * them.
569fe1a5d1cSSeigo Tanimura 	 */
570fe1a5d1cSSeigo Tanimura #if notdef
571fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_AC97_POWERDOWN, 0x300);
572fe1a5d1cSSeigo Tanimura #endif /* notdef */
573fe1a5d1cSSeigo Tanimura 
574fe1a5d1cSSeigo Tanimura 	/*
575fe1a5d1cSSeigo Tanimura 	 * Turn off the Processor by turning off the software clock enable flag in
576fe1a5d1cSSeigo Tanimura 	 * the clock control register.
577fe1a5d1cSSeigo Tanimura 	 */
578fe1a5d1cSSeigo Tanimura #if notdef
579fe1a5d1cSSeigo Tanimura 	clkcr1 = csa_readio(resp, BA0_CLKCR1) & ~CLKCR1_SWCE;
580fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_CLKCR1, clkcr1);
581fe1a5d1cSSeigo Tanimura #endif /* notdef */
582fe1a5d1cSSeigo Tanimura 
583fe1a5d1cSSeigo Tanimura 	/*
584fe1a5d1cSSeigo Tanimura 	 * Enable interrupts on the part.
585fe1a5d1cSSeigo Tanimura 	 */
586fe1a5d1cSSeigo Tanimura #if notdef
587fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
588fe1a5d1cSSeigo Tanimura #endif /* notdef */
589fe1a5d1cSSeigo Tanimura 
590fe1a5d1cSSeigo Tanimura 	return (0);
591fe1a5d1cSSeigo Tanimura }
592fe1a5d1cSSeigo Tanimura 
593f259d7eeSSeigo Tanimura void
594fe1a5d1cSSeigo Tanimura csa_clearserialfifos(csa_res *resp)
595fe1a5d1cSSeigo Tanimura {
596fe1a5d1cSSeigo Tanimura 	int i, j, pwr;
597fe1a5d1cSSeigo Tanimura 	u_int8_t clkcr1, serbst;
598fe1a5d1cSSeigo Tanimura 
599fe1a5d1cSSeigo Tanimura 	/*
600fe1a5d1cSSeigo Tanimura 	 * See if the devices are powered down.  If so, we must power them up first
601fe1a5d1cSSeigo Tanimura 	 * or they will not respond.
602fe1a5d1cSSeigo Tanimura 	 */
603fe1a5d1cSSeigo Tanimura 	pwr = 1;
604fe1a5d1cSSeigo Tanimura 	clkcr1 = csa_readio(resp, BA0_CLKCR1);
605fe1a5d1cSSeigo Tanimura 	if ((clkcr1 & CLKCR1_SWCE) == 0) {
606fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_CLKCR1, clkcr1 | CLKCR1_SWCE);
607fe1a5d1cSSeigo Tanimura 		pwr = 0;
608fe1a5d1cSSeigo Tanimura 	}
609fe1a5d1cSSeigo Tanimura 
610fe1a5d1cSSeigo Tanimura 	/*
611fe1a5d1cSSeigo Tanimura 	 * We want to clear out the serial port FIFOs so we don't end up playing
612fe1a5d1cSSeigo Tanimura 	 * whatever random garbage happens to be in them.  We fill the sample FIFOs
613fe1a5d1cSSeigo Tanimura 	 * with zero (silence).
614fe1a5d1cSSeigo Tanimura 	 */
615fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_SERBWP, 0);
616fe1a5d1cSSeigo Tanimura 
617fe1a5d1cSSeigo Tanimura 	/* Fill all 256 sample FIFO locations. */
618fe1a5d1cSSeigo Tanimura 	serbst = 0;
619fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 256 ; i++) {
620fe1a5d1cSSeigo Tanimura 		/* Make sure the previous FIFO write operation has completed. */
621fe1a5d1cSSeigo Tanimura 		for (j = 0 ; j < 5 ; j++) {
622f7e00c54SSeigo Tanimura 			DELAY(100);
623fe1a5d1cSSeigo Tanimura 			serbst = csa_readio(resp, BA0_SERBST);
624fe1a5d1cSSeigo Tanimura 			if ((serbst & SERBST_WBSY) == 0)
625fe1a5d1cSSeigo Tanimura 				break;
626fe1a5d1cSSeigo Tanimura 		}
627fe1a5d1cSSeigo Tanimura 		if ((serbst & SERBST_WBSY) != 0) {
628fe1a5d1cSSeigo Tanimura 			if (!pwr)
629fe1a5d1cSSeigo Tanimura 				csa_writeio(resp, BA0_CLKCR1, clkcr1);
630fe1a5d1cSSeigo Tanimura 		}
631fe1a5d1cSSeigo Tanimura 		/* Write the serial port FIFO index. */
632fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_SERBAD, i);
633fe1a5d1cSSeigo Tanimura 		/* Tell the serial port to load the new value into the FIFO location. */
634fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_SERBCM, SERBCM_WRC);
635fe1a5d1cSSeigo Tanimura 	}
636fe1a5d1cSSeigo Tanimura 	/*
637fe1a5d1cSSeigo Tanimura 	 *  Now, if we powered up the devices, then power them back down again.
638fe1a5d1cSSeigo Tanimura 	 *  This is kinda ugly, but should never happen.
639fe1a5d1cSSeigo Tanimura 	 */
640fe1a5d1cSSeigo Tanimura 	if (!pwr)
641fe1a5d1cSSeigo Tanimura 		csa_writeio(resp, BA0_CLKCR1, clkcr1);
642fe1a5d1cSSeigo Tanimura }
643fe1a5d1cSSeigo Tanimura 
644fe1a5d1cSSeigo Tanimura static void
645fe1a5d1cSSeigo Tanimura csa_resetdsp(csa_res *resp)
646fe1a5d1cSSeigo Tanimura {
647fe1a5d1cSSeigo Tanimura 	int i;
648fe1a5d1cSSeigo Tanimura 
649fe1a5d1cSSeigo Tanimura 	/*
650fe1a5d1cSSeigo Tanimura 	 * Write the reset bit of the SP control register.
651fe1a5d1cSSeigo Tanimura 	 */
652fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_SPCR, SPCR_RSTSP);
653fe1a5d1cSSeigo Tanimura 
654fe1a5d1cSSeigo Tanimura 	/*
655fe1a5d1cSSeigo Tanimura 	 * Write the control register.
656fe1a5d1cSSeigo Tanimura 	 */
657fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_SPCR, SPCR_DRQEN);
658fe1a5d1cSSeigo Tanimura 
659fe1a5d1cSSeigo Tanimura 	/*
660fe1a5d1cSSeigo Tanimura 	 * Clear the trap registers.
661fe1a5d1cSSeigo Tanimura 	 */
662fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 8 ; i++) {
663fe1a5d1cSSeigo Tanimura 		csa_writemem(resp, BA1_DREG, DREG_REGID_TRAP_SELECT + i);
664fe1a5d1cSSeigo Tanimura 		csa_writemem(resp, BA1_TWPR, 0xffff);
665fe1a5d1cSSeigo Tanimura 	}
666fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_DREG, 0);
667fe1a5d1cSSeigo Tanimura 
668fe1a5d1cSSeigo Tanimura 	/*
669fe1a5d1cSSeigo Tanimura 	 * Set the frame timer to reflect the number of cycles per frame.
670fe1a5d1cSSeigo Tanimura 	 */
671fe1a5d1cSSeigo Tanimura 	csa_writemem(resp, BA1_FRMT, 0xadf);
672fe1a5d1cSSeigo Tanimura }
673fe1a5d1cSSeigo Tanimura 
674fe1a5d1cSSeigo Tanimura static int
675fe1a5d1cSSeigo Tanimura csa_downloadimage(csa_res *resp)
676fe1a5d1cSSeigo Tanimura {
677fe1a5d1cSSeigo Tanimura 	int ret;
678fe1a5d1cSSeigo Tanimura 	u_long ul, offset;
679fe1a5d1cSSeigo Tanimura 
680fe1a5d1cSSeigo Tanimura 	for (ul = 0, offset = 0 ; ul < INKY_MEMORY_COUNT ; ul++) {
681fe1a5d1cSSeigo Tanimura 		/*
682fe1a5d1cSSeigo Tanimura 		 * DMA this block from host memory to the appropriate
683fe1a5d1cSSeigo Tanimura 		 * memory on the CSDevice.
684fe1a5d1cSSeigo Tanimura 		 */
685fe1a5d1cSSeigo Tanimura 		ret = csa_transferimage(
686fe1a5d1cSSeigo Tanimura 			resp,
687fe1a5d1cSSeigo Tanimura 			BA1Struct.BA1Array + offset,
688fe1a5d1cSSeigo Tanimura 			BA1Struct.MemoryStat[ul].ulDestByteOffset,
689fe1a5d1cSSeigo Tanimura 			BA1Struct.MemoryStat[ul].ulSourceByteSize);
690fe1a5d1cSSeigo Tanimura 		if (ret)
691fe1a5d1cSSeigo Tanimura 			return (ret);
692fe1a5d1cSSeigo Tanimura 		offset += BA1Struct.MemoryStat[ul].ulSourceByteSize >> 2;
693fe1a5d1cSSeigo Tanimura 	}
694fe1a5d1cSSeigo Tanimura 
695fe1a5d1cSSeigo Tanimura 	return (0);
696fe1a5d1cSSeigo Tanimura }
697fe1a5d1cSSeigo Tanimura 
698fe1a5d1cSSeigo Tanimura static int
699fe1a5d1cSSeigo Tanimura csa_transferimage(csa_res *resp, u_long *src, u_long dest, u_long len)
700fe1a5d1cSSeigo Tanimura {
701fe1a5d1cSSeigo Tanimura 	u_long ul;
702fe1a5d1cSSeigo Tanimura 
703fe1a5d1cSSeigo Tanimura 	/*
704fe1a5d1cSSeigo Tanimura 	 * We do not allow DMAs from host memory to host memory (although the DMA
705fe1a5d1cSSeigo Tanimura 	 * can do it) and we do not allow DMAs which are not a multiple of 4 bytes
706fe1a5d1cSSeigo Tanimura 	 * in size (because that DMA can not do that).  Return an error if either
707fe1a5d1cSSeigo Tanimura 	 * of these conditions exist.
708fe1a5d1cSSeigo Tanimura 	 */
709fe1a5d1cSSeigo Tanimura 	if ((len & 0x3) != 0)
710fe1a5d1cSSeigo Tanimura 		return (EINVAL);
711fe1a5d1cSSeigo Tanimura 
712fe1a5d1cSSeigo Tanimura 	/* Check the destination address that it is a multiple of 4 */
713fe1a5d1cSSeigo Tanimura 	if ((dest & 0x3) != 0)
714fe1a5d1cSSeigo Tanimura 		return (EINVAL);
715fe1a5d1cSSeigo Tanimura 
716fe1a5d1cSSeigo Tanimura 	/* Write the buffer out. */
717fe1a5d1cSSeigo Tanimura 	for (ul = 0 ; ul < len ; ul += 4)
718fe1a5d1cSSeigo Tanimura 		csa_writemem(resp, dest + ul, src[ul >> 2]);
719fe1a5d1cSSeigo Tanimura 
720fe1a5d1cSSeigo Tanimura 	return (0);
721fe1a5d1cSSeigo Tanimura }
722fe1a5d1cSSeigo Tanimura 
723fe1a5d1cSSeigo Tanimura int
724fe1a5d1cSSeigo Tanimura csa_readcodec(csa_res *resp, u_long offset, u_int32_t *data)
725fe1a5d1cSSeigo Tanimura {
726fe1a5d1cSSeigo Tanimura 	int i;
727fe1a5d1cSSeigo Tanimura 	u_int32_t acsda, acctl, acsts;
728fe1a5d1cSSeigo Tanimura 
729fe1a5d1cSSeigo Tanimura 	/*
730fe1a5d1cSSeigo Tanimura 	 * Make sure that there is not data sitting around from a previous
731fe1a5d1cSSeigo Tanimura 	 * uncompleted access. ACSDA = Status Data Register = 47Ch
732fe1a5d1cSSeigo Tanimura 	 */
733fe1a5d1cSSeigo Tanimura 	acsda = csa_readio(resp, BA0_ACSDA);
734fe1a5d1cSSeigo Tanimura 
735fe1a5d1cSSeigo Tanimura 	/*
736fe1a5d1cSSeigo Tanimura 	 * Setup the AC97 control registers on the CS461x to send the
737fe1a5d1cSSeigo Tanimura 	 * appropriate command to the AC97 to perform the read.
738fe1a5d1cSSeigo Tanimura 	 * ACCAD = Command Address Register = 46Ch
739fe1a5d1cSSeigo Tanimura 	 * ACCDA = Command Data Register = 470h
740fe1a5d1cSSeigo Tanimura 	 * ACCTL = Control Register = 460h
741fe1a5d1cSSeigo Tanimura 	 * set DCV - will clear when process completed
742fe1a5d1cSSeigo Tanimura 	 * set CRW - Read command
743fe1a5d1cSSeigo Tanimura 	 * set VFRM - valid frame enabled
744fe1a5d1cSSeigo Tanimura 	 * set ESYN - ASYNC generation enabled
745fe1a5d1cSSeigo Tanimura 	 * set RSTN - ARST# inactive, AC97 codec not reset
746fe1a5d1cSSeigo Tanimura 	 */
747fe1a5d1cSSeigo Tanimura 
748fe1a5d1cSSeigo Tanimura 	/*
749fe1a5d1cSSeigo Tanimura 	 * Get the actual AC97 register from the offset
750fe1a5d1cSSeigo Tanimura 	 */
751fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
752fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCDA, 0);
753fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
754fe1a5d1cSSeigo Tanimura 
755fe1a5d1cSSeigo Tanimura 	/*
756fe1a5d1cSSeigo Tanimura 	 * Wait for the read to occur.
757fe1a5d1cSSeigo Tanimura 	 */
758fe1a5d1cSSeigo Tanimura 	acctl = 0;
759fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 10 ; i++) {
760fe1a5d1cSSeigo Tanimura 		/*
761fe1a5d1cSSeigo Tanimura 		 * First, we want to wait for a short time.
762fe1a5d1cSSeigo Tanimura 		 */
763fe1a5d1cSSeigo Tanimura 		DELAY(25);
764fe1a5d1cSSeigo Tanimura 
765fe1a5d1cSSeigo Tanimura 		/*
766fe1a5d1cSSeigo Tanimura 		 * Now, check to see if the read has completed.
767fe1a5d1cSSeigo Tanimura 		 * ACCTL = 460h, DCV should be reset by now and 460h = 17h
768fe1a5d1cSSeigo Tanimura 		 */
769fe1a5d1cSSeigo Tanimura 		acctl = csa_readio(resp, BA0_ACCTL);
770fe1a5d1cSSeigo Tanimura 		if ((acctl & ACCTL_DCV) == 0)
771fe1a5d1cSSeigo Tanimura 			break;
772fe1a5d1cSSeigo Tanimura 	}
773fe1a5d1cSSeigo Tanimura 
774fe1a5d1cSSeigo Tanimura 	/*
775fe1a5d1cSSeigo Tanimura 	 * Make sure the read completed.
776fe1a5d1cSSeigo Tanimura 	 */
777fe1a5d1cSSeigo Tanimura 	if ((acctl & ACCTL_DCV) != 0)
778fe1a5d1cSSeigo Tanimura 		return (EAGAIN);
779fe1a5d1cSSeigo Tanimura 
780fe1a5d1cSSeigo Tanimura 	/*
781fe1a5d1cSSeigo Tanimura 	 * Wait for the valid status bit to go active.
782fe1a5d1cSSeigo Tanimura 	 */
783fe1a5d1cSSeigo Tanimura 	acsts = 0;
784fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 10 ; i++) {
785fe1a5d1cSSeigo Tanimura 		/*
786fe1a5d1cSSeigo Tanimura 		 * Read the AC97 status register.
787fe1a5d1cSSeigo Tanimura 		 * ACSTS = Status Register = 464h
788fe1a5d1cSSeigo Tanimura 		 */
789fe1a5d1cSSeigo Tanimura 		acsts = csa_readio(resp, BA0_ACSTS);
790fe1a5d1cSSeigo Tanimura 		/*
791fe1a5d1cSSeigo Tanimura 		 * See if we have valid status.
792fe1a5d1cSSeigo Tanimura 		 * VSTS - Valid Status
793fe1a5d1cSSeigo Tanimura 		 */
794fe1a5d1cSSeigo Tanimura 		if ((acsts & ACSTS_VSTS) != 0)
795fe1a5d1cSSeigo Tanimura 			break;
796fe1a5d1cSSeigo Tanimura 		/*
797fe1a5d1cSSeigo Tanimura 		 * Wait for a short while.
798fe1a5d1cSSeigo Tanimura 		 */
799fe1a5d1cSSeigo Tanimura 		 DELAY(25);
800fe1a5d1cSSeigo Tanimura 	}
801fe1a5d1cSSeigo Tanimura 
802fe1a5d1cSSeigo Tanimura 	/*
803fe1a5d1cSSeigo Tanimura 	 * Make sure we got valid status.
804fe1a5d1cSSeigo Tanimura 	 */
805fe1a5d1cSSeigo Tanimura 	if ((acsts & ACSTS_VSTS) == 0)
806fe1a5d1cSSeigo Tanimura 		return (EAGAIN);
807fe1a5d1cSSeigo Tanimura 
808fe1a5d1cSSeigo Tanimura 	/*
809fe1a5d1cSSeigo Tanimura 	 * Read the data returned from the AC97 register.
810fe1a5d1cSSeigo Tanimura 	 * ACSDA = Status Data Register = 474h
811fe1a5d1cSSeigo Tanimura 	 */
812fe1a5d1cSSeigo Tanimura 	*data = csa_readio(resp, BA0_ACSDA);
813fe1a5d1cSSeigo Tanimura 
814fe1a5d1cSSeigo Tanimura 	return (0);
815fe1a5d1cSSeigo Tanimura }
816fe1a5d1cSSeigo Tanimura 
817fe1a5d1cSSeigo Tanimura int
818fe1a5d1cSSeigo Tanimura csa_writecodec(csa_res *resp, u_long offset, u_int32_t data)
819fe1a5d1cSSeigo Tanimura {
820fe1a5d1cSSeigo Tanimura 	int i;
821fe1a5d1cSSeigo Tanimura 	u_int32_t acctl;
822fe1a5d1cSSeigo Tanimura 
823fe1a5d1cSSeigo Tanimura 	/*
824fe1a5d1cSSeigo Tanimura 	 * Setup the AC97 control registers on the CS461x to send the
825fe1a5d1cSSeigo Tanimura 	 * appropriate command to the AC97 to perform the write.
826fe1a5d1cSSeigo Tanimura 	 * ACCAD = Command Address Register = 46Ch
827fe1a5d1cSSeigo Tanimura 	 * ACCDA = Command Data Register = 470h
828fe1a5d1cSSeigo Tanimura 	 * ACCTL = Control Register = 460h
829fe1a5d1cSSeigo Tanimura 	 * set DCV - will clear when process completed
830fe1a5d1cSSeigo Tanimura 	 * set VFRM - valid frame enabled
831fe1a5d1cSSeigo Tanimura 	 * set ESYN - ASYNC generation enabled
832fe1a5d1cSSeigo Tanimura 	 * set RSTN - ARST# inactive, AC97 codec not reset
833fe1a5d1cSSeigo Tanimura 	 */
834fe1a5d1cSSeigo Tanimura 
835fe1a5d1cSSeigo Tanimura 	/*
836fe1a5d1cSSeigo Tanimura 	 * Get the actual AC97 register from the offset
837fe1a5d1cSSeigo Tanimura 	 */
838fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCAD, offset - BA0_AC97_RESET);
839fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCDA, data);
840fe1a5d1cSSeigo Tanimura 	csa_writeio(resp, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
841fe1a5d1cSSeigo Tanimura 
842fe1a5d1cSSeigo Tanimura 	/*
843fe1a5d1cSSeigo Tanimura 	 * Wait for the write to occur.
844fe1a5d1cSSeigo Tanimura 	 */
845fe1a5d1cSSeigo Tanimura 	acctl = 0;
846fe1a5d1cSSeigo Tanimura 	for (i = 0 ; i < 10 ; i++) {
847fe1a5d1cSSeigo Tanimura 		/*
848fe1a5d1cSSeigo Tanimura 		 * First, we want to wait for a short time.
849fe1a5d1cSSeigo Tanimura 		 */
850fe1a5d1cSSeigo Tanimura 		DELAY(25);
851fe1a5d1cSSeigo Tanimura 
852fe1a5d1cSSeigo Tanimura 		/*
853fe1a5d1cSSeigo Tanimura 		 * Now, check to see if the read has completed.
854fe1a5d1cSSeigo Tanimura 		 * ACCTL = 460h, DCV should be reset by now and 460h = 17h
855fe1a5d1cSSeigo Tanimura 		 */
856fe1a5d1cSSeigo Tanimura 		acctl = csa_readio(resp, BA0_ACCTL);
857fe1a5d1cSSeigo Tanimura 		if ((acctl & ACCTL_DCV) == 0)
858fe1a5d1cSSeigo Tanimura 			break;
859fe1a5d1cSSeigo Tanimura 	}
860fe1a5d1cSSeigo Tanimura 
861fe1a5d1cSSeigo Tanimura 	/*
862fe1a5d1cSSeigo Tanimura 	 * Make sure the write completed.
863fe1a5d1cSSeigo Tanimura 	 */
864fe1a5d1cSSeigo Tanimura 	if ((acctl & ACCTL_DCV) != 0)
865fe1a5d1cSSeigo Tanimura 		return (EAGAIN);
866fe1a5d1cSSeigo Tanimura 
867fe1a5d1cSSeigo Tanimura 	return (0);
868fe1a5d1cSSeigo Tanimura }
869fe1a5d1cSSeigo Tanimura 
870fe1a5d1cSSeigo Tanimura u_int32_t
871fe1a5d1cSSeigo Tanimura csa_readio(csa_res *resp, u_long offset)
872fe1a5d1cSSeigo Tanimura {
873fe1a5d1cSSeigo Tanimura 	u_int32_t ul;
874fe1a5d1cSSeigo Tanimura 
875fe1a5d1cSSeigo Tanimura 	if (offset < BA0_AC97_RESET)
876fe1a5d1cSSeigo Tanimura 		return bus_space_read_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset) & 0xffffffff;
877fe1a5d1cSSeigo Tanimura 	else {
878fe1a5d1cSSeigo Tanimura 		if (csa_readcodec(resp, offset, &ul))
879fe1a5d1cSSeigo Tanimura 			ul = 0;
880fe1a5d1cSSeigo Tanimura 		return (ul);
881fe1a5d1cSSeigo Tanimura 	}
882fe1a5d1cSSeigo Tanimura }
883fe1a5d1cSSeigo Tanimura 
884fe1a5d1cSSeigo Tanimura void
885fe1a5d1cSSeigo Tanimura csa_writeio(csa_res *resp, u_long offset, u_int32_t data)
886fe1a5d1cSSeigo Tanimura {
887fe1a5d1cSSeigo Tanimura 	if (offset < BA0_AC97_RESET)
888fe1a5d1cSSeigo Tanimura 		bus_space_write_4(rman_get_bustag(resp->io), rman_get_bushandle(resp->io), offset, data);
889fe1a5d1cSSeigo Tanimura 	else
890fe1a5d1cSSeigo Tanimura 		csa_writecodec(resp, offset, data);
891fe1a5d1cSSeigo Tanimura }
892fe1a5d1cSSeigo Tanimura 
893fe1a5d1cSSeigo Tanimura u_int32_t
894fe1a5d1cSSeigo Tanimura csa_readmem(csa_res *resp, u_long offset)
895fe1a5d1cSSeigo Tanimura {
896fe1a5d1cSSeigo Tanimura 	return bus_space_read_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset) & 0xffffffff;
897fe1a5d1cSSeigo Tanimura }
898fe1a5d1cSSeigo Tanimura 
899fe1a5d1cSSeigo Tanimura void
900fe1a5d1cSSeigo Tanimura csa_writemem(csa_res *resp, u_long offset, u_int32_t data)
901fe1a5d1cSSeigo Tanimura {
902fe1a5d1cSSeigo Tanimura 	bus_space_write_4(rman_get_bustag(resp->mem), rman_get_bushandle(resp->mem), offset, data);
903fe1a5d1cSSeigo Tanimura }
904fe1a5d1cSSeigo Tanimura 
905fe1a5d1cSSeigo Tanimura #if NPCI > 0
906fe1a5d1cSSeigo Tanimura static device_method_t csa_methods[] = {
907fe1a5d1cSSeigo Tanimura 	/* Device interface */
908fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_probe,		csa_probe),
909fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_attach,	csa_attach),
910fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_detach,	bus_generic_detach),
911fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
912fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_suspend,	bus_generic_suspend),
913fe1a5d1cSSeigo Tanimura 	DEVMETHOD(device_resume,	bus_generic_resume),
914fe1a5d1cSSeigo Tanimura 
915fe1a5d1cSSeigo Tanimura 	/* Bus interface */
916fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
917fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_alloc_resource,	csa_alloc_resource),
918fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_release_resource,	csa_release_resource),
919fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
920fe1a5d1cSSeigo Tanimura 	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
921f259d7eeSSeigo Tanimura 	DEVMETHOD(bus_setup_intr,	csa_setup_intr),
922f259d7eeSSeigo Tanimura 	DEVMETHOD(bus_teardown_intr,	csa_teardown_intr),
923fe1a5d1cSSeigo Tanimura 
924fe1a5d1cSSeigo Tanimura 	{ 0, 0 }
925fe1a5d1cSSeigo Tanimura };
926fe1a5d1cSSeigo Tanimura 
927fe1a5d1cSSeigo Tanimura static driver_t csa_driver = {
928fe1a5d1cSSeigo Tanimura 	"csa",
929fe1a5d1cSSeigo Tanimura 	csa_methods,
930fe1a5d1cSSeigo Tanimura 	sizeof(struct csa_softc),
931fe1a5d1cSSeigo Tanimura };
932fe1a5d1cSSeigo Tanimura 
933fe1a5d1cSSeigo Tanimura /*
934fe1a5d1cSSeigo Tanimura  * csa can be attached to a pci bus.
935fe1a5d1cSSeigo Tanimura  */
936fe1a5d1cSSeigo Tanimura DRIVER_MODULE(csa, pci, csa_driver, csa_devclass, 0, 0);
937fe1a5d1cSSeigo Tanimura #endif /* NPCI > 0 */
938