📄 pss.c
字号:
} err = download_boot_block(dev_info, buf); vfree(buf); return err; case SNDCTL_COPR_SENDMSG: mbuf = (copr_msg *)vmalloc(sizeof(copr_msg)); if (mbuf == NULL) return -ENOSPC; if (copy_from_user(mbuf, arg, sizeof(copr_msg))) { vfree(mbuf); return -EFAULT; } data = (unsigned short *)(mbuf->data); save_flags(flags); cli(); for (i = 0; i < mbuf->len; i++) { if (!pss_put_dspword(devc, *data++)) { restore_flags(flags); mbuf->len = i; /* feed back number of WORDs sent */ err = copy_to_user(arg, mbuf, sizeof(copr_msg)); vfree(mbuf); return err ? -EFAULT : -EIO; } } restore_flags(flags); vfree(mbuf); return 0; case SNDCTL_COPR_RCVMSG: err = 0; mbuf = (copr_msg *)vmalloc(sizeof(copr_msg)); if (mbuf == NULL) return -ENOSPC; data = (unsigned short *)mbuf->data; save_flags(flags); cli(); for (i = 0; i < sizeof(mbuf->data)/sizeof(unsigned short); i++) { mbuf->len = i; /* feed back number of WORDs read */ if (!pss_get_dspword(devc, data++)) { if (i == 0) err = -EIO; break; } } restore_flags(flags); if (copy_to_user(arg, mbuf, sizeof(copr_msg))) err = -EFAULT; vfree(mbuf); return err; case SNDCTL_COPR_RDATA: if (copy_from_user(&dbuf, arg, sizeof(dbuf))) return -EFAULT; save_flags(flags); cli(); if (!pss_put_dspword(devc, 0x00d0)) { restore_flags(flags); return -EIO; } if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { restore_flags(flags); return -EIO; } if (!pss_get_dspword(devc, &tmp)) { restore_flags(flags); return -EIO; } dbuf.parm1 = tmp; restore_flags(flags); if (copy_to_user(arg, &dbuf, sizeof(dbuf))) return -EFAULT; return 0; case SNDCTL_COPR_WDATA: if (copy_from_user(&dbuf, arg, sizeof(dbuf))) return -EFAULT; save_flags(flags); cli(); if (!pss_put_dspword(devc, 0x00d1)) { restore_flags(flags); return -EIO; } if (!pss_put_dspword(devc, (unsigned short) (dbuf.parm1 & 0xffff))) { restore_flags(flags); return -EIO; } tmp = (unsigned int)dbuf.parm2 & 0xffff; if (!pss_put_dspword(devc, tmp)) { restore_flags(flags); return -EIO; } restore_flags(flags); return 0; case SNDCTL_COPR_WCODE: if (copy_from_user(&dbuf, arg, sizeof(dbuf))) return -EFAULT; save_flags(flags); cli(); if (!pss_put_dspword(devc, 0x00d3)) { restore_flags(flags); return -EIO; } if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { restore_flags(flags); return -EIO; } tmp = (unsigned int)dbuf.parm2 & 0x00ff; if (!pss_put_dspword(devc, tmp)) { restore_flags(flags); return -EIO; } tmp = ((unsigned int)dbuf.parm2 >> 8) & 0xffff; if (!pss_put_dspword(devc, tmp)) { restore_flags(flags); return -EIO; } restore_flags(flags); return 0; case SNDCTL_COPR_RCODE: if (copy_from_user(&dbuf, arg, sizeof(dbuf))) return -EFAULT; save_flags(flags); cli(); if (!pss_put_dspword(devc, 0x00d2)) { restore_flags(flags); return -EIO; } if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { restore_flags(flags); return -EIO; } if (!pss_get_dspword(devc, &tmp)) { /* Read MSB */ restore_flags(flags); return -EIO; } dbuf.parm1 = tmp << 8; if (!pss_get_dspword(devc, &tmp)) { /* Read LSB */ restore_flags(flags); return -EIO; } dbuf.parm1 |= tmp & 0x00ff; restore_flags(flags); if (copy_to_user(arg, &dbuf, sizeof(dbuf))) return -EFAULT; return 0; default: return -EINVAL; } return -EINVAL;}static coproc_operations pss_coproc_operations ={ "ADSP-2115", THIS_MODULE, pss_coproc_open, pss_coproc_close, pss_coproc_ioctl, pss_coproc_reset, &pss_data};static void __init attach_pss_mpu(struct address_info *hw_config){ attach_mpu401(hw_config, THIS_MODULE); /* Slot 1 */ if (hw_config->slots[1] != -1) /* The MPU driver installed itself */ midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations;}static int __init probe_pss_mss(struct address_info *hw_config){ volatile int timeout; if (!pss_initialized) return 0; if (check_region(hw_config->io_base, 8)) { printk(KERN_ERR "PSS: WSS I/O port conflicts.\n"); return 0; } if (!set_io_base(devc, CONF_WSS, hw_config->io_base)) { printk("PSS: WSS base not settable.\n"); return 0; } if (!set_irq(devc, CONF_WSS, hw_config->irq)) { printk("PSS: WSS IRQ allocation error.\n"); return 0; } if (!set_dma(devc, CONF_WSS, hw_config->dma)) { printk(KERN_ERR "PSS: WSS DMA allocation error\n"); return 0; } /* * For some reason the card returns 0xff in the WSS status register * immediately after boot. Probably MIDI+SB emulation algorithm * downloaded to the ADSP2115 spends some time initializing the card. * Let's try to wait until it finishes this task. */ for (timeout = 0; timeout < 100000 && (inb(hw_config->io_base + WSS_INDEX) & WSS_INITIALIZING); timeout++) ; outb((0x0b), hw_config->io_base + WSS_INDEX); /* Required by some cards */ for (timeout = 0; (inb(hw_config->io_base + WSS_DATA) & WSS_AUTOCALIBRATION) && (timeout < 100000); timeout++) ; return probe_ms_sound(hw_config);}static void __init attach_pss_mss(struct address_info *hw_config){ int my_mix = -999; /* gcc shut up */ devc->ad_mixer_dev = NO_WSS_MIXER; if (pss_mixer) { if ((my_mix = sound_install_mixer (MIXER_DRIVER_VERSION, "PSS-SPEAKERS and AD1848 (through MSS audio codec)", &pss_mixer_operations, sizeof (struct mixer_operations), devc)) < 0) { printk(KERN_ERR "Could not install PSS mixer\n"); return; } } pss_mixer_reset(devc); attach_ms_sound(hw_config, THIS_MODULE); /* Slot 0 */ if (hw_config->slots[0] != -1) { /* The MSS driver installed itself */ audio_devs[hw_config->slots[0]]->coproc = &pss_coproc_operations; if (pss_mixer && (num_mixers == (my_mix + 2))) { /* The MSS mixer installed */ devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev; } }}static inline void __exit unload_pss(struct address_info *hw_config){ release_region(hw_config->io_base, 0x10); release_region(hw_config->io_base+0x10, 0x9);}static inline void __exit unload_pss_mpu(struct address_info *hw_config){ unload_mpu401(hw_config);}static inline void __exit unload_pss_mss(struct address_info *hw_config){ unload_ms_sound(hw_config);}static struct address_info cfg;static struct address_info cfg2;static struct address_info cfg_mpu;static int pss_io __initdata = -1;static int mss_io __initdata = -1;static int mss_irq __initdata = -1;static int mss_dma __initdata = -1;static int mpu_io __initdata = -1;static int mpu_irq __initdata = -1;static int pss_no_sound __initdata = 0; /* Just configure non-sound components */static int pss_keep_settings = 1; /* Keep hardware settings at module exit */static char *pss_firmware = "/etc/sound/pss_synth";MODULE_PARM(pss_io, "i");MODULE_PARM_DESC(pss_io, "Set i/o base of PSS card (probably 0x220 or 0x240)");MODULE_PARM(mss_io, "i");MODULE_PARM_DESC(mss_io, "Set WSS (audio) i/o base (0x530, 0x604, 0xE80, 0xF40, or other. Address must end in 0 or 4 and must be from 0x100 to 0xFF4)");MODULE_PARM(mss_irq, "i");MODULE_PARM_DESC(mss_irq, "Set WSS (audio) IRQ (3, 5, 7, 9, 10, 11, 12)");MODULE_PARM(mss_dma, "i");MODULE_PARM_DESC(mss_dma, "Set WSS (audio) DMA (0, 1, 3)");MODULE_PARM(mpu_io, "i");MODULE_PARM_DESC(mpu_io, "Set MIDI i/o base (0x330 or other. Address must be on 4 location boundaries and must be from 0x100 to 0xFFC)");MODULE_PARM(mpu_irq, "i");MODULE_PARM_DESC(mpu_irq, "Set MIDI IRQ (3, 5, 7, 9, 10, 11, 12)");MODULE_PARM(pss_cdrom_port, "i");MODULE_PARM_DESC(pss_cdrom_port, "Set the PSS CDROM port i/o base (0x340 or other)");MODULE_PARM(pss_enable_joystick, "i");MODULE_PARM_DESC(pss_enable_joystick, "Enables the PSS joystick port (1 to enable, 0 to disable)");MODULE_PARM(pss_no_sound, "i");MODULE_PARM_DESC(pss_no_sound, "Configure sound compoents (0 - no, 1 - yes)");MODULE_PARM(pss_keep_settings, "i");MODULE_PARM_DESC(pss_keep_settings, "Keep hardware setting at driver unloading (0 - no, 1 - yes)");MODULE_PARM(pss_firmware, "s");MODULE_PARM_DESC(pss_firmware, "Location of the firmware file (default - /etc/sound/pss_synth)");MODULE_PARM(pss_mixer, "b");MODULE_PARM_DESC(pss_mixer, "Enable (1) or disable (0) PSS mixer (controlling of output volume, bass, treble, synth volume). The mixer is not available on all PSS cards.");MODULE_AUTHOR("Hannu Savolainen, Vladimir Michl");MODULE_DESCRIPTION("Module for PSS sound cards (based on AD1848, ADSP-2115 and ESC614). This module includes control of output amplifier and synth volume of the Beethoven ADSP-16 card (this may work with other PSS cards).\n");MODULE_LICENSE("GPL");static int fw_load = 0;static int pssmpu = 0, pssmss = 0;/* * Load a PSS sound card module */static int __init init_pss(void){ if(pss_no_sound) /* If configuring only nonsound components */ { cfg.io_base = pss_io; if(!probe_pss(&cfg)) return -ENODEV; printk(KERN_INFO "ECHO-PSS Rev. %d\n", inw(REG(PSS_ID)) & 0x00ff); printk(KERN_INFO "PSS: loading in no sound mode.\n"); disable_all_emulations(); configure_nonsound_components(); return 0; } cfg.io_base = pss_io; cfg2.io_base = mss_io; cfg2.irq = mss_irq; cfg2.dma = mss_dma; cfg_mpu.io_base = mpu_io; cfg_mpu.irq = mpu_irq; if (cfg.io_base == -1 || cfg2.io_base == -1 || cfg2.irq == -1 || cfg.dma == -1) { printk(KERN_INFO "pss: mss_io, mss_dma, mss_irq and pss_io must be set.\n"); return -EINVAL; } if (!pss_synth) { fw_load = 1; pss_synthLen = mod_firmware_load(pss_firmware, (void *) &pss_synth); } if (!probe_pss(&cfg)) return -ENODEV; attach_pss(&cfg); /* * Attach stuff */ if (probe_pss_mpu(&cfg_mpu)) { pssmpu = 1; attach_pss_mpu(&cfg_mpu); } if (probe_pss_mss(&cfg2)) { pssmss = 1; attach_pss_mss(&cfg2); } return 0;}static void __exit cleanup_pss(void){ if(!pss_no_sound) { if(fw_load && pss_synth) vfree(pss_synth); if(pssmss) unload_pss_mss(&cfg2); if(pssmpu) unload_pss_mpu(&cfg_mpu); unload_pss(&cfg); } if(!pss_keep_settings) /* Keep hardware settings if asked */ { disable_all_emulations(); printk(KERN_INFO "Resetting PSS sound card configurations.\n"); }}module_init(init_pss);module_exit(cleanup_pss);#ifndef MODULEstatic int __init setup_pss(char *str){ /* io, mss_io, mss_irq, mss_dma, mpu_io, mpu_irq */ int ints[7]; str = get_options(str, ARRAY_SIZE(ints), ints); pss_io = ints[1]; mss_io = ints[2]; mss_irq = ints[3]; mss_dma = ints[4]; mpu_io = ints[5]; mpu_irq = ints[6]; return 1;}__setup("pss=", setup_pss);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -