📄 mad16.c
字号:
for (i = 0; i < 5; i++) { if (i > 3) /* Not a valid port */ { printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base); return 0; } if (valid_ports[i] == hw_config->io_base) { tmp |= i << 4; /* WSS port select bits */ break; } } /* * Set optional CD-ROM and joystick settings. */ tmp &= ~0x0f; mad_write(MC1_PORT, tmp); tmp = mad_read(MC2_PORT); mad_write(MC2_PORT, tmp); mad_write(MC3_PORT, 0xf0); /* Disable SB */ if (board_type == C924) /* Specific C924 init values */ { mad_write(MC4_PORT, 0xA0); mad_write(MC5_PORT, 0x05); mad_write(MC6_PORT, 0x03); } if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp)) return 0; if (ad_flags & (AD_F_CS4231 | AD_F_CS4248)) cs4231_mode = 0x02; /* CS4248/CS4231 sync delay switch */ if (board_type == C929) { mad_write(MC4_PORT, 0xa2); mad_write(MC5_PORT, 0xA5 | cs4231_mode); mad_write(MC6_PORT, 0x03); /* Disable MPU401 */ } else { mad_write(MC4_PORT, 0x02); mad_write(MC5_PORT, 0x30 | cs4231_mode); } for (i = 0xf8d; i <= 0xf93; i++) if (!c924pnp) DDB(printk("port %03x after init = %02x\n", i, mad_read(i))) else DDB(printk("port %03x after init = %02x\n", i-0x80, mad_read(i))); wss_init(hw_config); return 1;}static void __init attach_mad16(struct address_info *hw_config){ static signed char interrupt_bits[12] = { -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20 }; signed char bits; static char dma_bits[4] = { 1, 2, 0, 3 }; int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2; unsigned char dma2_bit = 0; already_initialized = 1; if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp)) return; /* * Set the IRQ and DMA addresses. */ if (board_type == C930 || c924pnp) interrupt_bits[5] = 0x28; /* Also IRQ5 is possible on C930 */ bits = interrupt_bits[hw_config->irq]; if (bits == -1) return; outb((bits | 0x40), config_port); if ((inb(version_port) & 0x40) == 0) printk(KERN_ERR "[IRQ Conflict?]\n"); /* * Handle the capture DMA channel */ if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma) { if (!((dma == 0 && dma2 == 1) || (dma == 1 && dma2 == 0) || (dma == 3 && dma2 == 0))) { /* Unsupported combination. Try to swap channels */ int tmp = dma; dma = dma2; dma2 = tmp; } if ((dma == 0 && dma2 == 1) || (dma == 1 && dma2 == 0) || (dma == 3 && dma2 == 0)) { dma2_bit = 0x04; /* Enable capture DMA */ } else { printk("MAD16: Invalid capture DMA\n"); dma2 = dma; } } else dma2 = dma; outb((bits | dma_bits[dma] | dma2_bit), config_port); /* Write IRQ+DMA setup */ hw_config->slots[0] = ad1848_init("MAD16 WSS", hw_config->io_base + 4, hw_config->irq, dma, dma2, 0, hw_config->osp, THIS_MODULE); request_region(hw_config->io_base, 4, "MAD16 WSS config");}static int __init probe_mad16_mpu(struct address_info *hw_config){ static int mpu_attached = 0; unsigned char tmp; if (!already_initialized) /* The MSS port must be initialized first */ return 0; if (mpu_attached) /* Don't let them call this twice */ return 0; mpu_attached = 1; if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ {#ifdef CONFIG_MAD16_OLDCARD tmp = mad_read(MC3_PORT); /* * MAD16 SB base is defined by the WSS base. It cannot be changed * alone. * Ignore configured I/O base. Use the active setting. */ if (mad_read(MC1_PORT) & 0x20) hw_config->io_base = 0x240; else hw_config->io_base = 0x220; switch (hw_config->irq) { case 5: tmp = (tmp & 0x3f) | 0x80; break; case 7: tmp = (tmp & 0x3f); break; case 11: tmp = (tmp & 0x3f) | 0x40; break; default: printk(KERN_ERR "mad16/Mozart: Invalid MIDI IRQ\n"); return 0; } mad_write(MC3_PORT, tmp | 0x04); hw_config->driver_use_1 = SB_MIDI_ONLY; if (!sb_dsp_detect(hw_config, 0, 0, NULL)) return 0; if (mad_read(MC1_PORT) & 0x20) hw_config->io_base = 0x240; else hw_config->io_base = 0x220; hw_config->name = "Mad16/Mozart"; sb_dsp_init(hw_config, THIS_MODULE); return 1;#else /* assuming all later Mozart cards are identified as * either 82C928 or Mozart. If so, following code attempts * to set MPU register. TODO - add probing */ tmp = mad_read(MC8_PORT); switch (hw_config->irq) { case 5: tmp |= 0x08; break; case 7: tmp |= 0x10; break; case 9: tmp |= 0x18; break; case 10: tmp |= 0x20; break; case 11: tmp |= 0x28; break; default: printk(KERN_ERR "mad16/MOZART: invalid mpu_irq\n"); return 0; } switch (hw_config->io_base) { case 0x300: tmp |= 0x01; break; case 0x310: tmp |= 0x03; break; case 0x320: tmp |= 0x05; break; case 0x330: tmp |= 0x07; break; default: printk(KERN_ERR "mad16/MOZART: invalid mpu_io\n"); return 0; } mad_write(MC8_PORT, tmp); /* write MPU port parameters */ goto probe_401;#endif } tmp = mad_read(MC6_PORT) & 0x83; tmp |= 0x80; /* MPU-401 enable */ /* Set the MPU base bits */ switch (hw_config->io_base) { case 0x300: tmp |= 0x60; break; case 0x310: tmp |= 0x40; break; case 0x320: tmp |= 0x20; break; case 0x330: tmp |= 0x00; break; default: printk(KERN_ERR "MAD16: Invalid MIDI port 0x%x\n", hw_config->io_base); return 0; } /* Set the MPU IRQ bits */ switch (hw_config->irq) { case 5: tmp |= 0x10; break; case 7: tmp |= 0x18; break; case 9: tmp |= 0x00; break; case 10: tmp |= 0x08; break; default: printk(KERN_ERR "MAD16: Invalid MIDI IRQ %d\n", hw_config->irq); break; } mad_write(MC6_PORT, tmp); /* Write MPU401 config */#ifndef CONFIG_MAD16_OLDCARDprobe_401:#endif hw_config->driver_use_1 = SB_MIDI_ONLY; hw_config->name = "Mad16/Mozart"; return probe_uart401(hw_config, THIS_MODULE);}static void __exit unload_mad16(struct address_info *hw_config){ ad1848_unload(hw_config->io_base + 4, hw_config->irq, hw_config->dma, hw_config->dma2, 0); release_region(hw_config->io_base, 4); sound_unload_audiodev(hw_config->slots[0]);}static void __exit unload_mad16_mpu(struct address_info *hw_config){#ifdef CONFIG_MAD16_OLDCARD if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ { sb_dsp_unload(hw_config, 0); return; }#endif unload_uart401(hw_config);}static struct address_info cfg;static struct address_info cfg_mpu;static int found_mpu;static int __initdata mpu_io = 0;static int __initdata mpu_irq = 0;static int __initdata io = -1;static int __initdata dma = -1;static int __initdata dma16 = -1; /* Set this for modules that need it */static int __initdata irq = -1;static int __initdata cdtype = 0;static int __initdata cdirq = 0;static int __initdata cdport = 0x340;static int __initdata cddma = -1;static int __initdata opl4 = 0;static int __initdata joystick = 0;MODULE_PARM(mpu_io, "i");MODULE_PARM(mpu_irq, "i");MODULE_PARM(io,"i");MODULE_PARM(dma,"i");MODULE_PARM(dma16,"i");MODULE_PARM(irq,"i");MODULE_PARM(cdtype,"i");MODULE_PARM(cdirq,"i");MODULE_PARM(cdport,"i");MODULE_PARM(cddma,"i");MODULE_PARM(opl4,"i");MODULE_PARM(joystick,"i");MODULE_PARM(debug,"i");static int __initdata dma_map[2][8] ={ {0x03, -1, -1, -1, -1, 0x00, 0x01, 0x02}, {0x03, -1, 0x01, 0x00, -1, -1, -1, -1}};static int __initdata irq_map[16] ={ 0x00, -1, -1, 0x0A, -1, 0x04, -1, 0x08, -1, 0x10, 0x14, 0x18, -1, -1, -1, -1};static int __init init_mad16(void){ int dmatype = 0; printk(KERN_INFO "MAD16 audio driver Copyright (C) by Hannu Savolainen 1993-1996\n"); printk(KERN_INFO "CDROM "); switch (cdtype) { case 0x00: printk("Disabled"); cdirq = 0; break; case 0x02: printk("Sony CDU31A"); dmatype = 1; if(cddma == -1) cddma = 3; break; case 0x04: printk("Mitsumi"); dmatype = 0; if(cddma == -1) cddma = 5; break; case 0x06: printk("Panasonic Lasermate"); dmatype = 1; if(cddma == -1) cddma = 3; break; case 0x08: printk("Secondary IDE"); dmatype = 0; if(cddma == -1) cddma = 5; break; case 0x0A: printk("Primary IDE"); dmatype = 0; if(cddma == -1) cddma = 5; break; default: printk("\n"); printk(KERN_ERR "Invalid CDROM type\n"); return -EINVAL; } /* * Build the config words */ mad16_conf = (joystick ^ 1) | cdtype; mad16_cdsel = 0; if (opl4) mad16_cdsel |= 0x20; if(cdtype){ if (cddma > 7 || cddma < 0 || dma_map[dmatype][cddma] == -1) { printk("\n"); printk(KERN_ERR "Invalid CDROM DMA\n"); return -EINVAL; } if (cddma) printk(", DMA %d", cddma); else printk(", no DMA"); if (!cdirq) printk(", no IRQ"); else if (cdirq < 0 || cdirq > 15 || irq_map[cdirq] == -1) { printk(", invalid IRQ (disabling)"); cdirq = 0; } else printk(", IRQ %d", cdirq); mad16_cdsel |= dma_map[dmatype][cddma]; if (cdtype < 0x08) { switch (cdport) { case 0x340: mad16_cdsel |= 0x00; break; case 0x330: mad16_cdsel |= 0x40; break; case 0x360: mad16_cdsel |= 0x80; break; case 0x320: mad16_cdsel |= 0xC0; break; default: printk(KERN_ERR "Unknown CDROM I/O base %d\n", cdport); return -EINVAL; } } mad16_cdsel |= irq_map[cdirq]; } printk(".\n"); printk(KERN_INFO "Joystick port "); if (joystick == 1) printk("enabled.\n"); else { joystick = 0; printk("disabled.\n"); } cfg.io_base = io; cfg.irq = irq; cfg.dma = dma; cfg.dma2 = dma16; if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) { printk(KERN_ERR "I/O, DMA and irq are mandatory\n"); return -EINVAL; } if (!probe_mad16(&cfg)) return -ENODEV; cfg_mpu.io_base = mpu_io; cfg_mpu.irq = mpu_irq; attach_mad16(&cfg); found_mpu = probe_mad16_mpu(&cfg_mpu); return 0;}static void __exit cleanup_mad16(void){ if (found_mpu) unload_mad16_mpu(&cfg_mpu); unload_mad16(&cfg);}module_init(init_mad16);module_exit(cleanup_mad16);#ifndef MODULEstatic int __init setup_mad16(char *str){ /* io, irq */ int ints[7]; str = get_options(str, ARRAY_SIZE(ints), ints); io = ints[1]; irq = ints[2]; dma = ints[3]; dma16 = ints[4]; mpu_io = ints[5]; mpu_irq = ints[6]; return 1;}__setup("mad16=", setup_mad16);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -