From f1382dc4850bb459d24a81c6cb0ef93ea7bd4a79 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 18 Mar 1998 17:17:51 +0000 Subject: o Merge with Linux 2.1.90. o Divide L1 cache sizes by 1024 before printing, makes the numbers a bit more credible ... --- drivers/sound/Config.in | 2 + drivers/sound/Makefile | 42 +- drivers/sound/ad1848.c | 113 ++- drivers/sound/audio.c | 1 - drivers/sound/bin2hex.c | 19 +- drivers/sound/cs4232.c | 17 +- drivers/sound/dev_table.c | 3 - drivers/sound/dmabuf.c | 35 +- drivers/sound/gus_card.c | 11 +- drivers/sound/hex2hex.c | 17 +- drivers/sound/maui.c | 25 +- drivers/sound/midibuf.c | 1 - drivers/sound/mpu401.c | 1778 ++++++++++++++++++++----------------------- drivers/sound/opl3.c | 78 +- drivers/sound/pas2_card.c | 4 +- drivers/sound/pss.c | 797 ++++++++++--------- drivers/sound/sb_audio.c | 16 +- drivers/sound/sb_card.c | 22 +- drivers/sound/sb_common.c | 32 +- drivers/sound/sound_calls.h | 6 +- drivers/sound/sound_timer.c | 8 + drivers/sound/soundcard.c | 22 +- drivers/sound/uart401.c | 337 ++++---- drivers/sound/uart6850.c | 9 +- drivers/sound/v_midi.c | 11 +- 25 files changed, 1652 insertions(+), 1754 deletions(-) (limited to 'drivers/sound') diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index 7ef5f8dd4..d4678da82 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -6,6 +6,8 @@ fi dep_tristate '100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SB $CONFIG_SOUND if [ "$CONFIG_SB" = "y" ]; then + bool 'Is the card a Soundman Games ?' CONFIG_SM_GAMES + bool 'Are you using the IBM Mwave "emulation" of SB ?' CONFIG_SB_MWAVE hex 'I/O base for SB Check from manual of the card' CONFIG_SB_BASE 220 int 'Sound Blaster IRQ Check from manual of the card' CONFIG_SB_IRQ 7 int 'Sound Blaster DMA 0, 1 or 3' CONFIG_SB_DMA 1 diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index e8ec0b12d..6b09e336b 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -117,22 +117,6 @@ else endif endif -ifeq ($(CONFIG_MPU401),y) -LX_OBJS += mpu401.o -else - ifeq ($(CONFIG_MPU401),m) - MX_OBJS += mpu401.o - else - ifeq ($(CONFIG_MPU_EMU),y) - LX_OBJS += mpu401.o - else - ifeq ($(CONFIG_MPU_EMU),m) - MX_OBJS += mpu401.o - endif - endif - endif -endif - ifeq ($(CONFIG_UART401),y) LX_OBJS += uart401.o else @@ -159,9 +143,31 @@ endif ifeq ($(CONFIG_SSCAPE),y) L_OBJS += sscape.o +LX_OBJS += ad1848.o +CONFIG_MPU401 = y else ifeq ($(CONFIG_SSCAPE),m) M_OBJS += sscape.o + MX_OBJS += ad1848.o + ifneq ($(CONFIG_MPU401),y) + CONFIG_MPU401 = m + endif + endif +endif + +ifeq ($(CONFIG_MPU401),y) +LX_OBJS += mpu401.o +else + ifeq ($(CONFIG_MPU401),m) + MX_OBJS += mpu401.o + else + ifeq ($(CONFIG_MPU_EMU),y) + LX_OBJS += mpu401.o + else + ifeq ($(CONFIG_MPU_EMU),m) + MX_OBJS += mpu401.o + endif + endif endif endif @@ -265,7 +271,7 @@ CONFIG_MAUI_BOOT_FILE := $(patsubst "%", %, $(CONFIG_MAUI_BOOT_FILE)) maui.o: maui_boot.h maui_boot.h: $(CONFIG_MAUI_BOOT_FILE) bin2hex - bin2hex maui_os < "$(CONFIG_MAUI_BOOT_FILE)" > $@ + bin2hex -i maui_os < "$(CONFIG_MAUI_BOOT_FILE)" > $@ @ ( \ echo 'ifeq ($(strip $(CONFIG_MAUI_BOOT_FILE)),$$(strip $$(CONFIG_MAUI_BOOT_FILE)))'; \ echo 'FILES_BOOT_UP_TO_DATE += $@'; \ @@ -297,7 +303,7 @@ CONFIG_TRIX_BOOT_FILE := $(patsubst "%", %, $(CONFIG_TRIX_BOOT_FILE)) trix.o: trix_boot.h trix_boot.h: $(CONFIG_TRIX_BOOT_FILE) hex2hex - hex2hex trix_boot < "$(CONFIG_TRIX_BOOT_FILE)" > $@ + hex2hex -i trix_boot < "$(CONFIG_TRIX_BOOT_FILE)" > $@ @ ( \ echo 'ifeq ($(strip $(CONFIG_TRIX_BOOT_FILE)),$$(strip $$(CONFIG_TRIX_BOOT_FILE)))'; \ echo 'FILES_BOOT_UP_TO_DATE += $@'; \ diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c index 6fdec35ec..d839ed208 100644 --- a/drivers/sound/ad1848.c +++ b/drivers/sound/ad1848.c @@ -23,6 +23,12 @@ */ /* * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * general sleep/wakeup clean up. + * Alan Cox : reformatted. Fixed SMP bugs. Moved to kernel alloc/free + * of irqs. Use dev_id. + * + * Status: + * Tested. Believed fully functional. */ #include @@ -144,9 +150,9 @@ static void ad1848_tmr_reprogram(int dev); static int ad_read(ad1848_info * devc, int reg) { - unsigned long flags; - int x; - int timeout = 900000; + unsigned long flags; + int x; + int timeout = 900000; while (timeout > 0 && inb(devc->base) == 0x80) /*Are we initializing */ timeout--; @@ -163,11 +169,10 @@ static int ad_read(ad1848_info * devc, int reg) static void ad_write(ad1848_info * devc, int reg, int data) { - unsigned long flags; - int timeout = 900000; + unsigned long flags; + int timeout = 900000; - while (timeout > 0 && - inb(devc->base) == 0x80) /*Are we initializing */ + while (timeout > 0 && inb(devc->base) == 0x80) /* Are we initializing */ timeout--; save_flags(flags); @@ -180,7 +185,7 @@ static void ad_write(ad1848_info * devc, int reg, int data) static void wait_for_calibration(ad1848_info * devc) { - int timeout = 0; + int timeout = 0; /* * Wait until the auto calibration process has finished. @@ -1751,7 +1756,11 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt else devc->audio_flags |= DMA_DUPLEX; } - + + portc = (ad1848_port_info *) kmalloc(sizeof(ad1848_port_info), GFP_KERNEL); + if(portc==NULL) + return -1; + if ((my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name, &ad1848_audio_driver, @@ -1762,12 +1771,11 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt dma_playback, dma_capture)) < 0) { + kfree(portc); + portc=NULL; return -1; } - portc = (ad1848_port_info *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(ad1848_port_info))); - sound_mem_sizes[sound_nblocks] = sizeof(ad1848_port_info); - if (sound_nblocks < 1024) - sound_nblocks++;; + audio_devs[my_dev]->portc = portc; memset((char *) portc, 0, sizeof(*portc)); @@ -1777,23 +1785,21 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt if (irq > 0) { - irq2dev[irq] = devc->dev_no = my_dev; - if (snd_set_irq_handler(devc->irq, adintr, - devc->name, - NULL) < 0) + devc->dev_no = my_dev; + if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0) { - printk(KERN_WARNING "ad1848: IRQ in use\n"); + printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n"); } if (devc->model != MD_1848 && devc->model != MD_C930) { - int x; - unsigned char tmp = ad_read(devc, 16); + int x; + unsigned char tmp = ad_read(devc, 16); devc->timer_ticks = 0; ad_write(devc, 21, 0x00); /* Timer MSB */ ad_write(devc, 20, 0x10); /* Timer LSB */ - +#ifndef __SMP__ ad_write(devc, 16, tmp | 0x40); /* Enable timer */ for (x = 0; x < 100000 && devc->timer_ticks == 0; x++); ad_write(devc, 16, tmp & ~0x40); /* Disable timer */ @@ -1805,6 +1811,9 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt DDB(printk("Interrupt test OK\n")); devc->irq_ok = 1; } +#else + devc->irq_ok=1; +#endif } else devc->irq_ok = 1; /* Couldn't test. assume it's OK */ @@ -1840,7 +1849,7 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt void ad1848_control(int cmd, int arg) { - ad1848_info *devc; + ad1848_info *devc; if (nr_ad1848_devs < 1) return; @@ -1850,7 +1859,7 @@ void ad1848_control(int cmd, int arg) switch (cmd) { case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */ - if (devc->model != MD_1845) + if (devc->model != MD_1845) return; ad_enter_MCE(devc); ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5)); @@ -1859,8 +1868,8 @@ void ad1848_control(int cmd, int arg) case AD1848_MIXER_REROUTE: { - int o = (arg >> 8) & 0xff; - int n = arg & 0xff; + int o = (arg >> 8) & 0xff; + int n = arg & 0xff; if (n == SOUND_MIXER_NONE) { /* Just hide this control */ @@ -1906,12 +1915,14 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int if (devc != NULL) { + if(audio_devs[dev]->portc!=NULL) + kfree(audio_devs[dev]->portc); release_region(devc->base, 4); if (!share_dma) { if (irq > 0) - snd_release_irq(devc->irq); + free_irq(devc->irq, NULL); sound_free_dma(audio_devs[dev]->dmap_out->dma); @@ -1926,35 +1937,15 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int void adintr(int irq, void *dev_id, struct pt_regs *dummy) { - unsigned char status; - ad1848_info *devc; - int dev; - int alt_stat = 0xff; - unsigned char c930_stat = 0; - int cnt = 0; - - if (irq < 0 || irq > 15) - { - dev = -1; - } - else - dev = irq2dev[irq]; - - if (dev < 0 || dev >= num_audiodevs) - { - for (irq = 0; irq < 17; irq++) - if (irq2dev[irq] != -1) - break; - - if (irq > 15) - { - /* printk("ad1848.c: Bogus interrupt %d\n", irq); */ - return; - } - dev = irq2dev[irq]; - devc = (ad1848_info *) audio_devs[dev]->devc; - } else - devc = (ad1848_info *) audio_devs[dev]->devc; + unsigned char status; + ad1848_info *devc; + int dev; + int alt_stat = 0xff; + unsigned char c930_stat = 0; + int cnt = 0; + + dev = (int)dev_id; + devc = (ad1848_info *) audio_devs[dev]->devc; interrupt_again: /* Jump back here if int status doesn't reset */ @@ -2542,12 +2533,12 @@ EXPORT_SYMBOL(unload_ms_sound); #ifdef MODULE -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(dma, "i"); -MODULE_PARM(dma2, "i"); -MODULE_PARM(type, "i"); -MODULE_PARM(deskpro_xl, "i"); +MODULE_PARM(io, "i"); /* I/O for a raw AD1848 card */ +MODULE_PARM(irq, "i"); /* IRQ to use */ +MODULE_PARM(dma, "i"); /* First DMA channel */ +MODULE_PARM(dma2, "i"); /* Second DMA channel */ +MODULE_PARM(type, "i"); /* Card type */ +MODULE_PARM(deskpro_xl, "i"); /* Special magic for Deskpro XL boxen */ int io = -1; int irq = -1; diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c index b27b1999a..9c9ccf095 100644 --- a/drivers/sound/audio.c +++ b/drivers/sound/audio.c @@ -21,7 +21,6 @@ #include #include -#include #include "sound_config.h" diff --git a/drivers/sound/bin2hex.c b/drivers/sound/bin2hex.c index 351dd24e0..fc49c99d9 100644 --- a/drivers/sound/bin2hex.c +++ b/drivers/sound/bin2hex.c @@ -2,12 +2,27 @@ int main( int argc, const char * argv [] ) { - const char * varname = argv[1]; + const char * varname; int i = 0; int c; + int id = 0; + if(argv[1] && strcmp(argv[1],"-i")==0) + { + argv++; + argc--; + id=1; + } + + if(argc==1) + { + fprintf(stderr, "bin2hex: [-i] firmware\n"); + exit(1); + } + + varname = argv[1]; printf( "/* automatically generated by bin2hex */\n" ); - printf( "static unsigned char %s [] =\n{\n", varname ); + printf( "static unsigned char %s [] %s =\n{\n", varname , id?"__initdata":""); while ( ( c = getchar( ) ) != EOF ) { diff --git a/drivers/sound/cs4232.c b/drivers/sound/cs4232.c index c8732dfe4..fdb5b738c 100644 --- a/drivers/sound/cs4232.c +++ b/drivers/sound/cs4232.c @@ -12,7 +12,14 @@ * CS4232 * CS4236 * CS4236B + * + * Note: You will need a PnP config setup to initialise some CS4232 boards + * anyway. + * + * Changes + * Alan Cox Modularisation, Basic cleanups. */ + /* * Copyright (C) by Hannu Savolainen 1993-1997 * @@ -20,6 +27,7 @@ * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. */ + #include #include @@ -99,6 +107,8 @@ int probe_cs4232(struct address_info *hw_config) * just one CS4232 compatible device can exist on the system. Also this * method conflicts with possible PnP support in the OS. For this reason * driver is just a temporary kludge. + * + * Also the Cirrus/Crystal method doesnt always work. Try ISAPnP first ;) */ /* @@ -106,8 +116,8 @@ int probe_cs4232(struct address_info *hw_config) * first time. */ - for (n = 0; n < 4; n++) { - + for (n = 0; n < 4; n++) + { /* * Wake up the card by sending a 32 byte Crystal key to the key port. */ @@ -298,8 +308,7 @@ struct address_info cfg; * loaded ready. */ -int -init_module(void) +int init_module(void) { if (io == -1 || irq == -1 || dma == -1 || dma2 == -1) { diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c index 666d7765e..7f3957bfd 100644 --- a/drivers/sound/dev_table.c +++ b/drivers/sound/dev_table.c @@ -148,9 +148,6 @@ void sound_unload_drivers(void) } } - for (i=0;iraw_buf_phys = virt_to_bus(start_addr); for (i = MAP_NR(start_addr); i <= MAP_NR(end_addr); i++) - set_bit(PG_reserved, &mem_map[i].flags);; + set_bit(PG_reserved, &mem_map[i].flags); return 0; } @@ -115,8 +115,6 @@ static void sound_free_dmap(struct dma_buffparms *dmap) if (dmap->raw_buf == NULL) return; - if (dmap->mapping_flags & DMA_MAP_MAPPED) - return; /* Don't free mmapped buffer. Will use it next time */ for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize; sz++, size <<= 1); start_addr = (unsigned long) dmap->raw_buf; @@ -127,6 +125,8 @@ static void sound_free_dmap(struct dma_buffparms *dmap) free_pages((unsigned long) dmap->raw_buf, sz); dmap->raw_buf = NULL; + /* Remember the buffer is deleted so we dont Oops later */ + dmap->fragment_size = 0; } @@ -206,6 +206,7 @@ static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap dmap->dma_mode = DMODE_NONE; dmap->flags &= ~DMA_BUSY; disable_dma(dmap->dma); + sound_free_dmap(dmap); } @@ -832,12 +833,12 @@ int DMAbuf_move_wrpointer(int dev, int l) dmap->user_counter += l; dmap->flags |= DMA_DIRTY; - if (dmap->user_counter >= dmap->max_byte_counter) { + if (dmap->byte_counter >= dmap->max_byte_counter) { /* Wrap the byte counters */ - long decr = dmap->user_counter; - dmap->user_counter = (dmap->user_counter % dmap->bytes_in_use) + dmap->bytes_in_use; - decr -= dmap->user_counter; - dmap->byte_counter -= decr; + long decr = dmap->byte_counter; + dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); + decr -= dmap->byte_counter; + dmap->user_counter -= decr; } end_ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size; @@ -928,7 +929,7 @@ static void do_outputintr(int dev, int dummy) dmap->byte_counter += dmap->bytes_in_use; if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ long decr = dmap->byte_counter; - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; + dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); decr -= dmap->byte_counter; dmap->user_counter -= decr; } @@ -952,7 +953,7 @@ static void do_outputintr(int dev, int dummy) dmap->byte_counter += dmap->bytes_in_use; if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ long decr = dmap->byte_counter; - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; + dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); decr -= dmap->byte_counter; dmap->user_counter -= decr; } @@ -1211,18 +1212,4 @@ unsigned int DMAbuf_poll(struct file * file, int dev, poll_table *wait) return poll_input(file, dev, wait) | poll_output(file, dev, wait); } -void DMAbuf_deinit(int dev) -{ - struct audio_operations *adev = audio_devs[dev]; - /* This routine is called when driver is being unloaded */ - if (!adev) - return; -#ifdef RUNTIME_DMA_ALLOC - sound_free_dmap(adev->dmap_out); - - if (adev->flags & DMA_DUPLEX) - sound_free_dmap(adev->dmap_in); -#endif -} - #endif diff --git a/drivers/sound/gus_card.c b/drivers/sound/gus_card.c index 0f4f769eb..92e6dbab6 100644 --- a/drivers/sound/gus_card.c +++ b/drivers/sound/gus_card.c @@ -30,7 +30,7 @@ int gus_pnp_flag = 0; void attach_gus_card(struct address_info *hw_config) { - snd_set_irq_handler(hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp); + snd_set_irq_handler(hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp, hw_config); gus_wave_init(hw_config); @@ -101,7 +101,7 @@ void unload_gus(struct address_info *hw_config) release_region(hw_config->io_base, 16); release_region(hw_config->io_base + 0x100, 12); /* 0x10c-> is MAX */ - snd_release_irq(hw_config->irq); + snd_release_irq(hw_config->irq, hw_config); sound_free_dma(hw_config->dma); @@ -111,14 +111,15 @@ void unload_gus(struct address_info *hw_config) void gusintr(int irq, void *dev_id, struct pt_regs *dummy) { - unsigned char src; - extern int gus_timer_enabled; + unsigned char src; + extern int gus_timer_enabled; + struct address_info *hw_config=dev_id; sti(); #ifdef CONFIG_GUSMAX if (have_gus_max) - adintr(irq, NULL, NULL); + adintr(irq, (void *)hw_config->slots[3], NULL); #endif while (1) diff --git a/drivers/sound/hex2hex.c b/drivers/sound/hex2hex.c index 19753bfc2..4b182625b 100644 --- a/drivers/sound/hex2hex.c +++ b/drivers/sound/hex2hex.c @@ -66,14 +66,27 @@ int loadhex(FILE *inf, unsigned char *buf) int main( int argc, const char * argv [] ) { - const char * varline = argv[1]; + const char * varline; int i,l; + int id=0; + if(argv[1] && strcmp(argv[1], "-i")==0) + { + argv++; + argc--; + id=1; + } + if(argv[1]==NULL) + { + fprintf(stderr,"hex2hex: [-i] filename\n"); + exit(1); + } + varline = argv[1; l = loadhex(stdin, buf); printf("/*\n *\t Computer generated file. Do not edit.\n */\n"); printf("static int %s_len = %d;\n", varline, l); - printf("static unsigned char %s[] = {\n", varline); + printf("static unsigned char %s[] %s = {\n", varline, id?"__initdata":""); for (i=0;i #include @@ -327,7 +335,7 @@ int probe_maui(struct address_info *hw_config) maui_base = hw_config->io_base; maui_osp = hw_config->osp; - if (snd_set_irq_handler(hw_config->irq, mauiintr, "Maui", maui_osp) < 0) + if (request_irq(hw_config->irq, mauiintr, 0, "Maui", NULL) < 0) return 0; /* @@ -342,26 +350,26 @@ int probe_maui(struct address_info *hw_config) maui_read() == -1 || maui_read() == -1) if (!maui_init(hw_config->irq)) { - snd_release_irq(hw_config->irq); + free_irq(hw_config->irq, NULL); return 0; } } if (!maui_write(0xCF)) /* Report hardware version */ { printk(KERN_ERR "No WaveFront firmware detected (card uninitialized?)\n"); - snd_release_irq(hw_config->irq); + free_irq(hw_config->irq, NULL); return 0; } if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1) { printk(KERN_ERR "No WaveFront firmware detected (card uninitialized?)\n"); - snd_release_irq(hw_config->irq); + free_irq(hw_config->irq, NULL); return 0; } if (tmp1 == 0xff || tmp2 == 0xff) { - snd_release_irq(hw_config->irq); - return 0; + free_irq(hw_config->irq, NULL); + return 0; } if (trace_init) printk(KERN_DEBUG "WaveFront hardware version %d.%d\n", tmp1, tmp2); @@ -439,7 +447,7 @@ void unload_maui(struct address_info *hw_config) if (irq < 0) irq = -irq; if (irq > 0) - snd_release_irq(irq); + free_irq(irq, NULL); } #ifdef MODULE @@ -452,8 +460,7 @@ static int fw_load = 0; struct address_info cfg; /* - * Install a CS4232 based card. Need to have ad1848 and mpu401 - * loaded ready. + * Install a Maui card. Needs mpu401 loaded already. */ int init_module(void) diff --git a/drivers/sound/midibuf.c b/drivers/sound/midibuf.c index 0c024a454..09dea3a34 100644 --- a/drivers/sound/midibuf.c +++ b/drivers/sound/midibuf.c @@ -15,7 +15,6 @@ */ #include #include -#include #define MIDIBUF_C diff --git a/drivers/sound/mpu401.c b/drivers/sound/mpu401.c index 9ae597404..ce92010fc 100644 --- a/drivers/sound/mpu401.c +++ b/drivers/sound/mpu401.c @@ -9,10 +9,12 @@ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * + * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) + * Alan Cox modularisation, use normal request_irq, use dev_id */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - */ + #include #include @@ -32,30 +34,30 @@ static int timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL; #endif struct mpu_config - { - int base; /* +{ + int base; /* * I/O base */ - int irq; - int opened; /* - * Open mode - */ - int devno; - int synthno; - int uart_mode; - int initialized; - int mode; + int irq; + int opened; /* + * Open mode + */ + int devno; + int synthno; + int uart_mode; + int initialized; + int mode; #define MODE_MIDI 1 #define MODE_SYNTH 2 - unsigned char version, revision; - unsigned int capabilities; + unsigned char version, revision; + unsigned int capabilities; #define MPU_CAP_INTLG 0x10000000 #define MPU_CAP_SYNC 0x00000010 #define MPU_CAP_FSK 0x00000020 #define MPU_CAP_CLS 0x00000040 #define MPU_CAP_SMPTE 0x00000080 #define MPU_CAP_2PORT 0x00000001 - int timer_flag; + int timer_flag; #define MBUF_MAX 10 #define BUFTEST(dc) if (dc->m_ptr >= MBUF_MAX || dc->m_ptr < 0) \ @@ -75,28 +77,27 @@ struct mpu_config #define COMDPORT(base) (base+1) #define STATPORT(base) (base+1) -static int -mpu401_status(struct mpu_config *devc) +static int mpu401_status(struct mpu_config *devc) { return inb(STATPORT(devc->base)); } + #define input_avail(devc) (!(mpu401_status(devc)&INPUT_AVAIL)) #define output_ready(devc) (!(mpu401_status(devc)&OUTPUT_READY)) -static void -write_command(struct mpu_config *devc, unsigned char cmd) + +static void write_command(struct mpu_config *devc, unsigned char cmd) { - outb((cmd), COMDPORT(devc->base)); + outb(cmd, COMDPORT(devc->base)); } -static int -read_data(struct mpu_config *devc) + +static int read_data(struct mpu_config *devc) { return inb(DATAPORT(devc->base)); } -static void -write_data(struct mpu_config *devc, unsigned char byte) +static void write_data(struct mpu_config *devc, unsigned char byte) { - outb((byte), DATAPORT(devc->base)); + outb(byte, DATAPORT(devc->base)); } #define OUTPUT_READY 0x40 @@ -107,22 +108,27 @@ write_data(struct mpu_config *devc, unsigned char byte) static struct mpu_config dev_conf[MAX_MIDI_DEV] = { - {0}}; + {0} +}; -static int n_mpu_devs = 0; -static volatile int irq2dev[17] = -{-1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int n_mpu_devs = 0; -static int reset_mpu401(struct mpu_config *devc); -static void set_uart_mode(int dev, struct mpu_config *devc, int arg); +static int reset_mpu401(struct mpu_config *devc); +static void set_uart_mode(int dev, struct mpu_config *devc, int arg); -static int mpu_timer_init(int midi_dev); -static void mpu_timer_interrupt(void); -static void timer_ext_event(struct mpu_config *devc, int event, int parm); +static int mpu_timer_init(int midi_dev); +static void mpu_timer_interrupt(void); +static void timer_ext_event(struct mpu_config *devc, int event, int parm); -static struct synth_info mpu_synth_info_proto = -{"MPU-401 MIDI interface", 0, SYNTH_TYPE_MIDI, MIDI_TYPE_MPU401, 0, 128, 0, 128, SYNTH_CAP_INPUT}; +static struct synth_info mpu_synth_info_proto = { + "MPU-401 MIDI interface", + 0, + SYNTH_TYPE_MIDI, + MIDI_TYPE_MPU401, + 0, 128, + 0, 128, + SYNTH_CAP_INPUT +}; static struct synth_info mpu_synth_info[MAX_MIDI_DEV]; @@ -158,10 +164,10 @@ static unsigned char len_tab[] = /* # of data bytes following a status #else #define STORE(cmd) \ { \ - int len; \ - unsigned char obuf[8]; \ - cmd; \ - seq_input_event(obuf, len); \ + int len; \ + unsigned char obuf[8]; \ + cmd; \ + seq_input_event(obuf, len); \ } #endif @@ -169,242 +175,242 @@ static unsigned char len_tab[] = /* # of data bytes following a status #define _seqbufptr 0 #define _SEQ_ADVBUF(x) len=x -static int -mpu_input_scanner(struct mpu_config *devc, unsigned char midic) +static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic) { switch (devc->m_state) - { - case ST_INIT: - switch (midic) - { - case 0xf8: - /* Timer overflow */ - break; - - case 0xfc: - printk(""); - break; - - case 0xfd: - if (devc->timer_flag) - mpu_timer_interrupt(); - break; - - case 0xfe: - return MPU_ACK; - break; - - case 0xf0: - case 0xf1: - case 0xf2: - case 0xf3: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - printk("", midic & 0x0f); - break; - - case 0xf9: - printk(""); - break; - - case 0xff: - devc->m_state = ST_SYSMSG; - break; - - default: - if (midic <= 0xef) - { - /* printk( "mpu time: %d ", midic); */ - devc->m_state = ST_TIMED; - } else - printk(" ", midic); - } - break; - - case ST_TIMED: - { - int msg = ((int) (midic & 0xf0) >> 4); - - devc->m_state = ST_DATABYTE; - - if (msg < 8) /* Data byte */ - { - /* printk( "midi msg (running status) "); */ - msg = ((int) (devc->last_status & 0xf0) >> 4); - msg -= 8; - devc->m_left = len_tab[msg] - 1; - - devc->m_ptr = 2; - devc->m_buf[0] = devc->last_status; - devc->m_buf[1] = midic; - - if (devc->m_left <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - } else if (msg == 0xf) /* MPU MARK */ - { - devc->m_state = ST_INIT; - - switch (midic) - { - case 0xf8: - /* printk( "NOP "); */ - break; - - case 0xf9: - /* printk( "meas end "); */ - break; - - case 0xfc: - /* printk( "data end "); */ - break; - - default: - printk("Unknown MPU mark %02x\n", midic); - } - } else - { - devc->last_status = midic; - /* printk( "midi msg "); */ - msg -= 8; - devc->m_left = len_tab[msg]; - - devc->m_ptr = 1; - devc->m_buf[0] = midic; - - if (devc->m_left <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - } - } - break; - - case ST_SYSMSG: - switch (midic) - { - case 0xf0: - printk(""); - devc->m_state = ST_SYSEX; - break; - - case 0xf1: - devc->m_state = ST_MTC; - break; - - case 0xf2: - devc->m_state = ST_SONGPOS; - devc->m_ptr = 0; - break; - - case 0xf3: - devc->m_state = ST_SONGSEL; - break; - - case 0xf6: - /* printk( "tune_request\n"); */ - devc->m_state = ST_INIT; - - /* - * Real time messages - */ - case 0xf8: - /* midi clock */ - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_CLOCK, 0); - break; - - case 0xfA: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_START, 0); - break; - - case 0xFB: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_CONTINUE, 0); - break; - - case 0xFC: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_STOP, 0); - break; - - case 0xFE: - /* active sensing */ - devc->m_state = ST_INIT; - break; - - case 0xff: - /* printk( "midi hard reset"); */ - devc->m_state = ST_INIT; - break; - - default: - printk("unknown MIDI sysmsg %0x\n", midic); - devc->m_state = ST_INIT; - } - break; - - case ST_MTC: - devc->m_state = ST_INIT; - printk("MTC frame %x02\n", midic); - break; - - case ST_SYSEX: - if (midic == 0xf7) - { - printk(""); - devc->m_state = ST_INIT; - } else - printk("%02x ", midic); - break; - - case ST_SONGPOS: - BUFTEST(devc); - devc->m_buf[devc->m_ptr++] = midic; - if (devc->m_ptr == 2) - { - devc->m_state = ST_INIT; - devc->m_ptr = 0; - timer_ext_event(devc, TMR_SPP, - ((devc->m_buf[1] & 0x7f) << 7) | - (devc->m_buf[0] & 0x7f)); - } - break; - - case ST_DATABYTE: - BUFTEST(devc); - devc->m_buf[devc->m_ptr++] = midic; - if ((--devc->m_left) <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - break; - - default: - printk("Bad state %d ", devc->m_state); - devc->m_state = ST_INIT; - } + { + case ST_INIT: + switch (midic) + { + case 0xf8: + /* Timer overflow */ + break; + + case 0xfc: + printk(""); + break; + + case 0xfd: + if (devc->timer_flag) + mpu_timer_interrupt(); + break; + + case 0xfe: + return MPU_ACK; + + case 0xf0: + case 0xf1: + case 0xf2: + case 0xf3: + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + printk("", midic & 0x0f); + break; + + case 0xf9: + printk(""); + break; + + case 0xff: + devc->m_state = ST_SYSMSG; + break; + + default: + if (midic <= 0xef) + { + /* printk( "mpu time: %d ", midic); */ + devc->m_state = ST_TIMED; + } + else + printk(" ", midic); + } + break; + + case ST_TIMED: + { + int msg = ((int) (midic & 0xf0) >> 4); + + devc->m_state = ST_DATABYTE; + + if (msg < 8) /* Data byte */ + { + /* printk( "midi msg (running status) "); */ + msg = ((int) (devc->last_status & 0xf0) >> 4); + msg -= 8; + devc->m_left = len_tab[msg] - 1; + + devc->m_ptr = 2; + devc->m_buf[0] = devc->last_status; + devc->m_buf[1] = midic; + + if (devc->m_left <= 0) + { + devc->m_state = ST_INIT; + do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); + devc->m_ptr = 0; + } + } + else if (msg == 0xf) /* MPU MARK */ + { + devc->m_state = ST_INIT; + + switch (midic) + { + case 0xf8: + /* printk( "NOP "); */ + break; + + case 0xf9: + /* printk( "meas end "); */ + break; + + case 0xfc: + /* printk( "data end "); */ + break; + + default: + printk("Unknown MPU mark %02x\n", midic); + } + } + else + { + devc->last_status = midic; + /* printk( "midi msg "); */ + msg -= 8; + devc->m_left = len_tab[msg]; + + devc->m_ptr = 1; + devc->m_buf[0] = midic; + + if (devc->m_left <= 0) + { + devc->m_state = ST_INIT; + do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); + devc->m_ptr = 0; + } + } + } + break; + + case ST_SYSMSG: + switch (midic) + { + case 0xf0: + printk(""); + devc->m_state = ST_SYSEX; + break; + + case 0xf1: + devc->m_state = ST_MTC; + break; + + case 0xf2: + devc->m_state = ST_SONGPOS; + devc->m_ptr = 0; + break; + + case 0xf3: + devc->m_state = ST_SONGSEL; + break; + + case 0xf6: + /* printk( "tune_request\n"); */ + devc->m_state = ST_INIT; + + /* + * Real time messages + */ + case 0xf8: + /* midi clock */ + devc->m_state = ST_INIT; + timer_ext_event(devc, TMR_CLOCK, 0); + break; + + case 0xfA: + devc->m_state = ST_INIT; + timer_ext_event(devc, TMR_START, 0); + break; + + case 0xFB: + devc->m_state = ST_INIT; + timer_ext_event(devc, TMR_CONTINUE, 0); + break; + + case 0xFC: + devc->m_state = ST_INIT; + timer_ext_event(devc, TMR_STOP, 0); + break; + + case 0xFE: + /* active sensing */ + devc->m_state = ST_INIT; + break; + + case 0xff: + /* printk( "midi hard reset"); */ + devc->m_state = ST_INIT; + break; + + default: + printk("unknown MIDI sysmsg %0x\n", midic); + devc->m_state = ST_INIT; + } + break; + + case ST_MTC: + devc->m_state = ST_INIT; + printk("MTC frame %x02\n", midic); + break; + + case ST_SYSEX: + if (midic == 0xf7) + { + printk(""); + devc->m_state = ST_INIT; + } + else + printk("%02x ", midic); + break; + + case ST_SONGPOS: + BUFTEST(devc); + devc->m_buf[devc->m_ptr++] = midic; + if (devc->m_ptr == 2) + { + devc->m_state = ST_INIT; + devc->m_ptr = 0; + timer_ext_event(devc, TMR_SPP, + ((devc->m_buf[1] & 0x7f) << 7) | + (devc->m_buf[0] & 0x7f)); + } + break; + case ST_DATABYTE: + BUFTEST(devc); + devc->m_buf[devc->m_ptr++] = midic; + if ((--devc->m_left) <= 0) + { + devc->m_state = ST_INIT; + do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); + devc->m_ptr = 0; + } + break; + + default: + printk("Bad state %d ", devc->m_state); + devc->m_state = ST_INIT; + } return 1; } -static void -mpu401_input_loop(struct mpu_config *devc) +static void mpu401_input_loop(struct mpu_config *devc) { - unsigned long flags; - int busy; - int n; + unsigned long flags; + int busy; + int n; save_flags(flags); cli(); @@ -418,72 +424,45 @@ mpu401_input_loop(struct mpu_config *devc) n = 50; while (input_avail(devc) && n-- > 0) - { - unsigned char c = read_data(devc); - - if (devc->mode == MODE_SYNTH) - { - mpu_input_scanner(devc, c); - } else if (devc->opened & OPEN_READ && devc->inputintr != NULL) - devc->inputintr(devc->devno, c); - } + { + unsigned char c = read_data(devc); + if (devc->mode == MODE_SYNTH) + { + mpu_input_scanner(devc, c); + } + else if (devc->opened & OPEN_READ && devc->inputintr != NULL) + devc->inputintr(devc->devno, c); + } devc->m_busy = 0; } -void -mpuintr(int irq, void *dev_id, struct pt_regs *dummy) +void mpuintr(int irq, void *dev_id, struct pt_regs *dummy) { struct mpu_config *devc; - int dev; + int dev = (int) dev_id; sti(); - -/* - * FreeBSD (and some others) pass unit number to the interrupt handler. - * In this case we have to scan the table for first handler. - */ - - if (irq < 1 || irq > 15) - { - dev = -1; - } else - dev = irq2dev[irq]; - - if (dev == -1) - { - int origirq = irq; - - for (irq = 0; irq <= 16; irq++) - if (irq2dev[irq] != -1) - break; - if (irq > 15) - { - printk("MPU-401: Bogus interrupt #%d?\n", origirq); - return; - } - dev = irq2dev[irq]; - devc = &dev_conf[dev]; - } else - devc = &dev_conf[dev]; + devc = &dev_conf[dev]; if (input_avail(devc)) + { if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH)) mpu401_input_loop(devc); else - { - /* Dummy read (just to acknowledge the interrupt) */ - read_data(devc); - } + { + /* Dummy read (just to acknowledge the interrupt) */ + read_data(devc); + } + } } -static int -mpu401_open(int dev, int mode, +static int mpu401_open(int dev, int mode, void (*input) (int dev, unsigned char data), void (*output) (int dev) ) { - int err; + int err; struct mpu_config *devc; if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) @@ -492,36 +471,34 @@ mpu401_open(int dev, int mode, devc = &dev_conf[dev]; if (devc->opened) - { - printk("MPU-401: Midi busy\n"); return -EBUSY; - } /* - * Verify that the device is really running. - * Some devices (such as Ensoniq SoundScape don't - * work before the on board processor (OBP) is initialized - * by downloading its microcode. + * Verify that the device is really running. + * Some devices (such as Ensoniq SoundScape don't + * work before the on board processor (OBP) is initialized + * by downloading its microcode. */ if (!devc->initialized) - { - if (mpu401_status(devc) == 0xff) /* Bus float */ - { - printk("MPU-401: Device not initialized properly\n"); - return -EIO; - } - reset_mpu401(devc); - } - irq2dev[devc->irq] = dev; + { + if (mpu401_status(devc) == 0xff) /* Bus float */ + { + printk(KERN_ERR "mpu401: Device not initialized properly\n"); + return -EIO; + } + reset_mpu401(devc); + } if (midi_devs[dev]->coproc) + { if ((err = midi_devs[dev]->coproc-> open(midi_devs[dev]->coproc->devc, COPR_MIDI)) < 0) - { - printk("MPU-401: Can't access coprocessor device\n"); - - return err; - } + { + printk("MPU-401: Can't access coprocessor device\n"); + return err; + } + } + set_uart_mode(dev, devc, 1); devc->mode = MODE_MIDI; devc->synthno = 0; @@ -534,19 +511,16 @@ mpu401_open(int dev, int mode, return 0; } -static void -mpu401_close(int dev) +static void mpu401_close(int dev) { struct mpu_config *devc; devc = &dev_conf[dev]; - if (devc->uart_mode) reset_mpu401(devc); /* * This disables the UART mode */ devc->mode = 0; - devc->inputintr = NULL; if (midi_devs[dev]->coproc) @@ -554,11 +528,10 @@ mpu401_close(int dev) devc->opened = 0; } -static int -mpu401_out(int dev, unsigned char midi_byte) +static int mpu401_out(int dev, unsigned char midi_byte) { - int timeout; - unsigned long flags; + int timeout; + unsigned long flags; struct mpu_config *devc; @@ -574,21 +547,20 @@ mpu401_out(int dev, unsigned char midi_byte) save_flags(flags); cli(); if (!output_ready(devc)) - { - printk("MPU-401: Send data timeout\n"); - restore_flags(flags); - return 0; - } + { + printk(KERN_WARNING "mpu401: Send data timeout\n"); + restore_flags(flags); + return 0; + } write_data(devc, midi_byte); restore_flags(flags); return 1; } -static int -mpu401_command(int dev, mpu_command_rec * cmd) +static int mpu401_command(int dev, mpu_command_rec * cmd) { - int i, timeout, ok; - int ret = 0; + int i, timeout, ok; + int ret = 0; unsigned long flags; struct mpu_config *devc; @@ -597,10 +569,10 @@ mpu401_command(int dev, mpu_command_rec * cmd) if (devc->uart_mode) /* * Not possible in UART mode */ - { - printk("MPU-401 commands not possible in the UART mode\n"); - return -EINVAL; - } + { + printk(KERN_WARNING "mpu401: commands not possible in the UART mode\n"); + return -EINVAL; + } /* * Test for input since pending input seems to block the output. */ @@ -613,83 +585,87 @@ mpu401_command(int dev, mpu_command_rec * cmd) */ timeout = 50000; - retry: +retry: if (timeout-- <= 0) - { - printk("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd); - return -EIO; - } + { + printk(KERN_WARNING "mpu401: Command (0x%x) timeout\n", (int) cmd->cmd); + return -EIO; + } save_flags(flags); cli(); if (!output_ready(devc)) - { + { restore_flags(flags); goto retry; - } + } write_command(devc, cmd->cmd); ok = 0; for (timeout = 50000; timeout > 0 && !ok; timeout--) + { if (input_avail(devc)) - { - if (devc->opened && devc->mode == MODE_SYNTH) - { - if (mpu_input_scanner(devc, read_data(devc)) == MPU_ACK) - ok = 1; - } else - { /* Device is not currently open. Use simpler method */ - if (read_data(devc) == MPU_ACK) - ok = 1; - } - } + { + if (devc->opened && devc->mode == MODE_SYNTH) + { + if (mpu_input_scanner(devc, read_data(devc)) == MPU_ACK) + ok = 1; + } + else + { + /* Device is not currently open. Use simpler method */ + if (read_data(devc) == MPU_ACK) + ok = 1; + } + } + } if (!ok) - { - restore_flags(flags); - /* printk( "MPU: No ACK to command (0x%x)\n", (int) cmd->cmd); */ - return -EIO; - } + { + restore_flags(flags); + return -EIO; + } if (cmd->nr_args) + { for (i = 0; i < cmd->nr_args; i++) - { - for (timeout = 3000; timeout > 0 && !output_ready(devc); timeout--); - - if (!mpu401_out(dev, cmd->data[i])) - { - restore_flags(flags); - printk("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd); - return -EIO; - } - } + { + for (timeout = 3000; timeout > 0 && !output_ready(devc); timeout--); + + if (!mpu401_out(dev, cmd->data[i])) + { + restore_flags(flags); + printk(KERN_WARNING "mpu401: Command (0x%x), parm send failed.\n", (int) cmd->cmd); + return -EIO; + } + } + } ret = 0; cmd->data[0] = 0; if (cmd->nr_returns) + { for (i = 0; i < cmd->nr_returns; i++) - { - ok = 0; - for (timeout = 5000; timeout > 0 && !ok; timeout--) - if (input_avail(devc)) - { - cmd->data[i] = read_data(devc); - ok = 1; - } - if (!ok) - { - restore_flags(flags); - /* printk( "MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd); */ - return -EIO; - } - } + { + ok = 0; + for (timeout = 5000; timeout > 0 && !ok; timeout--) + if (input_avail(devc)) + { + cmd->data[i] = read_data(devc); + ok = 1; + } + if (!ok) + { + restore_flags(flags); + return -EIO; + } + } + } restore_flags(flags); - return ret; } -static int -mpu_cmd(int dev, int cmd, int data) +static int mpu_cmd(int dev, int cmd, int data) { - int ret; + int ret; static mpu_command_rec rec; @@ -699,14 +675,11 @@ mpu_cmd(int dev, int cmd, int data) rec.data[0] = data & 0xff; if ((ret = mpu401_command(dev, &rec)) < 0) - { - return ret; - } + return ret; return (unsigned char) rec.data[0]; } -static int -mpu401_prefix_cmd(int dev, unsigned char status) +static int mpu401_prefix_cmd(int dev, unsigned char status) { struct mpu_config *devc = &dev_conf[dev]; @@ -714,37 +687,29 @@ mpu401_prefix_cmd(int dev, unsigned char status) return 1; if (status < 0xf0) - { - if (mpu_cmd(dev, 0xD0, 0) < 0) - { - return 0; - } - return 1; - } + { + if (mpu_cmd(dev, 0xD0, 0) < 0) + return 0; + return 1; + } switch (status) - { - case 0xF0: - if (mpu_cmd(dev, 0xDF, 0) < 0) - { - return 0; - } - return 1; - break; - - default: - return 0; - } + { + case 0xF0: + if (mpu_cmd(dev, 0xDF, 0) < 0) + return 0; + return 1; + default: + return 0; + } } -static int -mpu401_start_read(int dev) +static int mpu401_start_read(int dev) { return 0; } -static int -mpu401_end_read(int dev) +static int mpu401_end_read(int dev) { return 0; } @@ -756,49 +721,47 @@ static int mpu401_ioctl(int dev, unsigned cmd, caddr_t arg) int val, ret; devc = &dev_conf[dev]; - switch (cmd) { - case SNDCTL_MIDI_MPUMODE: - if (!(devc->capabilities & MPU_CAP_INTLG)) { /* No intelligent mode */ - printk("MPU-401: Intelligent mode not supported by the HW\n"); + switch (cmd) + { + case SNDCTL_MIDI_MPUMODE: + if (!(devc->capabilities & MPU_CAP_INTLG)) { /* No intelligent mode */ + printk(KERN_WARNING "mpu401: Intelligent mode not supported by the HW\n"); + return -EINVAL; + } + if (get_user(val, (int *)arg)) + return -EFAULT; + set_uart_mode(dev, devc, !val); + return 0; + + case SNDCTL_MIDI_MPUCMD: + if (copy_from_user(&rec, arg, sizeof(rec))) + return -EFAULT; + if ((ret = mpu401_command(dev, &rec)) < 0) + return ret; + if (copy_to_user(arg, &rec, sizeof(rec))) + return -EFAULT; + return 0; + + default: return -EINVAL; - } - if (__get_user(val, (int *)arg)) - return -EFAULT; - set_uart_mode(dev, devc, !val); - return 0; - - case SNDCTL_MIDI_MPUCMD: - if (__copy_from_user(&rec, arg, sizeof(rec))) - return -EFAULT; - if ((ret = mpu401_command(dev, &rec)) < 0) - return ret; - if (__copy_to_user(arg, &rec, sizeof(rec))) - return -EFAULT; - return 0; - - default: - return -EINVAL; } } -static void -mpu401_kick(int dev) +static void mpu401_kick(int dev) { } -static int -mpu401_buffer_status(int dev) +static int mpu401_buffer_status(int dev) { return 0; /* * No data in buffers */ } -static int -mpu_synth_ioctl(int dev, +static int mpu_synth_ioctl(int dev, unsigned int cmd, caddr_t arg) { - int midi_dev; + int midi_dev; struct mpu_config *devc; midi_dev = synth_devs[dev]->midi_dev; @@ -809,88 +772,77 @@ mpu_synth_ioctl(int dev, devc = &dev_conf[midi_dev]; switch (cmd) - { - - case SNDCTL_SYNTH_INFO: - memcpy((&((char *) arg)[0]), (char *) &mpu_synth_info[midi_dev], sizeof(struct synth_info)); + { - return 0; - break; + case SNDCTL_SYNTH_INFO: + memcpy((&((char *) arg)[0]), (char *) &mpu_synth_info[midi_dev], sizeof(struct synth_info)); + return 0; - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - break; + case SNDCTL_SYNTH_MEMAVL: + return 0x7fffffff; - default: - return -EINVAL; - } + default: + return -EINVAL; + } } -static int -mpu_synth_open(int dev, int mode) +static int mpu_synth_open(int dev, int mode) { - int midi_dev, err; + int midi_dev, err; struct mpu_config *devc; midi_dev = synth_devs[dev]->midi_dev; if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev] == NULL) - { - return -ENXIO; - } + return -ENXIO; + devc = &dev_conf[midi_dev]; /* - * Verify that the device is really running. - * Some devices (such as Ensoniq SoundScape don't - * work before the on board processor (OBP) is initialized - * by downloading its microcode. + * Verify that the device is really running. + * Some devices (such as Ensoniq SoundScape don't + * work before the on board processor (OBP) is initialized + * by downloading its microcode. */ if (!devc->initialized) - { - if (mpu401_status(devc) == 0xff) /* Bus float */ - { - printk("MPU-401: Device not initialized properly\n"); - return -EIO; - } - reset_mpu401(devc); - } + { + if (mpu401_status(devc) == 0xff) /* Bus float */ + { + printk(KERN_ERR "mpu401: Device not initialized properly\n"); + return -EIO; + } + reset_mpu401(devc); + } if (devc->opened) - { - printk("MPU-401: Midi busy\n"); - return -EBUSY; - } + return -EBUSY; devc->mode = MODE_SYNTH; devc->synthno = dev; devc->inputintr = NULL; - irq2dev[devc->irq] = midi_dev; if (midi_devs[midi_dev]->coproc) if ((err = midi_devs[midi_dev]->coproc-> open(midi_devs[midi_dev]->coproc->devc, COPR_MIDI)) < 0) - { - printk("MPU-401: Can't access coprocessor device\n"); - - return err; - } + { + printk(KERN_WARNING "mpu401: Can't access coprocessor device\n"); + return err; + } devc->opened = mode; reset_mpu401(devc); if (mode & OPEN_READ) - { - mpu_cmd(midi_dev, 0x8B, 0); /* Enable data in stop mode */ - mpu_cmd(midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ - mpu_cmd(midi_dev, 0x87, 0); /* Enable pitch & controller */ - } + { + mpu_cmd(midi_dev, 0x8B, 0); /* Enable data in stop mode */ + mpu_cmd(midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ + mpu_cmd(midi_dev, 0x87, 0); /* Enable pitch & controller */ + } return 0; } -static void -mpu_synth_close(int dev) -{ - int midi_dev; +static void mpu_synth_close(int dev) +{ + int midi_dev; struct mpu_config *devc; midi_dev = synth_devs[dev]->midi_dev; @@ -958,55 +910,52 @@ static struct midi_operations mpu401_midi_proto = static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV]; -static void -mpu401_chk_version(int n, struct mpu_config *devc) +static void mpu401_chk_version(int n, struct mpu_config *devc) { - int tmp; - unsigned long flags; + int tmp; + unsigned long flags; devc->version = devc->revision = 0; save_flags(flags); cli(); if ((tmp = mpu_cmd(n, 0xAC, 0)) < 0) - { - restore_flags(flags); - return; - } + { + restore_flags(flags); + return; + } if ((tmp & 0xf0) > 0x20) /* Why it's larger than 2.x ??? */ - { - restore_flags(flags); - return; - } + { + restore_flags(flags); + return; + } devc->version = tmp; if ((tmp = mpu_cmd(n, 0xAD, 0)) < 0) - { - devc->version = 0; - restore_flags(flags); - return; - } + { + devc->version = 0; + restore_flags(flags); + return; + } devc->revision = tmp; - restore_flags(flags); } -void -attach_mpu401(struct address_info *hw_config) +void attach_mpu401(struct address_info *hw_config) { - unsigned long flags; - char revision_char; + unsigned long flags; + char revision_char; - int m; + int m; struct mpu_config *devc; hw_config->slots[1] = -1; m = sound_alloc_mididev(); if (m == -1) - { - printk(KERN_WARNING "MPU-401: Too many midi devices detected\n"); - return; - } + { + printk(KERN_WARNING "MPU-401: Too many midi devices detected\n"); + return; + } devc = &dev_conf[m]; devc->base = hw_config->io_base; devc->osp = hw_config->osp; @@ -1024,35 +973,36 @@ attach_mpu401(struct address_info *hw_config) devc->irq = hw_config->irq; if (devc->irq < 0) - { - devc->irq *= -1; - devc->shared_irq = 1; - } - irq2dev[devc->irq] = m; + { + devc->irq *= -1; + devc->shared_irq = 1; + } if (!hw_config->always_detect) - { - /* Verify the hardware again */ - if (!reset_mpu401(devc)) - { - printk(KERN_WARNING "mpu401: Device didn't respond\n"); - sound_unload_mididev(m); - return; - } - if (!devc->shared_irq) - if (snd_set_irq_handler(devc->irq, mpuintr, "mpu401", devc->osp) < 0) - { - printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq); - sound_unload_mididev(m); - return; - } - save_flags(flags); - cli(); - mpu401_chk_version(m, devc); - if (devc->version == 0) - mpu401_chk_version(m, devc); - restore_flags(flags); - } + { + /* Verify the hardware again */ + if (!reset_mpu401(devc)) + { + printk(KERN_WARNING "mpu401: Device didn't respond\n"); + sound_unload_mididev(m); + return; + } + if (!devc->shared_irq) + { + if (request_irq(devc->irq, mpuintr, 0, "mpu401", (void *)m) < 0) + { + printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq); + sound_unload_mididev(m); + return; + } + } + save_flags(flags); + cli(); + mpu401_chk_version(m, devc); + if (devc->version == 0) + mpu401_chk_version(m, devc); + restore_flags(flags); + } request_region(hw_config->io_base, 2, "mpu401"); if (devc->version != 0) @@ -1061,36 +1011,32 @@ attach_mpu401(struct address_info *hw_config) devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */ - mpu401_synth_operations[m] = (struct synth_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct synth_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct synth_operations); - - if (sound_nblocks < 1024) - sound_nblocks++;; + mpu401_synth_operations[m] = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL); if (mpu401_synth_operations[m] == NULL) - { - sound_unload_mididev(m); - printk(KERN_ERR "mpu401: Can't allocate memory\n"); - return; - } + { + sound_unload_mididev(m); + printk(KERN_ERR "mpu401: Can't allocate memory\n"); + return; + } if (!(devc->capabilities & MPU_CAP_INTLG)) /* No intelligent mode */ - { - memcpy((char *) mpu401_synth_operations[m], - (char *) &std_midi_synth, + { + memcpy((char *) mpu401_synth_operations[m], + (char *) &std_midi_synth, sizeof(struct synth_operations)); - } else - { - memcpy((char *) mpu401_synth_operations[m], - (char *) &mpu401_synth_proto, + } + else + { + memcpy((char *) mpu401_synth_operations[m], + (char *) &mpu401_synth_proto, sizeof(struct synth_operations)); - } + } memcpy((char *) &mpu401_midi_operations[m], (char *) &mpu401_midi_proto, sizeof(struct midi_operations)); - mpu401_midi_operations[m].converter = - mpu401_synth_operations[m]; + mpu401_midi_operations[m].converter = mpu401_synth_operations[m]; memcpy((char *) &mpu_synth_info[m], (char *) &mpu_synth_info_proto, @@ -1099,37 +1045,36 @@ attach_mpu401(struct address_info *hw_config) n_mpu_devs++; if (devc->version == 0x20 && devc->revision >= 0x07) /* MusicQuest interface */ - { - int ports = (devc->revision & 0x08) ? 32 : 16; - - devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE | - MPU_CAP_CLS | MPU_CAP_2PORT; - - revision_char = (devc->revision == 0x7f) ? 'M' : ' '; - sprintf(mpu_synth_info[m].name, - "MQX-%d%c MIDI Interface #%d", - ports, - revision_char, - n_mpu_devs); - } else - { - - revision_char = devc->revision ? devc->revision + '@' : ' '; - if ((int) devc->revision > ('Z' - '@')) - revision_char = '+'; - - devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; - - if (hw_config->name) - sprintf(mpu_synth_info[m].name, "%s (MPU401)", hw_config->name); - else - sprintf(mpu_synth_info[m].name, - "MPU-401 %d.%d%c Midi interface #%d", - (int) (devc->version & 0xf0) >> 4, - devc->version & 0x0f, - revision_char, - n_mpu_devs); - } + { + int ports = (devc->revision & 0x08) ? 32 : 16; + + devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE | + MPU_CAP_CLS | MPU_CAP_2PORT; + + revision_char = (devc->revision == 0x7f) ? 'M' : ' '; + sprintf(mpu_synth_info[m].name, "MQX-%d%c MIDI Interface #%d", + ports, + revision_char, + n_mpu_devs); + } + else + { + revision_char = devc->revision ? devc->revision + '@' : ' '; + if ((int) devc->revision > ('Z' - '@')) + revision_char = '+'; + + devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; + + if (hw_config->name) + sprintf(mpu_synth_info[m].name, "%s (MPU401)", hw_config->name); + else + sprintf(mpu_synth_info[m].name, + "MPU-401 %d.%d%c Midi interface #%d", + (int) (devc->version & 0xf0) >> 4, + devc->version & 0x0f, + revision_char, + n_mpu_devs); + } strcpy(mpu401_midi_operations[m].info.name, mpu_synth_info[m].name); @@ -1137,24 +1082,21 @@ attach_mpu401(struct address_info *hw_config) conf_printf(mpu_synth_info[m].name, hw_config); mpu401_synth_operations[m]->midi_dev = devc->devno = m; - mpu401_synth_operations[devc->devno]->info = - &mpu_synth_info[devc->devno]; + mpu401_synth_operations[devc->devno]->info = &mpu_synth_info[devc->devno]; if (devc->capabilities & MPU_CAP_INTLG) /* Intelligent mode */ hw_config->slots[2] = mpu_timer_init(m); - irq2dev[devc->irq] = m; midi_devs[m] = &mpu401_midi_operations[devc->devno]; hw_config->slots[1] = m; sequencer_init(); } -static int -reset_mpu401(struct mpu_config *devc) +static int reset_mpu401(struct mpu_config *devc) { - unsigned long flags; - int ok, timeout, n; - int timeout_limit; + unsigned long flags; + int ok, timeout, n; + int timeout_limit; /* * Send the RESET command. Try again if no success at the first time. @@ -1167,30 +1109,30 @@ reset_mpu401(struct mpu_config *devc) devc->initialized = 1; for (n = 0; n < 2 && !ok; n++) - { - for (timeout = timeout_limit; timeout > 0 && !ok; timeout--) + { + for (timeout = timeout_limit; timeout > 0 && !ok; timeout--) ok = output_ready(devc); - write_command(devc, MPU_RESET); /* + write_command(devc, MPU_RESET); /* * Send MPU-401 RESET Command */ - /* - * Wait at least 25 msec. This method is not accurate so let's make the - * loop bit longer. Cannot sleep since this is called during boot. - */ + /* + * Wait at least 25 msec. This method is not accurate so let's make the + * loop bit longer. Cannot sleep since this is called during boot. + */ - for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--) - { - save_flags(flags); - cli(); - if (input_avail(devc)) - if (read_data(devc) == MPU_ACK) - ok = 1; - restore_flags(flags); - } + for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--) + { + save_flags(flags); + cli(); + if (input_avail(devc)) + if (read_data(devc) == MPU_ACK) + ok = 1; + restore_flags(flags); + } - } + } devc->m_state = ST_INIT; devc->m_ptr = 0; @@ -1201,43 +1143,37 @@ reset_mpu401(struct mpu_config *devc) return ok; } -static void -set_uart_mode(int dev, struct mpu_config *devc, int arg) +static void set_uart_mode(int dev, struct mpu_config *devc, int arg) { if (!arg && (devc->capabilities & MPU_CAP_INTLG)) - { - return; - } + return; if ((devc->uart_mode == 0) == (arg == 0)) - { - return; /* Already set */ - } + return; /* Already set */ reset_mpu401(devc); /* This exits the uart mode */ if (arg) - { - if (mpu_cmd(dev, UART_MODE_ON, 0) < 0) - { - printk("MPU%d: Can't enter UART mode\n", devc->devno); - devc->uart_mode = 0; - return; - } - } + { + if (mpu_cmd(dev, UART_MODE_ON, 0) < 0) + { + printk(KERN_ERR "mpu401: Can't enter UART mode\n"); + devc->uart_mode = 0; + return; + } + } devc->uart_mode = arg; } -int -probe_mpu401(struct address_info *hw_config) +int probe_mpu401(struct address_info *hw_config) { - int ok = 0; + int ok = 0; struct mpu_config tmp_devc; if (check_region(hw_config->io_base, 2)) - { - printk("\n\nmpu401.c: I/O port %x already in use\n\n", hw_config->io_base); - return 0; - } + { + printk(KERN_ERR "mpu401: I/O port %x already in use\n\n", hw_config->io_base); + return 0; + } tmp_devc.base = hw_config->io_base; tmp_devc.irq = hw_config->irq; tmp_devc.initialized = 0; @@ -1248,27 +1184,32 @@ probe_mpu401(struct address_info *hw_config) return 1; if (inb(hw_config->io_base + 1) == 0xff) - { - DDB(printk("MPU401: Port %x looks dead.\n", hw_config->io_base)); - return 0; /* Just bus float? */ - } + { + DDB(printk("MPU401: Port %x looks dead.\n", hw_config->io_base)); + return 0; /* Just bus float? */ + } ok = reset_mpu401(&tmp_devc); if (!ok) - { - DDB(printk("MPU401: Reset failed on port %x\n", hw_config->io_base)); - } + { + DDB(printk("MPU401: Reset failed on port %x\n", hw_config->io_base)); + } return ok; } -void -unload_mpu401(struct address_info *hw_config) +void unload_mpu401(struct address_info *hw_config) { + void *p; + int n=hw_config->slots[1]; + release_region(hw_config->io_base, 2); if (hw_config->always_detect == 0 && hw_config->irq > 0) - snd_release_irq(hw_config->irq); - sound_unload_mididev(hw_config->slots[1]); + free_irq(hw_config->irq, (void *)n); + p=mpu401_synth_operations[n]; + sound_unload_mididev(n); sound_unload_timerdev(hw_config->slots[2]); + if(p) + kfree(p); } /***************************************************** @@ -1285,23 +1226,20 @@ static volatile unsigned long curr_ticks, curr_clocks; static unsigned long prev_event_time; static int metronome_mode; -static unsigned long -clocks2ticks(unsigned long clocks) +static unsigned long clocks2ticks(unsigned long clocks) { /* - * The MPU-401 supports just a limited set of possible timebase values. - * Since the applications require more choices, the driver has to - * program the HW to do its best and to convert between the HW and - * actual timebases. + * The MPU-401 supports just a limited set of possible timebase values. + * Since the applications require more choices, the driver has to + * program the HW to do its best and to convert between the HW and + * actual timebases. */ - return ((clocks * curr_timebase) + (hw_timebase / 2)) / hw_timebase; } -static void -set_timebase(int midi_dev, int val) +static void set_timebase(int midi_dev, int val) { - int hw_val; + int hw_val; if (val < 48) val = 48; @@ -1314,19 +1252,18 @@ set_timebase(int midi_dev, int val) hw_val = max_timebase; if (mpu_cmd(midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0) - { - printk("MPU: Can't set HW timebase to %d\n", hw_val * 24); - return; - } + { + printk(KERN_WARNING "mpu401: Can't set HW timebase to %d\n", hw_val * 24); + return; + } hw_timebase = hw_val * 24; curr_timebase = val; } -static void -tmr_reset(void) +static void tmr_reset(void) { - unsigned long flags; + unsigned long flags; save_flags(flags); cli(); @@ -1336,8 +1273,7 @@ tmr_reset(void) restore_flags(flags); } -static void -set_timer_mode(int midi_dev) +static void set_timer_mode(int midi_dev) { if (timer_mode & TMR_MODE_CLS) mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ @@ -1345,31 +1281,31 @@ set_timer_mode(int midi_dev) mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ if (timer_mode & TMR_INTERNAL) - { + { mpu_cmd(midi_dev, 0x80, 0); /* Use MIDI sync */ - } else - { - if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS)) - { - mpu_cmd(midi_dev, 0x82, 0); /* Use MIDI sync */ - mpu_cmd(midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */ - } else if (timer_mode & TMR_MODE_FSK) - mpu_cmd(midi_dev, 0x81, 0); /* Use FSK sync */ - } + } + else + { + if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS)) + { + mpu_cmd(midi_dev, 0x82, 0); /* Use MIDI sync */ + mpu_cmd(midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */ + } + else if (timer_mode & TMR_MODE_FSK) + mpu_cmd(midi_dev, 0x81, 0); /* Use FSK sync */ + } } -static void -stop_metronome(int midi_dev) +static void stop_metronome(int midi_dev) { mpu_cmd(midi_dev, 0x84, 0); /* Disable metronome */ } -static void -setup_metronome(int midi_dev) +static void setup_metronome(int midi_dev) { - int numerator, denominator; - int clks_per_click, num_32nds_per_beat; - int beats_per_measure; + int numerator, denominator; + int clks_per_click, num_32nds_per_beat; + int beats_per_measure; numerator = ((unsigned) metronome_mode >> 24) & 0xff; denominator = ((unsigned) metronome_mode >> 16) & 0xff; @@ -1380,15 +1316,14 @@ setup_metronome(int midi_dev) if (!metronome_mode) mpu_cmd(midi_dev, 0x84, 0); /* Disable metronome */ else - { - mpu_cmd(midi_dev, 0xE4, clks_per_click); - mpu_cmd(midi_dev, 0xE6, beats_per_measure); - mpu_cmd(midi_dev, 0x83, 0); /* Enable metronome without accents */ - } + { + mpu_cmd(midi_dev, 0xE4, clks_per_click); + mpu_cmd(midi_dev, 0xE6, beats_per_measure); + mpu_cmd(midi_dev, 0x83, 0); /* Enable metronome without accents */ + } } -static int -mpu_start_timer(int midi_dev) +static int mpu_start_timer(int midi_dev) { tmr_reset(); set_timer_mode(midi_dev); @@ -1397,25 +1332,24 @@ mpu_start_timer(int midi_dev) return TIMER_NOT_ARMED; /* Already running */ if (timer_mode & TMR_INTERNAL) - { - mpu_cmd(midi_dev, 0x02, 0); /* Send MIDI start */ - tmr_running = 1; - return TIMER_NOT_ARMED; - } else - { - mpu_cmd(midi_dev, 0x35, 0); /* Enable mode messages to PC */ - mpu_cmd(midi_dev, 0x38, 0); /* Enable sys common messages to PC */ - mpu_cmd(midi_dev, 0x39, 0); /* Enable real time messages to PC */ - mpu_cmd(midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */ - } - + { + mpu_cmd(midi_dev, 0x02, 0); /* Send MIDI start */ + tmr_running = 1; + return TIMER_NOT_ARMED; + } + else + { + mpu_cmd(midi_dev, 0x35, 0); /* Enable mode messages to PC */ + mpu_cmd(midi_dev, 0x38, 0); /* Enable sys common messages to PC */ + mpu_cmd(midi_dev, 0x39, 0); /* Enable real time messages to PC */ + mpu_cmd(midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */ + } return TIMER_ARMED; } -static int -mpu_timer_open(int dev, int mode) +static int mpu_timer_open(int dev, int mode) { - int midi_dev = sound_timer_devs[dev]->devlink; + int midi_dev = sound_timer_devs[dev]->devlink; if (timer_open) return -EBUSY; @@ -1435,10 +1369,9 @@ mpu_timer_open(int dev, int mode) return 0; } -static void -mpu_timer_close(int dev) +static void mpu_timer_close(int dev) { - int midi_dev = sound_timer_devs[dev]->devlink; + int midi_dev = sound_timer_devs[dev]->devlink; timer_open = tmr_running = 0; mpu_cmd(midi_dev, 0x15, 0); /* Stop all */ @@ -1447,86 +1380,80 @@ mpu_timer_close(int dev) stop_metronome(midi_dev); } -static int -mpu_timer_event(int dev, unsigned char *event) +static int mpu_timer_event(int dev, unsigned char *event) { - unsigned char command = event[1]; - unsigned long parm = *(unsigned int *) &event[4]; - int midi_dev = sound_timer_devs[dev]->devlink; + unsigned char command = event[1]; + unsigned long parm = *(unsigned int *) &event[4]; + int midi_dev = sound_timer_devs[dev]->devlink; switch (command) - { - case TMR_WAIT_REL: - parm += prev_event_time; - case TMR_WAIT_ABS: - if (parm > 0) - { - long time; - - if (parm <= curr_ticks) /* It's the time */ - return TIMER_NOT_ARMED; - - time = parm; - next_event_time = prev_event_time = time; - - return TIMER_ARMED; - } - break; - - case TMR_START: - if (tmr_running) - break; - return mpu_start_timer(midi_dev); - break; - - case TMR_STOP: - mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ - stop_metronome(midi_dev); - tmr_running = 0; - break; - - case TMR_CONTINUE: - if (tmr_running) - break; - mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ - setup_metronome(midi_dev); - tmr_running = 1; - break; - - case TMR_TEMPO: - if (parm) - { - if (parm < 8) - parm = 8; - if (parm > 250) - parm = 250; - - if (mpu_cmd(midi_dev, 0xE0, parm) < 0) - printk("MPU: Can't set tempo to %d\n", (int) parm); - curr_tempo = parm; - } - break; - - case TMR_ECHO: - seq_copy_to_input(event, 8); - break; - - case TMR_TIMESIG: - if (metronome_mode) /* Metronome enabled */ - { - metronome_mode = parm; - setup_metronome(midi_dev); - } - break; - - default:; - } + { + case TMR_WAIT_REL: + parm += prev_event_time; + case TMR_WAIT_ABS: + if (parm > 0) + { + long time; + + if (parm <= curr_ticks) /* It's the time */ + return TIMER_NOT_ARMED; + time = parm; + next_event_time = prev_event_time = time; + + return TIMER_ARMED; + } + break; + + case TMR_START: + if (tmr_running) + break; + return mpu_start_timer(midi_dev); + + case TMR_STOP: + mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ + stop_metronome(midi_dev); + tmr_running = 0; + break; + case TMR_CONTINUE: + if (tmr_running) + break; + mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ + setup_metronome(midi_dev); + tmr_running = 1; + break; + + case TMR_TEMPO: + if (parm) + { + if (parm < 8) + parm = 8; + if (parm > 250) + parm = 250; + if (mpu_cmd(midi_dev, 0xE0, parm) < 0) + printk(KERN_WARNING "mpu401: Can't set tempo to %d\n", (int) parm); + curr_tempo = parm; + } + break; + + case TMR_ECHO: + seq_copy_to_input(event, 8); + break; + + case TMR_TIMESIG: + if (metronome_mode) /* Metronome enabled */ + { + metronome_mode = parm; + setup_metronome(midi_dev); + } + break; + + default: + } return TIMER_NOT_ARMED; } -static unsigned long -mpu_timer_get_time(int dev) +static unsigned long mpu_timer_get_time(int dev) { if (!timer_open) return 0; @@ -1534,128 +1461,115 @@ mpu_timer_get_time(int dev) return curr_ticks; } -static int -mpu_timer_ioctl(int dev, - unsigned int command, caddr_t arg) +static int mpu_timer_ioctl(int dev, unsigned int command, caddr_t arg) { - int midi_dev = sound_timer_devs[dev]->devlink; + int midi_dev = sound_timer_devs[dev]->devlink; switch (command) - { - case SNDCTL_TMR_SOURCE: - { - int parm; - - parm = *(int *) arg; - parm &= timer_caps; - - if (parm != 0) - { - timer_mode = parm; - - if (timer_mode & TMR_MODE_CLS) - mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ - else if (timer_mode & TMR_MODE_SMPTE) - mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ - } - return (*(int *) arg = timer_mode); - } - break; - - case SNDCTL_TMR_START: - mpu_start_timer(midi_dev); - return 0; - break; - - case SNDCTL_TMR_STOP: - tmr_running = 0; - mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ - stop_metronome(midi_dev); - return 0; - break; - - case SNDCTL_TMR_CONTINUE: - if (tmr_running) - return 0; - tmr_running = 1; - mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ - return 0; - break; - - case SNDCTL_TMR_TIMEBASE: - { - int val; - - val = *(int *) arg; - if (val) - set_timebase(midi_dev, val); - - return (*(int *) arg = curr_timebase); - } - break; - - case SNDCTL_TMR_TEMPO: - { - int val; - int ret; - - val = *(int *) arg; - - if (val) - { - if (val < 8) - val = 8; - if (val > 250) - val = 250; - if ((ret = mpu_cmd(midi_dev, 0xE0, val)) < 0) - { - printk("MPU: Can't set tempo to %d\n", (int) val); - return ret; - } - curr_tempo = val; - } - return (*(int *) arg = curr_tempo); - } - break; - - case SNDCTL_SEQ_CTRLRATE: - { - int val; - - val = *(int *) arg; - if (val != 0) /* Can't change */ - return -EINVAL; - - return (*(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60); - } - break; - - case SNDCTL_SEQ_GETTIME: - return (*(int *) arg = curr_ticks); - break; - - case SNDCTL_TMR_METRONOME: - metronome_mode = *(int *) arg; - setup_metronome(midi_dev); - return 0; - break; - - default:; - } + { + case SNDCTL_TMR_SOURCE: + { + int parm; + + parm = *(int *) arg; + parm &= timer_caps; + if (parm != 0) + { + timer_mode = parm; + + if (timer_mode & TMR_MODE_CLS) + mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ + else if (timer_mode & TMR_MODE_SMPTE) + mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ + } + return (*(int *) arg = timer_mode); + } + break; + + case SNDCTL_TMR_START: + mpu_start_timer(midi_dev); + return 0; + + case SNDCTL_TMR_STOP: + tmr_running = 0; + mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ + stop_metronome(midi_dev); + return 0; + + case SNDCTL_TMR_CONTINUE: + if (tmr_running) + return 0; + tmr_running = 1; + mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ + return 0; + + case SNDCTL_TMR_TIMEBASE: + { + int val; + + val = *(int *) arg; + if (val) + set_timebase(midi_dev, val); + return (*(int *) arg = curr_timebase); + } + break; + + case SNDCTL_TMR_TEMPO: + { + int val; + int ret; + + val = *(int *) arg; + + if (val) + { + if (val < 8) + val = 8; + if (val > 250) + val = 250; + if ((ret = mpu_cmd(midi_dev, 0xE0, val)) < 0) + { + printk(KERN_WARNING "mpu401: Can't set tempo to %d\n", (int) val); + return ret; + } + curr_tempo = val; + } + return (*(int *) arg = curr_tempo); + } + break; + + case SNDCTL_SEQ_CTRLRATE: + { + int val; + + val = *(int *) arg; + if (val != 0) /* Can't change */ + return -EINVAL; + return (*(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60); + } + break; + + case SNDCTL_SEQ_GETTIME: + return (*(int *) arg = curr_ticks); + + case SNDCTL_TMR_METRONOME: + metronome_mode = *(int *) arg; + setup_metronome(midi_dev); + return 0; + + default: + } return -EINVAL; } -static void -mpu_timer_arm(int dev, long time) +static void mpu_timer_arm(int dev, long time) { if (time < 0) time = curr_ticks + 1; else if (time <= curr_ticks) /* It's the time */ return; - next_event_time = prev_event_time = time; - return; } @@ -1672,10 +1586,8 @@ static struct sound_timer_operations mpu_timer = mpu_timer_arm }; -static void -mpu_timer_interrupt(void) +static void mpu_timer_interrupt(void) { - if (!timer_open) return; @@ -1686,10 +1598,10 @@ mpu_timer_interrupt(void) curr_ticks = clocks2ticks(curr_clocks); if (curr_ticks >= next_event_time) - { - next_event_time = (unsigned long) -1; - sequencer_timer(0); - } + { + next_event_time = (unsigned long) -1; + sequencer_timer(0); + } } static void timer_ext_event(struct mpu_config *devc, int event, int parm) @@ -1706,8 +1618,9 @@ static void timer_ext_event(struct mpu_config *devc, int event, int parm) break; case TMR_START: - printk("Ext MIDI start\n"); + printk("Ext MIDI start\n"); if (!tmr_running) + { if (timer_mode & TMR_EXTERNAL) { tmr_running = 1; @@ -1715,6 +1628,7 @@ static void timer_ext_event(struct mpu_config *devc, int event, int parm) next_event_time = 0; STORE(SEQ_START_TIMER()); } + } break; case TMR_STOP: diff --git a/drivers/sound/opl3.c b/drivers/sound/opl3.c index 36734c2e7..cd768801f 100644 --- a/drivers/sound/opl3.c +++ b/drivers/sound/opl3.c @@ -2,25 +2,30 @@ * sound/opl3.c * * A low level driver for Yamaha YM3812 and OPL-3 -chips - */ -/* + * +* * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * + * Changes + * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) + * Alan Cox modularisation, fixed sound_mem allocs. + * + * Status + * Believed to work. Badly needs rewriting a bit to support multiple + * OPL3 devices. */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - */ + #include #include #include /* * Major improvements to the FM handling 30AUG92 by Rob Hooft, - */ -/* * hooft@chem.ruu.nl */ @@ -109,32 +114,32 @@ static int opl3_ioctl(int dev, unsigned int cmd, caddr_t arg) struct sbi_instrument ins; switch (cmd) { - case SNDCTL_FM_LOAD_INSTR: - printk(KERN_WARNING "Warning: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n"); - if (__copy_from_user(&ins, arg, sizeof(ins))) - return -EFAULT; - if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) { - printk("FM Error: Invalid instrument number %d\n", ins.channel); - return -EINVAL; - } - return store_instr(ins.channel, &ins); + case SNDCTL_FM_LOAD_INSTR: + printk(KERN_WARNING "Warning: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n"); + if (copy_from_user(&ins, arg, sizeof(ins))) + return -EFAULT; + if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) { + printk(KERN_WARNING "FM Error: Invalid instrument number %d\n", ins.channel); + return -EINVAL; + } + return store_instr(ins.channel, &ins); - case SNDCTL_SYNTH_INFO: - devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice; - if (__copy_to_user(arg, &devc->fm_info, sizeof(devc->fm_info))) - return -EFAULT; - return 0; + case SNDCTL_SYNTH_INFO: + devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice; + if (copy_to_user(arg, &devc->fm_info, sizeof(devc->fm_info))) + return -EFAULT; + return 0; - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; + case SNDCTL_SYNTH_MEMAVL: + return 0x7fffffff; - case SNDCTL_FM_4OP_ENABLE: - if (devc->model == 2) - enter_4op_mode(); - return 0; + case SNDCTL_FM_4OP_ENABLE: + if (devc->model == 2) + enter_4op_mode(); + return 0; - default: - return -EINVAL; + default: + return -EINVAL; } } @@ -151,8 +156,8 @@ int opl3_detect(int ioaddr, int *osp) * Note2! The chip is initialized if detected. */ - unsigned char stat1, signature; - int i; + unsigned char stat1, signature; + int i; if (devc != NULL) { @@ -160,10 +165,7 @@ int opl3_detect(int ioaddr, int *osp) return 0; } - devc = (struct opl_devinfo *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(*devc))); - sound_mem_sizes[sound_nblocks] = sizeof(*devc); - if (sound_nblocks < 1024) - sound_nblocks++;; + devc = (struct opl_devinfo *)kmalloc(sizeof(*devc), GFP_KERNEL); if (devc == NULL) { @@ -333,7 +335,7 @@ static char fm_volume_table[128] = static void calc_vol(unsigned char *regbyte, int volume, int main_vol) { - int level = (~*regbyte & 0x3f); + int level = (~*regbyte & 0x3f); if (main_vol > 127) main_vol = 127; @@ -814,7 +816,8 @@ static int opl3_load_patch(int dev, int format, const char *addr, return -EINVAL; } - copy_from_user(&((char *) &ins)[offs], &(addr)[offs], sizeof(ins) - offs); + if(copy_from_user(&((char *) &ins)[offs], &(addr)[offs], sizeof(ins) - offs)) + return -EFAULT; if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) { @@ -1199,6 +1202,7 @@ void cleanup_module(void) { if (devc) { + kfree(devc); devc = NULL; sound_unload_synthdev(me); } diff --git a/drivers/sound/pas2_card.c b/drivers/sound/pas2_card.c index 656034d54..bf95b84d5 100644 --- a/drivers/sound/pas2_card.c +++ b/drivers/sound/pas2_card.c @@ -164,7 +164,7 @@ static int config_pas_hw(struct address_info *hw_config) } else { - if (snd_set_irq_handler(pas_irq, pasintr, "PAS16", hw_config->osp) < 0) + if (request_irq(pas_irq, pasintr, "PAS16", 0, NULL) < 0) ok = 0; } } @@ -355,7 +355,7 @@ void unload_pas(struct address_info *hw_config) { sound_free_dma(hw_config->dma); - snd_release_irq(hw_config->irq); + free_irq(hw_config->irq, NULL); } #ifdef MODULE diff --git a/drivers/sound/pss.c b/drivers/sound/pss.c index 9d62dd485..7a0a2e66e 100644 --- a/drivers/sound/pss.c +++ b/drivers/sound/pss.c @@ -11,7 +11,8 @@ * for more info. */ /* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) + * Alan Cox modularisation, clean up. */ #include #include @@ -62,12 +63,12 @@ static int pss_synthLen = 0; #endif typedef struct pss_confdata - { - int base; - int irq; - int dma; - int *osp; - } +{ + int base; + int irq; + int dma; + int *osp; +} pss_confdata; @@ -77,12 +78,11 @@ static pss_confdata *devc = &pss_data; static int pss_initialized = 0; static int nonstandard_microcode = 0; -static void -pss_write(int data) +static void pss_write(int data) { - int i, limit; + int i, limit; - limit = jiffies + 10; /* The timeout is 0.1 seconds */ + limit = jiffies + HZ/10; /* The timeout is 0.1 seconds */ /* * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes * called while interrupts are disabled. This means that the timer is @@ -92,21 +92,20 @@ pss_write(int data) */ for (i = 0; i < 5000000 && jiffies < limit; i++) - { - if (inw(devc->base + PSS_STATUS) & PSS_WRITE_EMPTY) - { - outw(devc->base + PSS_DATA, data); - return; - } - } - printk("PSS: DSP Command (%04x) Timeout.\n", data); + { + if (inw(devc->base + PSS_STATUS) & PSS_WRITE_EMPTY) + { + outw(devc->base + PSS_DATA, data); + return; + } + } + printk(KERN_ERR "PSS: DSP Command (%04x) Timeout.\n", data); } -int -probe_pss(struct address_info *hw_config) +int probe_pss(struct address_info *hw_config) { - unsigned short id; - int irq, dma; + unsigned short id; + int irq, dma; devc->base = hw_config->io_base; irq = devc->irq = hw_config->irq; @@ -129,8 +128,7 @@ probe_pss(struct address_info *hw_config) return 1; } -static int -set_irq(pss_confdata * devc, int dev, int irq) +static int set_irq(pss_confdata * devc, int dev, int irq) { static unsigned short irq_bits[16] = { @@ -148,16 +146,15 @@ set_irq(pss_confdata * devc, int dev, int irq) tmp = inw(REG(dev)) & ~0x38; /* Load confreg, mask IRQ bits out */ if ((bits = irq_bits[irq]) == 0 && irq != 0) - { - printk("PSS: Invalid IRQ %d\n", irq); - return 0; - } + { + printk(KERN_ERR "PSS: Invalid IRQ %d\n", irq); + return 0; + } outw(tmp | bits, REG(dev)); return 1; } -static int -set_io_base(pss_confdata * devc, int dev, int base) +static int set_io_base(pss_confdata * devc, int dev, int base) { unsigned short tmp = inw(REG(dev)) & 0x003f; unsigned short bits = (base & 0x0ffc) << 4; @@ -167,8 +164,7 @@ set_io_base(pss_confdata * devc, int dev, int base) return 1; } -static int -set_dma(pss_confdata * devc, int dev, int dma) +static int set_dma(pss_confdata * devc, int dev, int dma) { static unsigned short dma_bits[8] = { @@ -184,150 +180,139 @@ set_dma(pss_confdata * devc, int dev, int dma) tmp = inw(REG(dev)) & ~0x07; /* Load confreg, mask DMA bits out */ if ((bits = dma_bits[dma]) == 0 && dma != 4) - { - printk("PSS: Invalid DMA %d\n", dma); + { + printk(KERN_ERR "PSS: Invalid DMA %d\n", dma); return 0; - } + } outw(tmp | bits, REG(dev)); return 1; } -static int -pss_reset_dsp(pss_confdata * devc) +static int pss_reset_dsp(pss_confdata * devc) { - unsigned long i, limit = jiffies + 10; + unsigned long i, limit = jiffies + HZ/10; outw(0x2000, REG(PSS_CONTROL)); - - for (i = 0; i < 32768 && jiffies < limit; i++) + for (i = 0; i < 32768 && (limit-jiffies >= 0); i++) inw(REG(PSS_CONTROL)); - outw(0x0000, REG(PSS_CONTROL)); - return 1; } -static int -pss_put_dspword(pss_confdata * devc, unsigned short word) +static int pss_put_dspword(pss_confdata * devc, unsigned short word) { - int i, val; + int i, val; for (i = 0; i < 327680; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & PSS_WRITE_EMPTY) - { - outw(word, REG(PSS_DATA)); - return 1; - } - } + { + val = inw(REG(PSS_STATUS)); + if (val & PSS_WRITE_EMPTY) + { + outw(word, REG(PSS_DATA)); + return 1; + } + } return 0; } -static int -pss_get_dspword(pss_confdata * devc, unsigned short *word) +static int pss_get_dspword(pss_confdata * devc, unsigned short *word) { - int i, val; + int i, val; for (i = 0; i < 327680; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & PSS_READ_FULL) - { - *word = inw(REG(PSS_DATA)); - return 1; - } - } - + { + val = inw(REG(PSS_STATUS)); + if (val & PSS_READ_FULL) + { + *word = inw(REG(PSS_DATA)); + return 1; + } + } return 0; } -static int -pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags) +static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags) { - int i, limit, val, count; + int i, limit, val, count; if (flags & CPF_FIRST) - { + { /*_____ Warn DSP software that a boot is coming */ - outw(0x00fe, REG(PSS_DATA)); - - limit = jiffies + 10; + outw(0x00fe, REG(PSS_DATA)); - for (i = 0; i < 32768 && jiffies < limit; i++) - if (inw(REG(PSS_DATA)) == 0x5500) - break; - - outw(*block++, REG(PSS_DATA)); + limit = jiffies + HZ/10; + for (i = 0; i < 32768 && jiffies < limit; i++) + if (inw(REG(PSS_DATA)) == 0x5500) + break; - pss_reset_dsp(devc); - } + outw(*block++, REG(PSS_DATA)); + pss_reset_dsp(devc); + } count = 1; while (1) - { - int j; + { + int j; - for (j = 0; j < 327670; j++) - { + for (j = 0; j < 327670; j++) + { /*_____ Wait for BG to appear */ - if (inw(REG(PSS_STATUS)) & PSS_FLAG3) - break; - } - - if (j == 327670) - { - /* It's ok we timed out when the file was empty */ - if (count >= size && flags & CPF_LAST) - break; - else - { - printk("\nPSS: Download timeout problems, byte %d=%d\n", count, size); - return 0; - } - } + if (inw(REG(PSS_STATUS)) & PSS_FLAG3) + break; + } + + if (j == 327670) + { + /* It's ok we timed out when the file was empty */ + if (count >= size && flags & CPF_LAST) + break; + else + { + printk("\nPSS: Download timeout problems, byte %d=%d\n", count, size); + return 0; + } + } /*_____ Send the next byte */ - outw(*block++, REG(PSS_DATA)); - count++; - } + outw(*block++, REG(PSS_DATA)); + count++; + } if (flags & CPF_LAST) - { + { /*_____ Why */ - outw(0, REG(PSS_DATA)); - - limit = jiffies + 10; - for (i = 0; i < 32768 && jiffies < limit; i++) - val = inw(REG(PSS_STATUS)); - - limit = jiffies + 10; - for (i = 0; i < 32768 && jiffies < limit; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & 0x4000) - break; - } - - /* now read the version */ - for (i = 0; i < 32000; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & PSS_READ_FULL) - break; - } - if (i == 32000) - return 0; - - val = inw(REG(PSS_DATA)); - /* printk( "", val/16, val % 16); */ - } + outw(0, REG(PSS_DATA)); + + limit = jiffies + HZ/10; + for (i = 0; i < 32768 && (limit - jiffies >= 0); i++) + val = inw(REG(PSS_STATUS)); + + limit = jiffies + HZ/10; + for (i = 0; i < 32768 && (limit-jiffies >= 0); i++) + { + val = inw(REG(PSS_STATUS)); + if (val & 0x4000) + break; + } + + /* now read the version */ + for (i = 0; i < 32000; i++) + { + val = inw(REG(PSS_STATUS)); + if (val & PSS_READ_FULL) + break; + } + if (i == 32000) + return 0; + + val = inw(REG(PSS_DATA)); + /* printk( "", val/16, val % 16); */ + } return 1; } -void -attach_pss(struct address_info *hw_config) +void attach_pss(struct address_info *hw_config) { unsigned short id; - char tmp[100]; + char tmp[100]; devc->base = hw_config->io_base; devc->irq = hw_config->irq; @@ -350,20 +335,20 @@ attach_pss(struct address_info *hw_config) #if YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES if (sound_alloc_dma(hw_config->dma, "PSS")) - { - printk("pss.c: Can't allocate DMA channel\n"); - return; - } + { + printk("pss.c: Can't allocate DMA channel.\n"); + return; + } if (!set_irq(devc, CONF_PSS, devc->irq)) - { - printk("PSS: IRQ error\n"); - return; - } + { + printk("PSS: IRQ allocation error.\n"); + return; + } if (!set_dma(devc, CONF_PSS, devc->dma)) - { - printk("PSS: DRQ error\n"); - return; - } + { + printk(KERN_ERR "PSS: DMA allocation error\n"); + return; + } #endif pss_initialized = 1; @@ -371,8 +356,7 @@ attach_pss(struct address_info *hw_config) conf_printf(tmp, hw_config); } -static void -pss_init_speaker(void) +static void pss_init_speaker(void) { /* Don't ask what are these commands. I really don't know */ pss_write(0x0010); @@ -387,53 +371,52 @@ pss_init_speaker(void) pss_write(0x0800 | 0x00ce); /* Stereo switch? */ } -int -probe_pss_mpu(struct address_info *hw_config) +int probe_pss_mpu(struct address_info *hw_config) { - int timeout; + int timeout; if (!pss_initialized) return 0; if (check_region(hw_config->io_base, 2)) - { - printk("PSS: MPU I/O port conflict\n"); - return 0; - } + { + printk("PSS: MPU I/O port conflict\n"); + return 0; + } if (!set_io_base(devc, CONF_MIDI, hw_config->io_base)) - { - printk("PSS: MIDI base error.\n"); + { + printk("PSS: MIDI base could not be set.\n"); return 0; - } + } if (!set_irq(devc, CONF_MIDI, hw_config->irq)) - { - printk("PSS: MIDI IRQ error.\n"); + { + printk("PSS: MIDI IRQ allocation error.\n"); return 0; - } + } if (!pss_synthLen) - { - printk("PSS: Can't enable MPU. MIDI synth microcode not available.\n"); - return 0; - } + { + printk(KERN_ERR "PSS: Can't enable MPU. MIDI synth microcode not available.\n"); + return 0; + } if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) - { - printk("PSS: Unable to load MIDI synth microcode to DSP.\n"); - return 0; - } + { + printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); + return 0; + } pss_init_speaker(); -/* - * Finally wait until the DSP algorithm has initialized itself and - * deactivates receive interrupt. - */ + /* + * Finally wait until the DSP algorithm has initialized itself and + * deactivates receive interrupt. + */ for (timeout = 900000; timeout > 0; timeout--) - { - if ((inb(hw_config->io_base + 1) & 0x80) == 0) /* Input data avail */ - inb(hw_config->io_base); /* Discard it */ - else - break; /* No more input */ - } + { + if ((inb(hw_config->io_base + 1) & 0x80) == 0) /* Input data avail */ + inb(hw_config->io_base); /* Discard it */ + else + break; /* No more input */ + } #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) return probe_mpu401(hw_config); @@ -442,62 +425,56 @@ probe_pss_mpu(struct address_info *hw_config) #endif } -static int -pss_coproc_open(void *dev_info, int sub_device) +static int pss_coproc_open(void *dev_info, int sub_device) { switch (sub_device) - { - case COPR_MIDI: - - if (pss_synthLen == 0) - { - printk("PSS: MIDI synth microcode not available.\n"); - return -EIO; - } - if (nonstandard_microcode) - if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) - { - printk("PSS: Unable to load MIDI synth microcode to DSP.\n"); - return -EIO; - } - nonstandard_microcode = 0; - break; - - default:; - } + { + case COPR_MIDI: + if (pss_synthLen == 0) + { + printk(KERN_ERR "PSS: MIDI synth microcode not available.\n"); + return -EIO; + } + if (nonstandard_microcode) + if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) + { + printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); + return -EIO; + } + nonstandard_microcode = 0; + break; + + default: + } return 0; } -static void -pss_coproc_close(void *dev_info, int sub_device) +static void pss_coproc_close(void *dev_info, int sub_device) { return; } -static void -pss_coproc_reset(void *dev_info) +static void pss_coproc_reset(void *dev_info) { if (pss_synthLen) if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) - { - printk("PSS: Unable to load MIDI synth microcode to DSP.\n"); - } + { + printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); + } nonstandard_microcode = 0; } -static int -download_boot_block(void *dev_info, copr_buffer * buf) +static int download_boot_block(void *dev_info, copr_buffer * buf) { if (buf->len <= 0 || buf->len > sizeof(buf->data)) return -EINVAL; if (!pss_download_boot(devc, buf->data, buf->len, buf->flags)) - { - printk("PSS: Unable to load microcode block to DSP.\n"); - return -EIO; - } + { + printk(KERN_ERR "PSS: Unable to load microcode block to DSP.\n"); + return -EIO; + } nonstandard_microcode = 1; /* The MIDI microcode has been overwritten */ - return 0; } @@ -512,169 +489,170 @@ static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, caddr_t arg, int l int i, err; /* printk( "PSS coproc ioctl %x %x %d\n", cmd, arg, local); */ - switch (cmd) { - case SNDCTL_COPR_RESET: - pss_coproc_reset(dev_info); - return 0; + switch (cmd) + { + case SNDCTL_COPR_RESET: + pss_coproc_reset(dev_info); + return 0; - case SNDCTL_COPR_LOAD: - buf = (copr_buffer *) vmalloc(sizeof(copr_buffer)); - if (buf == NULL) - return -ENOSPC; - if (__copy_from_user(buf, arg, sizeof(copr_buffer))) { + case SNDCTL_COPR_LOAD: + buf = (copr_buffer *) vmalloc(sizeof(copr_buffer)); + if (buf == NULL) + return -ENOSPC; + if (copy_from_user(buf, arg, sizeof(copr_buffer))) { + vfree(buf); + return -EFAULT; + } + err = download_boot_block(dev_info, buf); vfree(buf); - return -EFAULT; - } - err = download_boot_block(dev_info, buf); - vfree(buf); - return err; + 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)); + 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 err ? -EFAULT : -EIO; + return -EFAULT; } - } - 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 < mbuf->len; i++) { - mbuf->len = i; /* feed back number of WORDs read */ - if (!pss_get_dspword(devc, data++)) { - if (i == 0) - err = -EIO; - break; + 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); - 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)) { + 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 < mbuf->len; 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); - return -EIO; - } - dbuf.parm1 = tmp; - restore_flags(flags); - if (__copy_to_user(arg, &dbuf, sizeof(dbuf))) - return -EFAULT; - return 0; + if (copy_to_user(arg, mbuf, sizeof(copr_msg))) + err = -EFAULT; + vfree(mbuf); + return err; - 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)) { + 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); - return -EIO; - } - restore_flags(flags); - return 0; + if (copy_to_user(arg, &dbuf, sizeof(dbuf))) + return -EFAULT; + 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)) { + 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 -EIO; - } - restore_flags(flags); - return 0; + 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 */ + 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 -EIO; - } - dbuf.parm1 = tmp << 8; - if (!pss_get_dspword(devc, &tmp)) { /* Read LSB */ + 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); - return -EIO; - } - dbuf.parm1 |= tmp & 0x00ff; - restore_flags(flags); - if (__copy_to_user(arg, &dbuf, sizeof(dbuf))) - return -EFAULT; - return 0; + if (copy_to_user(arg, &dbuf, sizeof(dbuf))) + return -EFAULT; + return 0; - default: - return -EINVAL; + default: + return -EINVAL; } return -EINVAL; } @@ -689,52 +667,47 @@ static coproc_operations pss_coproc_operations = &pss_data }; -void -attach_pss_mpu(struct address_info *hw_config) +void attach_pss_mpu(struct address_info *hw_config) { #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) - { - attach_mpu401(hw_config); /* Slot 1 */ - - if (hw_config->slots[1] != -1) /* The MPU driver installed itself */ - midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations; - } + attach_mpu401(hw_config); /* Slot 1 */ + if (hw_config->slots[1] != -1) /* The MPU driver installed itself */ + midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations; #endif } -int -probe_pss_mss(struct address_info *hw_config) +int probe_pss_mss(struct address_info *hw_config) { - volatile int timeout; + volatile int timeout; if (!pss_initialized) return 0; if (check_region(hw_config->io_base, 8)) - { - printk("PSS: WSS I/O port conflict\n"); + { + 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 error.\n"); - return 0; - } + { + printk("PSS: WSS base not settable.\n"); + return 0; + } if (!set_irq(devc, CONF_WSS, hw_config->irq)) - { - printk("PSS: WSS IRQ error.\n"); - return 0; - } + { + printk("PSS: WSS IRQ allocation error.\n"); + return 0; + } if (!set_dma(devc, CONF_WSS, hw_config->dma)) - { - printk("PSS: WSS DRQ error\n"); - return 0; - } + { + 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 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 + 3) & 0x3f) != 0x04; @@ -748,8 +721,7 @@ probe_pss_mss(struct address_info *hw_config) return probe_ms_sound(hw_config); } -void -attach_pss_mss(struct address_info *hw_config) +void attach_pss_mss(struct address_info *hw_config) { attach_ms_sound(hw_config); /* Slot 0 */ @@ -757,34 +729,31 @@ attach_pss_mss(struct address_info *hw_config) audio_devs[hw_config->slots[0]]->coproc = &pss_coproc_operations; } -void -unload_pss(struct address_info *hw_config) +void unload_pss(struct address_info *hw_config) { } -void -unload_pss_mpu(struct address_info *hw_config) +void unload_pss_mpu(struct address_info *hw_config) { #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) unload_mpu401(hw_config); #endif } -void -unload_pss_mss(struct address_info *hw_config) +void unload_pss_mss(struct address_info *hw_config) { unload_ms_sound(hw_config); } #ifdef MODULE -int pss_io = 0x220; +int pss_io = -1; -int mss_io = 0x530; -int mss_irq = 11; -int mss_dma = 1; +int mss_io = -1; +int mss_irq = -1; +int mss_dma = -1; -int mpu_io = 0x330; +int mpu_io = -1; int mpu_irq = -1; struct address_info cfgpss = { 0 /* pss_io */, 0, -1, -1 }; @@ -798,22 +767,20 @@ MODULE_PARM(mss_dma, "i"); MODULE_PARM(mpu_io, "i"); MODULE_PARM(mpu_irq, "i"); -static int fw_load = 0; -static int pssmpu = 0, pssmss = 0; +static int fw_load = 0; +static int pssmpu = 0, pssmss = 0; /* * Load a PSS sound card module */ -int -init_module(void) +int init_module(void) { -#if 0 - if (pss_io == -1 || irq == -1 || dma == -1) { - printk("pss: dma, irq and io must be set.\n"); - return -EINVAL; + if (pss_io == -1 || mss_io == -1 || mss_irq == -1 || mss_dma == -1) { + printk(KERN_INFO "pss: mss_io, mss_dma, mss_irq and pss_io must be set.\n"); + return -EINVAL; } -#endif + cfgpss.io_base = pss_io; cfgmss.io_base = mss_io; @@ -823,7 +790,8 @@ init_module(void) cfgmpu.io_base = mpu_io; cfgmpu.irq = mpu_irq; - if (!pss_synth) { + if (!pss_synth) + { fw_load = 1; pss_synthLen = mod_firmware_load("/etc/sound/pss_synth", (void *) &pss_synth); } @@ -845,8 +813,7 @@ init_module(void) return 0; } -void -cleanup_module(void) +void cleanup_module(void) { if (fw_load && pss_synth) kfree(pss_synth); diff --git a/drivers/sound/sb_audio.c b/drivers/sound/sb_audio.c index 9a0fe3c79..bf3a8dbef 100644 --- a/drivers/sound/sb_audio.c +++ b/drivers/sound/sb_audio.c @@ -1151,14 +1151,14 @@ void sb_audio_init(sb_devc * devc, char *name) } if ((devc->my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, - name, - driver, - sizeof(struct audio_driver), - audio_flags, - format_mask, - devc, - devc->dma8, - devc->dma8)) < 0) + name, + driver, + sizeof(struct audio_driver), + audio_flags, + format_mask, + devc, + devc->dma8, + devc->dma8)) < 0) { printk(KERN_ERR "sb: unable to install audio.\n"); return; diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c index fddf74b79..941422c3f 100644 --- a/drivers/sound/sb_card.c +++ b/drivers/sound/sb_card.c @@ -69,6 +69,7 @@ int trix = 0; /* Set trix=1 to load this as support for trix */ int pas2 = 0; /* Set pas2=1 to load this as support for pas2 */ int sm_games = 0; /* Mixer - see sb_mixer.c */ int acer = 0; /* Do acer notebook init */ +int mwave_bug = 0; /* Using the dreadful mwave sb emulation */ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); @@ -80,10 +81,11 @@ MODULE_PARM(mad16, "i"); MODULE_PARM(trix, "i"); MODULE_PARM(pas2, "i"); MODULE_PARM(sm_games, "i"); +MODULE_PARM(mwave_bug, "i"); -static int sbmpu = 0; +static int sbmpu = 0; -void *smw_free = NULL; +void *smw_free = NULL; int init_module(void) { @@ -119,8 +121,7 @@ int init_module(void) return 0; } -void -cleanup_module(void) +void cleanup_module(void) { if (smw_free) kfree(smw_free); @@ -133,19 +134,20 @@ cleanup_module(void) #else -#ifdef SM_GAMES +#ifdef CONFIG_SM_GAMES int sm_games = 1; - #else int sm_games = 0; - #endif -#ifdef SB_ACER +#ifdef CONFIG_SB_ACER int acer = 1; - #else int acer = 0; - +#endif +#ifdef CONFIG_SB_MWAVE +int mwave_bug = 1; +#else +int mwave_bug = 0; #endif #endif #endif diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c index 0f3e1e6aa..fcdcfcf2c 100644 --- a/drivers/sound/sb_common.c +++ b/drivers/sound/sb_common.c @@ -28,7 +28,6 @@ static sb_devc *detected_devc = NULL; /* For communication from probe to init */ static sb_devc *last_devc = NULL; /* For MPU401 initialization */ -static sb_devc *irq2devc[16] = {NULL}; static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6 }; @@ -123,15 +122,9 @@ static void sbintr(int irq, void *dev_id, struct pt_regs *dummy) int status; unsigned char src = 0xff; - sb_devc *devc = irq2devc[irq]; + sb_devc *devc = dev_id; - if (devc == NULL || devc->irq != irq) - { - DEB(printk("sbintr: Bogus interrupt IRQ%d\n", irq)); - return; - } devc->irq_ok = 1; - if (devc->model == MDL_SB16) { src = sb_getmixer(devc, IRQ_STAT); /* Interrupt source register */ @@ -710,6 +703,7 @@ void sb_dsp_init(struct address_info *hw_config) sb_devc *devc; char name[100]; extern int sb_be_quiet; + extern int mwave_bug; /* * Check if we had detected a SB device earlier @@ -743,21 +737,19 @@ void sb_dsp_init(struct address_info *hw_config) if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && hw_config->irq > 0) { /* IRQ setup */ - if (snd_set_irq_handler(hw_config->irq, sbintr, "soundblaster", devc->osp) < 0) + if (request_irq(hw_config->irq, sbintr, 0, "soundblaster", devc) < 0) { printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq); sound_unload_audiodev(devc->dev); return; } - irq2devc[hw_config->irq] = devc; devc->irq_ok = 0; if (devc->major == 4) if (!sb16_set_irq_hw(devc, devc->irq)) /* Unsupported IRQ */ { - snd_release_irq(devc->irq); + free_irq(devc->irq, devc); sound_unload_audiodev(devc->dev); - irq2devc[hw_config->irq] = NULL; return; } if ((devc->type == 0 || devc->type == MDL_ESS) && @@ -777,7 +769,7 @@ void sb_dsp_init(struct address_info *hw_config) /* Skip IRQ detection if SMP (doesn't work) */ devc->irq_ok = 1; #else - if (devc->major == 4 && devc->minor <= 11) /* Won't work */ + if ((devc->major == 4 && devc->minor <= 11 ) || mwave_bug ) /* Won't work */ devc->irq_ok = 1; else { @@ -883,6 +875,7 @@ void sb_dsp_init(struct address_info *hw_config) } } hw_config->card_subtype = devc->model; + hw_config->slots[0]=devc->dev; last_devc = devc; /* For SB MPU detection */ if (!(devc->caps & SB_NO_AUDIO) && devc->dma8 >= 0) @@ -915,15 +908,8 @@ void sb_dsp_disable_recording(int io_base) void sb_dsp_unload(struct address_info *hw_config) { sb_devc *devc; - int irq = hw_config->irq; - if (irq < 0) - irq *= -1; - - if (irq > 2 && irq < 16) - devc = irq2devc[irq]; - else - devc = NULL; + devc = audio_devs[hw_config->slots[0]]->devc; if (devc && devc->base == hw_config->io_base) { @@ -937,12 +923,12 @@ void sb_dsp_unload(struct address_info *hw_config) } if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && devc->irq > 0) { - snd_release_irq(devc->irq); - irq2devc[devc->irq] = NULL; + free_irq(devc->irq, devc); sound_unload_mixerdev(devc->my_mixerdev); sound_unload_mididev(devc->my_mididev); sound_unload_audiodev(devc->my_dev); } + kfree(devc); } else release_region(hw_config->io_base, 16); diff --git a/drivers/sound/sound_calls.h b/drivers/sound/sound_calls.h index aed677c89..416737f65 100644 --- a/drivers/sound/sound_calls.h +++ b/drivers/sound/sound_calls.h @@ -11,7 +11,6 @@ int DMAbuf_start_output(int dev, int buff_no, int l); int DMAbuf_move_wrpointer(int dev, int l); /* int DMAbuf_ioctl(int dev, unsigned int cmd, caddr_t arg, int local); */ void DMAbuf_init(int dev, int dma1, int dma2); -void DMAbuf_deinit(int dev); int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode); int DMAbuf_open_dma (int dev); void DMAbuf_close_dma (int dev); @@ -84,8 +83,9 @@ void MIDIbuf_init(void); /* From soundcard.c */ void request_sound_timer (int count); void sound_stop_timer(void); -int snd_set_irq_handler (int interrupt_level, void(*iproc)(int, void*, struct pt_regs *), char *name, int *osp); -void snd_release_irq(int vect); +/* These two are about to die.. */ +int snd_set_irq_handler (int interrupt_level, void(*iproc)(int, void*, struct pt_regs *), char *name, int *osp, void *dev_id); +void snd_release_irq(int vect, void *ptr); void sound_dma_malloc(int dev); void sound_dma_free(int dev); void conf_printf(char *name, struct address_info *hw_config); diff --git a/drivers/sound/sound_timer.c b/drivers/sound/sound_timer.c index 8a519e7e2..986668316 100644 --- a/drivers/sound/sound_timer.c +++ b/drivers/sound/sound_timer.c @@ -47,6 +47,14 @@ void reprogram_timer(void) { unsigned long usecs_per_tick; + /* + * The user is changing the timer rate before setting a timer + * slap, bad bad not allowed. + */ + + if(!tmr) + return; + usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase); /* diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index e23e5486e..fe3622a73 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #ifdef __KERNEL__ #include #include @@ -439,7 +439,7 @@ static int sound_open(struct inode *inode, struct file *file) case SND_DEV_CTL: dev >>= 4; -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) { char modname[20]; sprintf(modname, "mixer%d", dev); @@ -555,14 +555,14 @@ static int sound_mixer_ioctl(int mixdev, unsigned int cmd, caddr_t arg) { if (mixdev < 0 || mixdev >= MAX_MIXER_DEV) return -ENXIO; -#ifdef CONFIG_KERNELD +#ifdef CONFIG_KMOD /* Try to load the mixer... */ if (mixer_devs[mixdev] == NULL) { char modname[20]; sprintf(modname, "mixer%d", mixdev); request_module(modname); } -#endif /* CONFIG_KERNELD */ +#endif /* CONFIG_KMOD */ if (mixdev >= num_mixers || !mixer_devs[mixdev]) return -ENXIO; if (cmd == SOUND_MIXER_INFO) @@ -801,7 +801,7 @@ free_all_irqs(void) if (irqs & (1ul << i)) { printk(KERN_WARNING "Sound warning: IRQ%d was left allocated - fixed.\n", i); - snd_release_irq(i); + snd_release_irq(i, NULL); } } irqs = 0; @@ -895,14 +895,14 @@ void cleanup_module(void) } #endif -int snd_set_irq_handler(int interrupt_level, void (*iproc) (int, void *, struct pt_regs *), char *name, int *osp) +int snd_set_irq_handler(int interrupt_level, void (*iproc) (int, void *, struct pt_regs *), char *name, int *osp, void *dev_id) { - int retcode; - unsigned long flags; + int retcode; + unsigned long flags; save_flags(flags); cli(); - retcode = request_irq(interrupt_level, iproc, 0, name, NULL); + retcode = request_irq(interrupt_level, iproc, 0, name, dev_id); if (retcode < 0) { @@ -915,13 +915,13 @@ int snd_set_irq_handler(int interrupt_level, void (*iproc) (int, void *, struct return retcode; } -void snd_release_irq(int vect) +void snd_release_irq(int vect, void *dev_id) { if (!(irqs & (1ul << vect))) return; irqs &= ~(1ul << vect); - free_irq(vect, NULL); + free_irq(vect, dev_id); } int sound_alloc_dma(int chn, char *deviceID) diff --git a/drivers/sound/uart401.c b/drivers/sound/uart401.c index 7293e9047..2e7ed2a27 100644 --- a/drivers/sound/uart401.c +++ b/drivers/sound/uart401.c @@ -9,7 +9,15 @@ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * Changes: + * Alan Cox Reformatted, removed sound_mem usage, use normal Linux + * interrupt allocation. + * + * Status: + * Untested */ + #include #include @@ -19,45 +27,43 @@ #if (defined(CONFIG_UART401)||defined(CONFIG_MIDI)) || defined(MODULE) typedef struct uart401_devc - { - int base; - int irq; - int *osp; - void (*midi_input_intr) (int dev, unsigned char data); - int opened, disabled; - volatile unsigned char input_byte; - int my_dev; - int share_irq; - } +{ + int base; + int irq; + int *osp; + void (*midi_input_intr) (int dev, unsigned char data); + int opened, disabled; + volatile unsigned char input_byte; + int my_dev; + int share_irq; +} uart401_devc; static uart401_devc *detected_devc = NULL; -static uart401_devc *irq2devc[16] = -{NULL}; #define DATAPORT (devc->base) #define COMDPORT (devc->base+1) #define STATPORT (devc->base+1) -static int -uart401_status(uart401_devc * devc) +static int uart401_status(uart401_devc * devc) { return inb(STATPORT); } + #define input_avail(devc) (!(uart401_status(devc)&INPUT_AVAIL)) #define output_ready(devc) (!(uart401_status(devc)&OUTPUT_READY)) -static void -uart401_cmd(uart401_devc * devc, unsigned char cmd) + +static void uart401_cmd(uart401_devc * devc, unsigned char cmd) { outb((cmd), COMDPORT); } -static int -uart401_read(uart401_devc * devc) + +static int uart401_read(uart401_devc * devc) { return inb(DATAPORT); } -static void -uart401_write(uart401_devc * devc, unsigned char byte) + +static void uart401_write(uart401_devc * devc, unsigned char byte) { outb((byte), DATAPORT); } @@ -71,30 +77,26 @@ uart401_write(uart401_devc * devc, unsigned char byte) static int reset_uart401(uart401_devc * devc); static void enter_uart_mode(uart401_devc * devc); -static void -uart401_input_loop(uart401_devc * devc) +static void uart401_input_loop(uart401_devc * devc) { while (input_avail(devc)) - { - unsigned char c = uart401_read(devc); - - if (c == MPU_ACK) - devc->input_byte = c; - else if (devc->opened & OPEN_READ && devc->midi_input_intr) - devc->midi_input_intr(devc->my_dev, c); - } + { + unsigned char c = uart401_read(devc); + + if (c == MPU_ACK) + devc->input_byte = c; + else if (devc->opened & OPEN_READ && devc->midi_input_intr) + devc->midi_input_intr(devc->my_dev, c); + } } -void -uart401intr(int irq, void *dev_id, struct pt_regs *dummy) +void uart401intr(int irq, void *dev_id, struct pt_regs *dummy) { - uart401_devc *devc; + uart401_devc *devc = dev_id; if (irq < 1 || irq > 15) return; - devc = irq2devc[irq]; - if (devc == NULL) return; @@ -108,12 +110,12 @@ uart401_open(int dev, int mode, void (*output) (int dev) ) { - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; + uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; if (devc->opened) - { - return -EBUSY; - } + { + return -EBUSY; + } while (input_avail(devc)) uart401_read(devc); @@ -125,21 +127,19 @@ uart401_open(int dev, int mode, return 0; } -static void -uart401_close(int dev) +static void uart401_close(int dev) { - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; + uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; reset_uart401(devc); devc->opened = 0; } -static int -uart401_out(int dev, unsigned char midi_byte) +static int uart401_out(int dev, unsigned char midi_byte) { - int timeout; - unsigned long flags; - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; + int timeout; + unsigned long flags; + uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; if (devc->disabled) return 1; @@ -163,36 +163,32 @@ uart401_out(int dev, unsigned char midi_byte) for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); if (!output_ready(devc)) - { - printk("MPU-401: Timeout - Device not responding\n"); + { + printk(KERN_WARNING "uart401: Timeout - Device not responding\n"); devc->disabled = 1; reset_uart401(devc); enter_uart_mode(devc); return 1; - } + } uart401_write(devc, midi_byte); return 1; } -static int -uart401_start_read(int dev) +static int uart401_start_read(int dev) { return 0; } -static int -uart401_end_read(int dev) +static int uart401_end_read(int dev) { return 0; } -static void -uart401_kick(int dev) +static void uart401_kick(int dev) { } -static int -uart401_buffer_status(int dev) +static int uart401_buffer_status(int dev) { return 0; } @@ -203,7 +199,9 @@ uart401_buffer_status(int dev) static struct midi_operations uart401_operations = { - {"MPU-401 (UART) MIDI", 0, 0, SNDCARD_MPU401}, + { + "MPU-401 (UART) MIDI", 0, 0, SNDCARD_MPU401 + }, &std_midi_synth, {0}, uart401_open, @@ -218,11 +216,10 @@ static struct midi_operations uart401_operations = NULL }; -static void -enter_uart_mode(uart401_devc * devc) +static void enter_uart_mode(uart401_devc * devc) { - int ok, timeout; - unsigned long flags; + int ok, timeout; + unsigned long flags; save_flags(flags); cli(); @@ -242,11 +239,10 @@ enter_uart_mode(uart401_devc * devc) restore_flags(flags); } -void -attach_uart401(struct address_info *hw_config) +void attach_uart401(struct address_info *hw_config) { - uart401_devc *devc; - char *name = "MPU-401 (UART) MIDI"; + uart401_devc *devc; + char *name = "MPU-401 (UART) MIDI"; if (hw_config->name) name = hw_config->name; @@ -255,80 +251,75 @@ attach_uart401(struct address_info *hw_config) return; - devc = (uart401_devc *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(uart401_devc))); - sound_mem_sizes[sound_nblocks] = sizeof(uart401_devc); - if (sound_nblocks < 1024) - sound_nblocks++;; + devc = (uart401_devc *) kmalloc(sizeof(uart401_devc), GFP_KERNEL); if (devc == NULL) - { - printk(KERN_WARNING "uart401: Can't allocate memory\n"); - return; - } + { + printk(KERN_WARNING "uart401: Can't allocate memory\n"); + return; + } memcpy((char *) devc, (char *) detected_devc, sizeof(uart401_devc)); detected_devc = NULL; devc->irq = hw_config->irq; if (devc->irq < 0) - { - devc->share_irq = 1; - devc->irq *= -1; - } else + { + devc->share_irq = 1; + devc->irq *= -1; + } + else devc->share_irq = 0; if (devc->irq < 1 || devc->irq > 15) + { + kfree(devc); return; + } if (!devc->share_irq) - if (snd_set_irq_handler(devc->irq, uart401intr, "MPU-401 UART", devc->osp) < 0) - { - printk(KERN_WARNING "uart401: Failed to allocate IRQ%d\n", devc->irq); - devc->share_irq = 1; - } - irq2devc[devc->irq] = devc; + { + if (request_irq(devc->irq, uart401intr, 0, "MPU-401 UART", devc) < 0) + { + printk(KERN_WARNING "uart401: Failed to allocate IRQ%d\n", devc->irq); + devc->share_irq = 1; + } + } devc->my_dev = sound_alloc_mididev(); request_region(hw_config->io_base, 4, "MPU-401 UART"); enter_uart_mode(devc); if (devc->my_dev == -1) - { - printk(KERN_INFO "uart401: Too many midi devices detected\n"); - return; - } + { + printk(KERN_INFO "uart401: Too many midi devices detected\n"); + kfree(devc); + return; + } conf_printf(name, hw_config); std_midi_synth.midi_dev = devc->my_dev; - - - midi_devs[devc->my_dev] = (struct midi_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct midi_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct midi_operations); - - if (sound_nblocks < 1024) - sound_nblocks++;; + midi_devs[devc->my_dev] = (struct midi_operations *)kmalloc(sizeof(struct midi_operations), GFP_KERNEL); if (midi_devs[devc->my_dev] == NULL) - { - printk("uart401: Failed to allocate memory\n"); - sound_unload_mididev(devc->my_dev); - return; - } + { + printk(KERN_ERR "uart401: Failed to allocate memory\n"); + sound_unload_mididev(devc->my_dev); + kfree(devc); + devc=NULL; + return; + } memcpy((char *) midi_devs[devc->my_dev], (char *) &uart401_operations, sizeof(struct midi_operations)); midi_devs[devc->my_dev]->devc = devc; - - - midi_devs[devc->my_dev]->converter = (struct synth_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct synth_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct synth_operations); - - if (sound_nblocks < 1024) - sound_nblocks++; - + midi_devs[devc->my_dev]->converter = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL); if (midi_devs[devc->my_dev]->converter == NULL) - { - printk(KERN_WARNING "uart401: Failed to allocate memory\n"); - sound_unload_mididev(devc->my_dev); - return; - } + { + printk(KERN_WARNING "uart401: Failed to allocate memory\n"); + sound_unload_mididev(devc->my_dev); + kfree(midi_devs[devc->my_dev]); + kfree(devc); + devc=NULL; + return; + } memcpy((char *) midi_devs[devc->my_dev]->converter, (char *) &std_midi_synth, sizeof(struct synth_operations)); @@ -339,10 +330,9 @@ attach_uart401(struct address_info *hw_config) devc->opened = 0; } -static int -reset_uart401(uart401_devc * devc) +static int reset_uart401(uart401_devc * devc) { - int ok, timeout, n; + int ok, timeout, n; /* * Send the RESET command. Try again if no success at the first time. @@ -351,31 +341,33 @@ reset_uart401(uart401_devc * devc) ok = 0; for (n = 0; n < 2 && !ok; n++) - { - for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); - - devc->input_byte = 0; - uart401_cmd(devc, MPU_RESET); - - /* - * Wait at least 25 msec. This method is not accurate so let's make the - * loop bit longer. Cannot sleep since this is called during boot. - */ - - for (timeout = 50000; timeout > 0 && !ok; timeout--) - if (devc->input_byte == MPU_ACK) /* Interrupt */ - ok = 1; - else if (input_avail(devc)) - if (uart401_read(devc) == MPU_ACK) - ok = 1; - - } + { + for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); + devc->input_byte = 0; + uart401_cmd(devc, MPU_RESET); + /* + * Wait at least 25 msec. This method is not accurate so let's make the + * loop bit longer. Cannot sleep since this is called during boot. + */ + + for (timeout = 50000; timeout > 0 && !ok; timeout--) + { + if (devc->input_byte == MPU_ACK) /* Interrupt */ + ok = 1; + else if (input_avail(devc)) + { + if (uart401_read(devc) == MPU_ACK) + ok = 1; + } + } + } if (ok) - { - DEB(printk("Reset UART401 OK\n")); - } else + { + DEB(printk("Reset UART401 OK\n")); + } + else DDB(printk("Reset UART401 failed - No hardware detected.\n")); if (ok) @@ -386,14 +378,12 @@ reset_uart401(uart401_devc * devc) return ok; } -int -probe_uart401(struct address_info *hw_config) +int probe_uart401(struct address_info *hw_config) { - int ok = 0; - unsigned long flags; - + int ok = 0; + unsigned long flags; static uart401_devc hw_info; - uart401_devc *devc = &hw_info; + uart401_devc *devc = &hw_info; DDB(printk("Entered probe_uart401()\n")); @@ -422,21 +412,10 @@ probe_uart401(struct address_info *hw_config) return ok; } -void -unload_uart401(struct address_info *hw_config) +void unload_uart401(struct address_info *hw_config) { - uart401_devc *devc; - - int irq = hw_config->irq; - - if (irq < 0) - { - irq *= -1; - } - if (irq < 1 || irq > 15) - return; - - devc = irq2devc[irq]; + uart401_devc *devc; + devc = midi_devs[hw_config->slots[4]]->devc; if (devc == NULL) return; @@ -444,47 +423,47 @@ unload_uart401(struct address_info *hw_config) release_region(hw_config->io_base, 4); if (!devc->share_irq) - snd_release_irq(devc->irq); - + free_irq(devc->irq, devc); + sound_unload_mididev(hw_config->slots[4]); if (devc) + { + kfree(midi_devs[devc->my_dev]->converter); + kfree(midi_devs[devc->my_dev]); + kfree(devc); devc = NULL; - sound_unload_mididev(hw_config->slots[4]); + } } #ifdef MODULE -int io = -1; -int irq = -1; +int io = -1; +int irq = -1; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); struct address_info hw; -int -init_module(void) +int init_module(void) { /* Can be loaded either for module use or to provide functions to others */ if (io != -1 && irq != -1) - { - printk("MPU-401 UART driver Copyright (C) Hannu Savolainen 1993-1997"); - hw.irq = irq; - hw.io_base = io; - if (probe_uart401(&hw) == 0) - return -ENODEV; - attach_uart401(&hw); - } + { + printk(KERN_INFO "MPU-401 UART driver Copyright (C) Hannu Savolainen 1993-1997"); + hw.irq = irq; + hw.io_base = io; + if (probe_uart401(&hw) == 0) + return -ENODEV; + attach_uart401(&hw); + } SOUND_LOCK; return 0; } -void -cleanup_module(void) +void cleanup_module(void) { if (io != -1 && irq != -1) - { - unload_uart401(&hw); - } + unload_uart401(&hw); /* FREE SYMTAB */ SOUND_LOCK_END; } diff --git a/drivers/sound/uart6850.c b/drivers/sound/uart6850.c index 932be1846..b26e75a89 100644 --- a/drivers/sound/uart6850.c +++ b/drivers/sound/uart6850.c @@ -10,6 +10,11 @@ * Extended by Alan Cox for Red Hat Software. Now a loadable MIDI driver. * 28/4/97 - (C) Copyright Alan Cox. Released under the GPL version 2. * + * Alan Cox: Updated for new modular code. Removed snd_* irq handling. Now + * uses native linux resources + * + * Status: Testing required + * */ #include #include @@ -297,7 +302,7 @@ int probe_uart6850(struct address_info *hw_config) uart6850_base = hw_config->io_base; uart6850_irq = hw_config->irq; - if (snd_set_irq_handler(uart6850_irq, m6850intr, "MIDI6850", uart6850_osp) < 0) + if (request_irq(uart6850_irq, m6850intr, 0, "MIDI6850", NULL) < 0) return 0; ok = reset_uart6850(); @@ -307,7 +312,7 @@ int probe_uart6850(struct address_info *hw_config) void unload_uart6850(struct address_info *hw_config) { - snd_release_irq(hw_config->irq); + free_irq(hw_config->irq, NULL); sound_unload_mididev(hw_config->slots[4]); } diff --git a/drivers/sound/v_midi.c b/drivers/sound/v_midi.c index 12c221a68..4820d5f36 100644 --- a/drivers/sound/v_midi.c +++ b/drivers/sound/v_midi.c @@ -2,15 +2,22 @@ * sound/v_midi.c * * The low level driver for the Sound Blaster DS chips. - */ -/* + * + * * Copyright (C) by Hannu Savolainen 1993-1996 * * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. * ?? + * + * Changes + * Alan Cox Modularisation, changed memory allocations + * + * Status + * Untested */ + #include #include -- cgit v1.2.3