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 */ |