Deleted Added
full compact
csa.c (55288) csa.c (55320)
1/*-
1/*
2 * Copyright (c) 1999 Seigo Tanimura
3 * All rights reserved.
4 *
5 * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
6 * cwcealdr1.zip, the sample sources by Crystal Semiconductor.
7 * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
8 *
9 * Redistribution and use in source and binary forms, with or without

--- 12 unchanged lines hidden (view full) ---

22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
2 * Copyright (c) 1999 Seigo Tanimura
3 * All rights reserved.
4 *
5 * Portions of this source are based on cwcealdr.cpp and dhwiface.cpp in
6 * cwcealdr1.zip, the sample sources by Crystal Semiconductor.
7 * Copyright (c) 1996-1998 Crystal Semiconductor Corp.
8 *
9 * Redistribution and use in source and binary forms, with or without

--- 12 unchanged lines hidden (view full) ---

22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $FreeBSD: head/sys/dev/sound/pci/csa.c 55288 2000-01-01 09:07:03Z tanimura $
30 * $FreeBSD: head/sys/dev/sound/pci/csa.c 55320 2000-01-03 02:51:16Z tanimura $
31 */
32
33#include "pci.h"
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/kernel.h>
38#include <sys/bus.h>

--- 24 unchanged lines hidden (view full) ---

63 driver_intr_t* pcmintr; /* pcm intr */
64 void *pcmintr_arg; /* pcm intr arg */
65#if notyet
66 device_t midi; /* midi device */
67 driver_intr_t* midiintr; /* midi intr */
68 void *midiintr_arg; /* midi intr arg */
69#endif /* notyet */
70 void *ih; /* cookie */
31 */
32
33#include "pci.h"
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/kernel.h>
38#include <sys/bus.h>

--- 24 unchanged lines hidden (view full) ---

63 driver_intr_t* pcmintr; /* pcm intr */
64 void *pcmintr_arg; /* pcm intr arg */
65#if notyet
66 device_t midi; /* midi device */
67 driver_intr_t* midiintr; /* midi intr */
68 void *midiintr_arg; /* midi intr arg */
69#endif /* notyet */
70 void *ih; /* cookie */
71
72 struct csa_bridgeinfo binfo; /* The state of this bridge. */
71};
72
73typedef struct csa_softc *sc_p;
74
75#if NPCI > 0
76static int csa_probe(device_t dev);
77static int csa_attach(device_t dev);
78#endif /* NPCI > 0 */
79static struct resource *csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
80 u_long start, u_long end, u_long count, u_int flags);
81static int csa_release_resource(device_t bus, device_t child, int type, int rid,
82 struct resource *r);
73};
74
75typedef struct csa_softc *sc_p;
76
77#if NPCI > 0
78static int csa_probe(device_t dev);
79static int csa_attach(device_t dev);
80#endif /* NPCI > 0 */
81static struct resource *csa_alloc_resource(device_t bus, device_t child, int type, int *rid,
82 u_long start, u_long end, u_long count, u_int flags);
83static int csa_release_resource(device_t bus, device_t child, int type, int rid,
84 struct resource *r);
85static int csa_setup_intr(device_t bus, device_t child,
86 struct resource *irq, int flags,
87 driver_intr_t *intr, void *arg, void **cookiep);
88static int csa_teardown_intr(device_t bus, device_t child,
89 struct resource *irq, void *cookie);
90static driver_intr_t csa_intr;
83static int csa_initialize(sc_p scp);
91static int csa_initialize(sc_p scp);
84static void csa_clearserialfifos(csa_res *resp);
85static void csa_resetdsp(csa_res *resp);
86static int csa_downloadimage(csa_res *resp);
87static int csa_transferimage(csa_res *resp, u_long *src, u_long dest, u_long len);
88
89static devclass_t csa_devclass;
90
91#if NPCI > 0
92static int
93csa_probe(device_t dev)
94{
92static void csa_resetdsp(csa_res *resp);
93static int csa_downloadimage(csa_res *resp);
94static int csa_transferimage(csa_res *resp, u_long *src, u_long dest, u_long len);
95
96static devclass_t csa_devclass;
97
98#if NPCI > 0
99static int
100csa_probe(device_t dev)
101{
95 device_t child;
96 char *s;
102 char *s;
97 struct sndcard_func *func;
98
99 s = NULL;
100 switch (pci_get_devid(dev)) {
101 case CS4610_PCI_ID:
102 s = "Crystal Semiconductor CS4610/4611 Audio accelerator";
103 break;
104 case CS4614_PCI_ID:
105 s = "Crystal Semiconductor CS4614/4622/4624 Audio accelerator/4280 Audio controller";
106 break;
107 case CS4615_PCI_ID:
108 s = "Crystal Semiconductor CS4615 Audio accelerator";
109 break;
110 case CS4281_PCI_ID:
111 s = "Crystal Semiconductor CS4281 Audio controller";
112 break;
113 }
114
115 if (s != NULL) {
116 device_set_desc(dev, s);
103
104 s = NULL;
105 switch (pci_get_devid(dev)) {
106 case CS4610_PCI_ID:
107 s = "Crystal Semiconductor CS4610/4611 Audio accelerator";
108 break;
109 case CS4614_PCI_ID:
110 s = "Crystal Semiconductor CS4614/4622/4624 Audio accelerator/4280 Audio controller";
111 break;
112 case CS4615_PCI_ID:
113 s = "Crystal Semiconductor CS4615 Audio accelerator";
114 break;
115 case CS4281_PCI_ID:
116 s = "Crystal Semiconductor CS4281 Audio controller";
117 break;
118 }
119
120 if (s != NULL) {
121 device_set_desc(dev, s);
117
118 /* PCM Audio */
119 func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
120 if (func == NULL)
121 return (ENOMEM);
122 bzero(func, sizeof(*func));
123 func->func = SCF_PCM;
124 child = device_add_child(dev, "pcm", -1);
125 device_set_ivars(child, func);
126
127#if notyet
128 /* Midi Interface */
129 func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
130 if (func == NULL)
131 return (ENOMEM);
132 bzero(func, sizeof(*func));
133 func->func = SCF_MIDI;
134 child = device_add_child(dev, "midi", -1);
135 device_set_ivars(child, func);
136#endif /* notyet */
137
138 return (0);
139 }
140
141 return (ENXIO);
142}
143
144static int
145csa_attach(device_t dev)
146{
147 u_int32_t stcmd;
148 sc_p scp;
149 csa_res *resp;
122 return (0);
123 }
124
125 return (ENXIO);
126}
127
128static int
129csa_attach(device_t dev)
130{
131 u_int32_t stcmd;
132 sc_p scp;
133 csa_res *resp;
134 struct sndcard_func *func;
150
151 scp = device_get_softc(dev);
152
153 /* Fill in the softc. */
154 bzero(scp, sizeof(*scp));
155 scp->dev = dev;
156
157 /* Wake up the device. */
158 stcmd = pci_read_config(dev, PCIR_COMMAND, 4);
159 if ((stcmd & PCIM_CMD_MEMEN) == 0 || (stcmd & PCIM_CMD_BUSMASTEREN) == 0) {
160 stcmd |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
161 pci_write_config(dev, PCIR_COMMAND, 4, stcmd);
162 }
135
136 scp = device_get_softc(dev);
137
138 /* Fill in the softc. */
139 bzero(scp, sizeof(*scp));
140 scp->dev = dev;
141
142 /* Wake up the device. */
143 stcmd = pci_read_config(dev, PCIR_COMMAND, 4);
144 if ((stcmd & PCIM_CMD_MEMEN) == 0 || (stcmd & PCIM_CMD_BUSMASTEREN) == 0) {
145 stcmd |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
146 pci_write_config(dev, PCIR_COMMAND, 4, stcmd);
147 }
163 stcmd = pci_read_config(dev, PCIR_LATTIMER, 4);
164 if (stcmd < 32)
165 stcmd = 32;
166 pci_write_config(dev, PCIR_LATTIMER, 4, stcmd);
167
168 /* Allocate the resources. */
169 resp = &scp->res;
170 resp->io_rid = CS461x_IO_OFFSET;
171 resp->io = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->io_rid, 0, ~0, CS461x_IO_SIZE, RF_ACTIVE);
172 if (resp->io == NULL)
173 return (ENXIO);
174 resp->mem_rid = CS461x_MEM_OFFSET;

--- 5 unchanged lines hidden (view full) ---

180 resp->irq_rid = 0;
181 resp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &resp->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
182 if (resp->irq == NULL) {
183 bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
184 bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
185 return (ENXIO);
186 }
187
148
149 /* Allocate the resources. */
150 resp = &scp->res;
151 resp->io_rid = CS461x_IO_OFFSET;
152 resp->io = bus_alloc_resource(dev, SYS_RES_MEMORY, &resp->io_rid, 0, ~0, CS461x_IO_SIZE, RF_ACTIVE);
153 if (resp->io == NULL)
154 return (ENXIO);
155 resp->mem_rid = CS461x_MEM_OFFSET;

--- 5 unchanged lines hidden (view full) ---

161 resp->irq_rid = 0;
162 resp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &resp->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
163 if (resp->irq == NULL) {
164 bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
165 bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
166 return (ENXIO);
167 }
168
169 /* Enable interrupt. */
170 if (bus_setup_intr(dev, resp->irq, INTR_TYPE_TTY, csa_intr, scp, &scp->ih)) {
171 bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
172 bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
173 bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
174 return (ENXIO);
175 }
176 if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
177 csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
178
188 /* Initialize the chip. */
189 if (csa_initialize(scp)) {
190 bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
191 bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
192 bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
193 return (ENXIO);
194 }
195
196 /* Reset the Processor. */
197 csa_resetdsp(resp);
198
199 /* Download the Processor Image to the processor. */
200 if (csa_downloadimage(resp)) {
201 bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
202 bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
203 bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
204 return (ENXIO);
205 }
206
179 /* Initialize the chip. */
180 if (csa_initialize(scp)) {
181 bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
182 bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
183 bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
184 return (ENXIO);
185 }
186
187 /* Reset the Processor. */
188 csa_resetdsp(resp);
189
190 /* Download the Processor Image to the processor. */
191 if (csa_downloadimage(resp)) {
192 bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
193 bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
194 bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
195 return (ENXIO);
196 }
197
198 /* Attach the children. */
199
200 /* PCM Audio */
201 func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
202 if (func == NULL)
203 return (ENOMEM);
204 bzero(func, sizeof(*func));
205 func->varinfo = &scp->binfo;
206 func->func = SCF_PCM;
207 scp->pcm = device_add_child(dev, "pcm", -1);
208 device_set_ivars(scp->pcm, func);
209
210#if notyet
211 /* Midi Interface */
212 func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT);
213 if (func == NULL)
214 return (ENOMEM);
215 bzero(func, sizeof(*func));
216 func->varinfo = &scp->binfo;
217 func->func = SCF_MIDI;
218 scp->midi = device_add_child(dev, "midi", -1);
219 device_set_ivars(scp->midi, func);
220#endif /* notyet */
221
207 bus_generic_attach(dev);
208
209 return (0);
210}
211#endif /* NPCI > 0 */
212
213static struct resource *
214csa_alloc_resource(device_t bus, device_t child, int type, int *rid,

--- 32 unchanged lines hidden (view full) ---

247
248static int
249csa_release_resource(device_t bus, device_t child, int type, int rid,
250 struct resource *r)
251{
252 return (0);
253}
254
222 bus_generic_attach(dev);
223
224 return (0);
225}
226#endif /* NPCI > 0 */
227
228static struct resource *
229csa_alloc_resource(device_t bus, device_t child, int type, int *rid,

--- 32 unchanged lines hidden (view full) ---

262
263static int
264csa_release_resource(device_t bus, device_t child, int type, int rid,
265 struct resource *r)
266{
267 return (0);
268}
269
270/*
271 * The following three functions deal with interrupt handling.
272 * An interrupt is primarily handled by the bridge driver.
273 * The bridge driver then determines the child devices to pass
274 * the interrupt. Certain information of the device can be read
275 * only once(eg the value of HISR). The bridge driver is responsible
276 * to pass such the information to the children.
277 */
278
255static int
279static int
280csa_setup_intr(device_t bus, device_t child,
281 struct resource *irq, int flags,
282 driver_intr_t *intr, void *arg, void **cookiep)
283{
284 sc_p scp;
285 csa_res *resp;
286 struct sndcard_func *func;
287
288 scp = device_get_softc(bus);
289 resp = &scp->res;
290
291 /*
292 * Look at the function code of the child to determine
293 * the appropriate hander for it.
294 */
295 func = device_get_ivars(child);
296 if (func == NULL || irq != resp->irq)
297 return (EINVAL);
298
299 switch (func->func) {
300 case SCF_PCM:
301 scp->pcmintr = intr;
302 scp->pcmintr_arg = arg;
303 break;
304
305#if notyet
306 case SCF_MIDI:
307 scp->midiintr = intr;
308 scp->midiintr_arg = arg;
309 break;
310#endif /* notyet */
311
312 default:
313 return (EINVAL);
314 }
315 *cookiep = scp;
316 if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
317 csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
318
319 return (0);
320}
321
322static int
323csa_teardown_intr(device_t bus, device_t child,
324 struct resource *irq, void *cookie)
325{
326 sc_p scp;
327 csa_res *resp;
328 struct sndcard_func *func;
329
330 scp = device_get_softc(bus);
331 resp = &scp->res;
332
333 /*
334 * Look at the function code of the child to determine
335 * the appropriate hander for it.
336 */
337 func = device_get_ivars(child);
338 if (func == NULL || irq != resp->irq || cookie != scp)
339 return (EINVAL);
340
341 switch (func->func) {
342 case SCF_PCM:
343 scp->pcmintr = NULL;
344 scp->pcmintr_arg = NULL;
345 break;
346
347#if notyet
348 case SCF_MIDI:
349 scp->midiintr = NULL;
350 scp->midiintr_arg = NULL;
351 break;
352#endif /* notyet */
353
354 default:
355 return (EINVAL);
356 }
357
358 return (0);
359}
360
361/* The interrupt handler */
362static void
363csa_intr(void *arg)
364{
365 sc_p scp = arg;
366 csa_res *resp;
367 u_int32_t hisr;
368
369 resp = &scp->res;
370
371 /* Is this interrupt for us? */
372 hisr = csa_readio(resp, BA0_HISR);
373 if ((hisr & ~HISR_INTENA) == 0) {
374 /* Throw an eoi. */
375 csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
376 return;
377 }
378
379 /*
380 * Pass the value of HISR via struct csa_bridgeinfo.
381 * The children get access through their ivars.
382 */
383 scp->binfo.hisr = hisr;
384
385 /* Invoke the handlers of the children. */
386 if ((hisr & (HISR_VC0 | HISR_VC1)) != 0 && scp->pcmintr != NULL)
387 scp->pcmintr(scp->pcmintr_arg);
388#if notyet
389 if ((hisr & HISR_MIDI) != 0 && scp->midiintr != NULL)
390 scp->midiintr(scp->midiintr_arg);
391#endif /* notyet */
392
393 /* Throw an eoi. */
394 csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
395}
396
397static int
256csa_initialize(sc_p scp)
257{
258 int i;
259 u_int32_t acsts, acisv;
260 csa_res *resp;
261
262 resp = &scp->res;
263

--- 179 unchanged lines hidden (view full) ---

443 */
444#if notdef
445 csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
446#endif /* notdef */
447
448 return (0);
449}
450
398csa_initialize(sc_p scp)
399{
400 int i;
401 u_int32_t acsts, acisv;
402 csa_res *resp;
403
404 resp = &scp->res;
405

--- 179 unchanged lines hidden (view full) ---

585 */
586#if notdef
587 csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
588#endif /* notdef */
589
590 return (0);
591}
592
451static void
593void
452csa_clearserialfifos(csa_res *resp)
453{
454 int i, j, pwr;
455 u_int8_t clkcr1, serbst;
456
457 /*
458 * See if the devices are powered down. If so, we must power them up first
459 * or they will not respond.

--- 311 unchanged lines hidden (view full) ---

771 DEVMETHOD(device_resume, bus_generic_resume),
772
773 /* Bus interface */
774 DEVMETHOD(bus_print_child, bus_generic_print_child),
775 DEVMETHOD(bus_alloc_resource, csa_alloc_resource),
776 DEVMETHOD(bus_release_resource, csa_release_resource),
777 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
778 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
594csa_clearserialfifos(csa_res *resp)
595{
596 int i, j, pwr;
597 u_int8_t clkcr1, serbst;
598
599 /*
600 * See if the devices are powered down. If so, we must power them up first
601 * or they will not respond.

--- 311 unchanged lines hidden (view full) ---

913 DEVMETHOD(device_resume, bus_generic_resume),
914
915 /* Bus interface */
916 DEVMETHOD(bus_print_child, bus_generic_print_child),
917 DEVMETHOD(bus_alloc_resource, csa_alloc_resource),
918 DEVMETHOD(bus_release_resource, csa_release_resource),
919 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
920 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
779 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
780 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
921 DEVMETHOD(bus_setup_intr, csa_setup_intr),
922 DEVMETHOD(bus_teardown_intr, csa_teardown_intr),
781
782 { 0, 0 }
783};
784
785static driver_t csa_driver = {
786 "csa",
787 csa_methods,
788 sizeof(struct csa_softc),
789};
790
791/*
792 * csa can be attached to a pci bus.
793 */
794DRIVER_MODULE(csa, pci, csa_driver, csa_devclass, 0, 0);
795#endif /* NPCI > 0 */
923
924 { 0, 0 }
925};
926
927static driver_t csa_driver = {
928 "csa",
929 csa_methods,
930 sizeof(struct csa_softc),
931};
932
933/*
934 * csa can be attached to a pci bus.
935 */
936DRIVER_MODULE(csa, pci, csa_driver, csa_devclass, 0, 0);
937#endif /* NPCI > 0 */