📄 ad1848.c
字号:
snd_set_blocksize(d); /* update blocksize if user did not force it */}/* * here we have support for PnP cards * */#if NPNP > 0static char * cs423x_probe(u_long csn, u_long vend_id);static void cs423x_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev);static struct pnp_device cs423x = { "CS423x/Yamaha", cs423x_probe, cs423x_attach, &nsnd, /* use this for all sound cards */ &tty_imask /* imask */};DATA_SET (pnpdevice_set, cs423x);static char *cs423x_probe(u_long csn, u_long vend_id){ char *s = NULL ; u_long id = vend_id & 0xff00ffff; if ( id == 0x3700630e ) s = "CS4237" ; else if ( id == 0x2500630e) s = "CS4235" ; else if ( id == 0x3500630e || id == 0x3600630e ) s = "CS4236" ; else if ( id == 0x3200630e) s = "CS4232" ; else if ( id == 0x2000a865) s = "Yamaha SA2"; else if ( id == 0x3000a865) s = "Yamaha SA3"; else if (vend_id == 0x0000a865) s = "Yamaha YMF719 OPL-SA3"; else if (vend_id == 0x8140d315) s = "SoundscapeVIVO"; if (s) { struct pnp_cinfo d; read_pnp_parms(&d, 0); if (d.enable == 0) { printf("This is a %s, but LDN 0 is disabled\n", s); return NULL ; } return s; } return NULL ;}extern snddev_info sb_op_desc;static voidcs423x_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev){ struct pnp_cinfo d ; snddev_info tmp_d ; /* patched copy of the basic snddev_info */ int ldn = 0 ; if (read_pnp_parms ( &d , ldn ) == 0 ) { printf("failed to read pnp parms\n"); return ; } snddev_last_probed = &tmp_d; if (d.flags & DV_PNP_SBCODEC) { /*** use sb-compatible codec ***/ dev->id_alive = 16 ; /* number of io ports ? */ tmp_d = sb_op_desc ; if (vend_id==0x2000a865 || vend_id==0x3000a865 || vend_id==0x0008a865 || vend_id==0x8140d315) { /* Yamaha SA2/SA3 or ENSONIQ SoundscapeVIVO ENS4081 */ dev->id_iobase = d.port[0] ; tmp_d.alt_base = d.port[1] ; d.irq[1] = 0 ; /* only needed for the VIVO */ } else { dev->id_iobase = d.port[2] ; tmp_d.alt_base = d.port[0] - 4; } d.drq[1] = 4 ; /* disable, it is not used ... */ } else { /* mss-compatible codec */ dev->id_alive = 8 ; /* number of io ports ? */ tmp_d = mss_op_desc ; dev->id_iobase = d.port[0] -4 ; /* XXX old mss have 4 bytes before... */ tmp_d.alt_base = d.port[2]; switch (vend_id & 0xff00ffff) { case 0x2000a865: /* Yamaha SA2 */ case 0x3000a865: /* Yamaha SA3 */ case 0x0000a865: /* Yamaha TMF719 SA3 */ dev->id_iobase = d.port[1]; tmp_d.alt_base = d.port[0]; tmp_d.conf_base = d.port[4]; tmp_d.bd_id = MD_YM0020 ; break; case 0x8100d315: /* ENSONIQ SoundscapeVIVO */ dev->id_iobase = d.port[1]; tmp_d.alt_base = d.port[0]; tmp_d.bd_id = MD_VIVO ; d.irq[1] = 0 ; break; case 0x3700630e: /* CS4237 */ tmp_d.bd_id = MD_CS4237 ; break; case 0x2500630e: /* AOpen AW37 */ tmp_d.bd_id = MD_CS4237 ; break ; case 0x3500630e: /* CS4236 */ case 0x3600630e: /* CS4236 */ tmp_d.bd_id = MD_CS4236 ; break; default: tmp_d.bd_id = MD_CS4232 ; /* to short-circuit the detect routine */ break; } strcpy(tmp_d.name, name); tmp_d.audio_fmt |= AFMT_FULLDUPLEX ; } write_pnp_parms( &d, ldn ); enable_pnp_card(); if ( (vend_id & 0x0000ffff) == 0x0000a865 ) { /* special volume setting for the Yamaha... */ outb(tmp_d.conf_base, 7 /* volume, left */); outb(tmp_d.conf_base+1, 0 ); outb(tmp_d.conf_base, 8 /* volume, right */); outb(tmp_d.conf_base+1, 0 ); } dev->id_drq = d.drq[0] ; /* primary dma */ dev->id_irq = (1 << d.irq[0] ) ; dev->id_intr = pcmintr ; dev->id_flags = DV_F_DUAL_DMA | (d.drq[1] ) ; tmp_d.synth_base = d.port[1]; /* XXX check this for yamaha */ pcmattach(dev);}static char *opti931_probe(u_long csn, u_long vend_id);static void opti931_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev);static struct pnp_device opti931 = { "OPTi931", opti931_probe, opti931_attach, &nsnd, /* use this for all sound cards */ &tty_imask /* imask */};DATA_SET (pnpdevice_set, opti931);static char *opti931_probe(u_long csn, u_long vend_id){ if (vend_id == 0x3109143e) { struct pnp_cinfo d; read_pnp_parms(&d, 1); if (d.enable == 0) { printf("This is an OPTi931, but LDN 1 is disabled\n"); return NULL ; } return "OPTi931" ; } return NULL ;}static voidopti931_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev){ struct pnp_cinfo d ; snddev_info tmp_d ; /* patched copy of the basic snddev_info */ int p; read_pnp_parms ( &d , 3 ); /* free resources taken by LDN 3 */ d.irq[0]=0; /* free irq... */ d.port[0]=0; /* free address... */ d.enable = 0 ; write_pnp_parms ( &d , 3 ); read_pnp_parms ( &d , 2 ); /* disable LDN 2 */ d.enable = 0 ; write_pnp_parms ( &d , 2 ); read_pnp_parms ( &d , 1 ) ; write_pnp_parms( &d, 1 ); enable_pnp_card(); snddev_last_probed = &tmp_d; tmp_d = d.flags & DV_PNP_SBCODEC ? sb_op_desc : mss_op_desc ; strcpy(tmp_d.name, name); /* * My MED3931 v.1.0 allocates 3 bytes for the config space, * whereas v.2.0 allocates 4 bytes. What I know for sure is that the * upper two ports must be used, and they should end on a boundary * of 4 bytes. So I need the following trick... */ p = tmp_d.conf_base = (d.port[3] & ~3) + 2; /* config port */ /* * now set default values for both modes. */ dev->id_iobase = d.port[0] - 4 ; /* old mss have 4 bytes before... */ tmp_d.io_base = dev->id_iobase; /* needed for ad_write to work... */ tmp_d.alt_base = d.port[2]; tmp_d.synth_base = d.port[1]; DEB(printf("opti_attach: selecting mode\n");) opti_write(p, 4, 0xd6 /* fifo empty, OPL3, audio enable, SB3.2 */ ); DELAY(1000*300); ad_write (&tmp_d, 10, 2); /* enable interrupts */ DEB(printf("opti_attach: int enabled\n");) if (d.flags & DV_PNP_SBCODEC) { /* sb-compatible codec */ /* * the 931 is not a real SB, it has important pieces of * hardware controlled by both the MSS and the SB port... */ printf("--- opti931 in sb mode ---\n"); opti_write(p, 6, 1); /* MCIR6 mss disable, sb enable */ /* * swap the main and alternate iobase address since we want * to work in sb mode. */ dev->id_iobase = d.port[2] ; tmp_d.alt_base = d.port[0] - 4; dev->id_flags = DV_F_DUAL_DMA | d.drq[1] ; } else { /* mss-compatible codec */ tmp_d.bd_id = MD_OPTI931 ; /* to short-circuit the detect routine */ opti_write(p, 6 , 2); /* MCIR6: mss enable, sb disable */ opti_write(p, 5, 0x28); /* MCIR5: codec in exp. mode,fifo */ dev->id_flags = DV_F_DUAL_DMA | d.drq[1] ; tmp_d.audio_fmt |= AFMT_FULLDUPLEX ; /* not really well... */ tmp_d.isr = opti931_intr; } dev->id_drq = d.drq[0] ; /* primary dma */ dev->id_irq = (1 << d.irq[0] ) ; dev->id_intr = pcmintr ; pcmattach(dev);}static char *opti925_probe(u_long csn, u_long vend_id);static void opti925_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev); static struct pnp_device opti925 = { "opti925", opti925_probe, opti925_attach, &nsnd, /* use this for all sound cards */ &tty_imask /* imask */ }; DATA_SET (pnpdevice_set, opti925); static char *opti925_probe(u_long csn, u_long vend_id){ if (vend_id == 0x2509143e) { struct pnp_cinfo d ; read_pnp_parms ( &d , 1 ) ; if (d.enable == 0) { printf("This is an OPTi925, but LDN 1 is disabled\n"); return NULL; } return "OPTi925" ; } return NULL ;} static void opti925_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) { struct pnp_cinfo d ; snddev_info tmp_d ; /* patched copy of the basic snddev_info */ int the_irq = 0 ; tmp_d = mss_op_desc; snddev_last_probed = &tmp_d; read_pnp_parms ( &d , 3 ); /* disable LDN 3 */ the_irq = d.irq[0]; d.port[0] = 0 ; d.enable = 0 ; write_pnp_parms ( &d , 3 ); read_pnp_parms ( &d , 2 ); /* disable LDN 2 */ d.port[0] = 0 ; d.enable = 0 ; write_pnp_parms ( &d , 2 ); read_pnp_parms ( &d , 1 ) ; d.irq[0] = the_irq ; dev->id_iobase = d.port[1]; tmp_d.alt_base = d.port[0]; write_pnp_parms ( &d , 1 ); enable_pnp_card(); tmp_d.conf_base = d.port[3]; dev->id_drq = d.drq[0] ; /* primary dma */ dev->id_irq = (1 << d.irq[0] ) ; dev->id_intr = pcmintr ; dev->id_flags = DV_F_DUAL_DMA | d.drq[1] ; tmp_d.audio_fmt |= AFMT_FULLDUPLEX ; snddev_last_probed->probe(dev); /* not really necessary but doesn't harm */ pcmattach(dev);}static void gus_mem_cfg(snddev_info *tmp);static char *guspnp_probe(u_long csn, u_long vend_id);static void guspnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev);static struct pnp_device guspnp = { "GusPnP", guspnp_probe, guspnp_attach, &nsnd, /* use this for all sound cards */ &tty_imask /* imask */};DATA_SET (pnpdevice_set, guspnp);static char *guspnp_probe(u_long csn, u_long vend_id){ if (vend_id == 0x0100561e) { struct pnp_cinfo d; read_pnp_parms(&d, 0); if (d.enable == 0) { printf("This is a GusPnP, but LDN 0 is disabled\n"); return NULL ; } return "GusPnP" ; } return NULL ;}static voidguspnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev){ struct pnp_cinfo d ; snddev_info tmp_d ; /* patched copy of the basic snddev_info */ u_char tmp; read_pnp_parms ( &d , 0 ) ; /* d.irq[1] = d.irq[0] ; */ pnp_write ( 0xf2, 0xff ); /* enable power on the guspnp */ write_pnp_parms ( &d , 0 ); enable_pnp_card(); tmp_d = mss_op_desc ; snddev_last_probed = &tmp_d; dev->id_iobase = d.port[2] - 4 ; /* room for 4 mss registers */ dev->id_drq = d.drq[1] ; /* XXX PLAY dma */ dev->id_irq = (1 << d.irq[0] ) ; dev->id_intr = pcmintr ; dev->id_flags = DV_F_DUAL_DMA | d.drq[0] ; /* REC dma */ tmp_d.io_base = d.port[2] - 4; tmp_d.alt_base = d.port[0]; /* 0x220 */ tmp_d.conf_base = d.port[1]; /* gus control block... */ tmp_d.bd_id = MD_GUSPNP ; /* reset */ gus_write(tmp_d.conf_base, 0x4c /* _URSTI */, 0 );/* Pull reset */ DELAY(1000 * 30); /* release reset and enable DAC */ gus_write(tmp_d.conf_base, 0x4c /* _URSTI */, 3 ); DELAY(1000 * 30); /* end of reset */ outb( tmp_d.alt_base, 0xC ); /* enable int and dma */ /* * unmute left & right line. Need to go in mode3, unmute, * and back to mode 2 */ tmp = ad_read(&tmp_d, 0x0c); ad_write(&tmp_d, 0x0c, 0x6c ); /* special value to enter mode 3 */ ad_write(&tmp_d, 0x19, 0 ); /* unmute left */ ad_write(&tmp_d, 0x1b, 0 ); /* unmute right */ ad_write(&tmp_d, 0x0c, tmp ); /* restore old mode */ /* send codec interrupts on irq1 and only use that one */ gus_write(tmp_d.conf_base, 0x5a , 0x4f ); /* enable access to hidden regs */ tmp = gus_read(tmp_d.conf_base, 0x5b /* IVERI */ ); gus_write(tmp_d.conf_base, 0x5b , tmp | 1 ); BVDDB(printf("GUS: silicon rev %c\n", 'A' + ( ( tmp & 0xf ) >> 4) );) strcpy(tmp_d.name, name); pcmattach(dev);}#if 0intgus_mem_write(snddev_info *d, int addr, u_char data){ gus_writew(d->conf_base, 0x43 , addr & 0xffff ); gus_write(d->conf_base, 0x44 , (addr>>16) & 0xff ); outb(d->conf_base + 7, data);}u_chargus_mem_read(snddev_info *d, int addr){ gus_writew(d->conf_base, 0x43 , addr & 0xffff ); gus_write(d->conf_base, 0x44 , (addr>>16) & 0xff ); return inb(d->conf_base + 7);}voidgus_mem_cfg(snddev_info *d){ int base; u_char old; u_char a, b; printf("configuring gus memory...\n"); gus_writew(d->conf_base, 0x52 /* LMCFI */, 1 /* 512K*/); old = gus_read(d->conf_base, 0x19); gus_write(d->conf_base, 0x19, old | 1); /* enable enhaced mode */ for (base = 0; base < 1024; base++) { a=gus_mem_read(d, base*1024); a = ~a ; gus_mem_write(d, base*1024, a); b=gus_mem_read(d, base*1024); if ( b != a ) break ; } printf("Have found %d KB ( 0x%x != 0x%x)\n", base, a, b);}#endif /* gus mem cfg... */#endif /* NPNP > 0 */#endif /* NPCM > 0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -