📄 msnd_pinnacle.c
字号:
/* Pinnacle/Fiji Logical Device Configuration */static int __init msnd_write_cfg(int cfg, int reg, int value){ outb(reg, cfg); outb(value, cfg + 1); if (value != inb(cfg + 1)) { printk(KERN_ERR LOGNAME ": msnd_write_cfg: I/O error\n"); return -EIO; } return 0;}static int __init msnd_write_cfg_io0(int cfg, int num, WORD io){ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) return -EIO; if (msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io))) return -EIO; if (msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io))) return -EIO; return 0;}static int __init msnd_write_cfg_io1(int cfg, int num, WORD io){ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) return -EIO; if (msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io))) return -EIO; if (msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io))) return -EIO; return 0;}static int __init msnd_write_cfg_irq(int cfg, int num, WORD irq){ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) return -EIO; if (msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq))) return -EIO; if (msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE)) return -EIO; return 0;}static int __init msnd_write_cfg_mem(int cfg, int num, int mem){ WORD wmem; mem >>= 8; mem &= 0xfff; wmem = (WORD)mem; if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) return -EIO; if (msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem))) return -EIO; if (msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem))) return -EIO; if (wmem && msnd_write_cfg(cfg, IREG_MEMCONTROL, (MEMTYPE_HIADDR | MEMTYPE_16BIT))) return -EIO; return 0;}static int __init msnd_activate_logical(int cfg, int num){ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) return -EIO; if (msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE)) return -EIO; return 0;}static int __init msnd_write_cfg_logical(int cfg, int num, WORD io0, WORD io1, WORD irq, int mem){ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) return -EIO; if (msnd_write_cfg_io0(cfg, num, io0)) return -EIO; if (msnd_write_cfg_io1(cfg, num, io1)) return -EIO; if (msnd_write_cfg_irq(cfg, num, irq)) return -EIO; if (msnd_write_cfg_mem(cfg, num, mem)) return -EIO; if (msnd_activate_logical(cfg, num)) return -EIO; return 0;}typedef struct msnd_pinnacle_cfg_device { WORD io0, io1, irq; int mem;} msnd_pinnacle_cfg_t[4];static int __init msnd_pinnacle_cfg_devices(int cfg, int reset, msnd_pinnacle_cfg_t device){ int i; /* Reset devices if told to */ if (reset) { printk(KERN_INFO LOGNAME ": Resetting all devices\n"); for (i = 0; i < 4; ++i) if (msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0)) return -EIO; } /* Configure specified devices */ for (i = 0; i < 4; ++i) { switch (i) { case 0: /* DSP */ if (!(device[i].io0 && device[i].irq && device[i].mem)) continue; break; case 1: /* MPU */ if (!(device[i].io0 && device[i].irq)) continue; printk(KERN_INFO LOGNAME ": Configuring MPU to I/O 0x%x IRQ %d\n", device[i].io0, device[i].irq); break; case 2: /* IDE */ if (!(device[i].io0 && device[i].io1 && device[i].irq)) continue; printk(KERN_INFO LOGNAME ": Configuring IDE to I/O 0x%x, 0x%x IRQ %d\n", device[i].io0, device[i].io1, device[i].irq); break; case 3: /* Joystick */ if (!(device[i].io0)) continue; printk(KERN_INFO LOGNAME ": Configuring joystick to I/O 0x%x\n", device[i].io0); break; } /* Configure the device */ if (msnd_write_cfg_logical(cfg, i, device[i].io0, device[i].io1, device[i].irq, device[i].mem)) return -EIO; } return 0;}#endif#ifdef MODULEMODULE_AUTHOR ("Andrew Veliath <andrewtv@usa.net>");MODULE_DESCRIPTION ("Turtle Beach " LONGNAME " Linux Driver");MODULE_LICENSE("GPL");MODULE_PARM (io, "i");MODULE_PARM (irq, "i");MODULE_PARM (mem, "i");MODULE_PARM (write_ndelay, "i");MODULE_PARM (fifosize, "i");MODULE_PARM (calibrate_signal, "i");#ifndef MSND_CLASSICMODULE_PARM (digital, "i");MODULE_PARM (cfg, "i");MODULE_PARM (reset, "i");MODULE_PARM (mpu_io, "i");MODULE_PARM (mpu_irq, "i");MODULE_PARM (ide_io0, "i");MODULE_PARM (ide_io1, "i");MODULE_PARM (ide_irq, "i");MODULE_PARM (joystick_io, "i");#endifstatic int io __initdata = -1;static int irq __initdata = -1;static int mem __initdata = -1;static int write_ndelay __initdata = -1;#ifndef MSND_CLASSIC/* Pinnacle/Fiji non-PnP Config Port */static int cfg __initdata = -1;/* Extra Peripheral Configuration */static int reset __initdata = 0;static int mpu_io __initdata = 0;static int mpu_irq __initdata = 0;static int ide_io0 __initdata = 0;static int ide_io1 __initdata = 0;static int ide_irq __initdata = 0;static int joystick_io __initdata = 0;/* If we have the digital daugherboard... */static int digital __initdata = 0;#endifstatic int fifosize __initdata = DEFFIFOSIZE;static int calibrate_signal __initdata = 0;#else /* not a module */static int write_ndelay __initdata = -1;#ifdef MSND_CLASSICstatic int io __initdata = CONFIG_MSNDCLAS_IO;static int irq __initdata = CONFIG_MSNDCLAS_IRQ;static int mem __initdata = CONFIG_MSNDCLAS_MEM;#else /* Pinnacle/Fiji */static int io __initdata = CONFIG_MSNDPIN_IO;static int irq __initdata = CONFIG_MSNDPIN_IRQ;static int mem __initdata = CONFIG_MSNDPIN_MEM;/* Pinnacle/Fiji non-PnP Config Port */#ifdef CONFIG_MSNDPIN_NONPNP# ifndef CONFIG_MSNDPIN_CFG# define CONFIG_MSNDPIN_CFG 0x250# endif#else# ifdef CONFIG_MSNDPIN_CFG# undef CONFIG_MSNDPIN_CFG# endif# define CONFIG_MSNDPIN_CFG -1#endifstatic int cfg __initdata = CONFIG_MSNDPIN_CFG;/* If not a module, we don't need to bother with reset=1 */static int reset;/* Extra Peripheral Configuration (Default: Disable) */#ifndef CONFIG_MSNDPIN_MPU_IO# define CONFIG_MSNDPIN_MPU_IO 0#endifstatic int mpu_io __initdata = CONFIG_MSNDPIN_MPU_IO;#ifndef CONFIG_MSNDPIN_MPU_IRQ# define CONFIG_MSNDPIN_MPU_IRQ 0#endifstatic int mpu_irq __initdata = CONFIG_MSNDPIN_MPU_IRQ;#ifndef CONFIG_MSNDPIN_IDE_IO0# define CONFIG_MSNDPIN_IDE_IO0 0#endifstatic int ide_io0 __initdata = CONFIG_MSNDPIN_IDE_IO0;#ifndef CONFIG_MSNDPIN_IDE_IO1# define CONFIG_MSNDPIN_IDE_IO1 0#endifstatic int ide_io1 __initdata = CONFIG_MSNDPIN_IDE_IO1;#ifndef CONFIG_MSNDPIN_IDE_IRQ# define CONFIG_MSNDPIN_IDE_IRQ 0#endifstatic int ide_irq __initdata = CONFIG_MSNDPIN_IDE_IRQ;#ifndef CONFIG_MSNDPIN_JOYSTICK_IO# define CONFIG_MSNDPIN_JOYSTICK_IO 0#endifstatic int joystick_io __initdata = CONFIG_MSNDPIN_JOYSTICK_IO;/* Have SPDIF (Digital) Daughterboard */#ifndef CONFIG_MSNDPIN_DIGITAL# define CONFIG_MSNDPIN_DIGITAL 0#endifstatic int digital __initdata = CONFIG_MSNDPIN_DIGITAL;#endif /* MSND_CLASSIC */#ifndef CONFIG_MSND_FIFOSIZE# define CONFIG_MSND_FIFOSIZE DEFFIFOSIZE#endifstatic int fifosize __initdata = CONFIG_MSND_FIFOSIZE;#ifndef CONFIG_MSND_CALSIGNAL# define CONFIG_MSND_CALSIGNAL 0#endifstatic intcalibrate_signal __initdata = CONFIG_MSND_CALSIGNAL;#endif /* MODULE */static int __init msnd_init(void){ int err;#ifndef MSND_CLASSIC static msnd_pinnacle_cfg_t pinnacle_devs;#endif /* MSND_CLASSIC */ printk(KERN_INFO LOGNAME ": Turtle Beach " LONGNAME " Linux Driver Version " VERSION ", Copyright (C) 1998 Andrew Veliath\n"); if (io == -1 || irq == -1 || mem == -1) printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n");#ifdef MSND_CLASSIC if (io == -1 || !(io == 0x290 || io == 0x260 || io == 0x250 || io == 0x240 || io == 0x230 || io == 0x220 || io == 0x210 || io == 0x3e0)) { printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, or 0x3E0\n"); return -EINVAL; }#else if (io == -1 || io < 0x100 || io > 0x3e0 || (io % 0x10) != 0) { printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must within the range 0x100 to 0x3E0 and must be evenly divisible by 0x10\n"); return -EINVAL; }#endif /* MSND_CLASSIC */ if (irq == -1 || !(irq == 5 || irq == 7 || irq == 9 || irq == 10 || irq == 11 || irq == 12)) { printk(KERN_ERR LOGNAME ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n"); return -EINVAL; } if (mem == -1 || !(mem == 0xb0000 || mem == 0xc8000 || mem == 0xd0000 || mem == 0xd8000 || mem == 0xe0000 || mem == 0xe8000)) { printk(KERN_ERR LOGNAME ": \"mem\" - must be set to " "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or 0xe8000\n"); return -EINVAL; }#ifdef MSND_CLASSIC switch (irq) { case 5: dev.irqid = HPIRQ_5; break; case 7: dev.irqid = HPIRQ_7; break; case 9: dev.irqid = HPIRQ_9; break; case 10: dev.irqid = HPIRQ_10; break; case 11: dev.irqid = HPIRQ_11; break; case 12: dev.irqid = HPIRQ_12; break; } switch (mem) { case 0xb0000: dev.memid = HPMEM_B000; break; case 0xc8000: dev.memid = HPMEM_C800; break; case 0xd0000: dev.memid = HPMEM_D000; break; case 0xd8000: dev.memid = HPMEM_D800; break; case 0xe0000: dev.memid = HPMEM_E000; break; case 0xe8000: dev.memid = HPMEM_E800; break; }#else if (cfg == -1) { printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); } else if (cfg != 0x250 && cfg != 0x260 && cfg != 0x270) { printk(KERN_INFO LOGNAME ": Config port must be 0x250, 0x260 or 0x270 (or unspecified for PnP mode)\n"); return -EINVAL; } else { printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%x\n", cfg); /* DSP */ pinnacle_devs[0].io0 = io; pinnacle_devs[0].irq = irq; pinnacle_devs[0].mem = mem; /* The following are Pinnacle specific */ /* MPU */ pinnacle_devs[1].io0 = mpu_io; pinnacle_devs[1].irq = mpu_irq; /* IDE */ pinnacle_devs[2].io0 = ide_io0; pinnacle_devs[2].io1 = ide_io1; pinnacle_devs[2].irq = ide_irq; /* Joystick */ pinnacle_devs[3].io0 = joystick_io; if (check_region(cfg, 2)) { printk(KERN_ERR LOGNAME ": Config port 0x%x conflict\n", cfg); return -EIO; } request_region(cfg, 2, "Pinnacle/Fiji Config"); if (msnd_pinnacle_cfg_devices(cfg, reset, pinnacle_devs)) { printk(KERN_ERR LOGNAME ": Device configuration error\n"); release_region(cfg, 2); return -EIO; } release_region(cfg, 2); }#endif /* MSND_CLASSIC */ if (fifosize < 16) fifosize = 16; if (fifosize > 1024) fifosize = 1024; set_default_audio_parameters();#ifdef MSND_CLASSIC dev.type = msndClassic;#else dev.type = msndPinnacle;#endif dev.io = io; dev.numio = DSP_NUMIO; dev.irq = irq; dev.base = mem; dev.fifosize = fifosize * 1024; dev.calibrate_signal = calibrate_signal ? 1 : 0; dev.recsrc = 0; dev.dspq_data_buff = DSPQ_DATA_BUFF; dev.dspq_buff_size = DSPQ_BUFF_SIZE; if (write_ndelay == -1) write_ndelay = CONFIG_MSND_WRITE_NDELAY; if (write_ndelay) clear_bit(F_DISABLE_WRITE_NDELAY, &dev.flags); else set_bit(F_DISABLE_WRITE_NDELAY, &dev.flags);#ifndef MSND_CLASSIC if (digital) set_bit(F_HAVEDIGITAL, &dev.flags);#endif init_waitqueue_head(&dev.writeblock); init_waitqueue_head(&dev.readblock); init_waitqueue_head(&dev.writeflush); msnd_fifo_init(&dev.DAPF); msnd_fifo_init(&dev.DARF); spin_lock_init(&dev.lock); printk(KERN_INFO LOGNAME ": %u byte audio FIFOs (x2)\n", dev.fifosize); if ((err = msnd_fifo_alloc(&dev.DAPF, dev.fifosize)) < 0) { printk(KERN_ERR LOGNAME ": Couldn't allocate write FIFO\n"); return err; } if ((err = msnd_fifo_alloc(&dev.DARF, dev.fifosize)) < 0) { printk(KERN_ERR LOGNAME ": Couldn't allocate read FIFO\n"); msnd_fifo_free(&dev.DAPF); return err; } if ((err = probe_multisound()) < 0) { printk(KERN_ERR LOGNAME ": Probe failed\n"); msnd_fifo_free(&dev.DAPF); msnd_fifo_free(&dev.DARF); return err; } if ((err = attach_multisound()) < 0) { printk(KERN_ERR LOGNAME ": Attach failed\n"); msnd_fifo_free(&dev.DAPF); msnd_fifo_free(&dev.DARF); return err; } return 0;}static void __exit msdn_cleanup(void){ unload_multisound(); msnd_fifo_free(&dev.DAPF); msnd_fifo_free(&dev.DARF);}module_init(msnd_init);module_exit(msdn_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -