summaryrefslogtreecommitdiffstats
path: root/drivers/sound/uart401.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sound/uart401.c')
-rw-r--r--drivers/sound/uart401.c176
1 files changed, 74 insertions, 102 deletions
diff --git a/drivers/sound/uart401.c b/drivers/sound/uart401.c
index 0b7eb3297..3b1c4417e 100644
--- a/drivers/sound/uart401.c
+++ b/drivers/sound/uart401.c
@@ -15,6 +15,7 @@
* interrupt allocation. Protect against bogus unload
* Fixed to allow IRQ > 15
* Christoph Hellwig Adapted to module_init/module_exit
+ * Arnaldo C. de Melo got rid of check_region
*
* Status:
* Untested
@@ -40,8 +41,6 @@ typedef struct uart401_devc
}
uart401_devc;
-static uart401_devc *detected_devc = NULL;
-
#define DATAPORT (devc->base)
#define COMDPORT (devc->base+1)
#define STATPORT (devc->base+1)
@@ -241,95 +240,6 @@ static void enter_uart_mode(uart401_devc * devc)
restore_flags(flags);
}
-void attach_uart401(struct address_info *hw_config, struct module *owner)
-{
- uart401_devc *devc;
- char *name = "MPU-401 (UART) MIDI";
-
-
- if (hw_config->name)
- name = hw_config->name;
-
- if (detected_devc == NULL)
- return;
-
-
- devc = (uart401_devc *) kmalloc(sizeof(uart401_devc), GFP_KERNEL);
- if (devc == NULL)
- {
- 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 = 0;
-
- if (!devc->share_irq)
- {
- 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");
- kfree(devc);
- return;
- }
- conf_printf(name, hw_config);
-
- std_midi_synth.midi_dev = devc->my_dev;
- midi_devs[devc->my_dev] = (struct midi_operations *)kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
- if (midi_devs[devc->my_dev] == NULL)
- {
- 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));
-
- if (owner)
- midi_devs[devc->my_dev]->owner = owner;
-
- midi_devs[devc->my_dev]->devc = devc;
- 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");
- kfree(midi_devs[devc->my_dev]);
- kfree(devc);
- sound_unload_mididev(devc->my_dev);
- devc=NULL;
- return;
- }
- memcpy((char *) midi_devs[devc->my_dev]->converter, (char *) &std_midi_synth,
- sizeof(struct synth_operations));
-
- strcpy(midi_devs[devc->my_dev]->info.name, name);
- midi_devs[devc->my_dev]->converter->id = "UART401";
- hw_config->slots[4] = devc->my_dev;
- sequencer_init();
- devc->opened = 0;
-}
-
static int reset_uart401(uart401_devc * devc)
{
int ok, timeout, n;
@@ -379,21 +289,28 @@ static int reset_uart401(uart401_devc * devc)
return ok;
}
-int probe_uart401(struct address_info *hw_config)
+int probe_uart401(struct address_info *hw_config, struct module *owner)
{
+ uart401_devc *devc;
+ char *name = "MPU-401 (UART) MIDI";
int ok = 0;
unsigned long flags;
- static uart401_devc hw_info;
- uart401_devc *devc = &hw_info;
DDB(printk("Entered probe_uart401()\n"));
/* Default to "not found" */
hw_config->slots[4] = -1;
- detected_devc = NULL;
- if (check_region(hw_config->io_base, 4))
+ if (!request_region(hw_config->io_base, 4, "MPU-401 UART")) {
+ printk(KERN_INFO "uart401: could not request_region(%d, 4)\n", hw_config->io_base);
return 0;
+ }
+
+ devc = kmalloc(sizeof(uart401_devc), GFP_KERNEL);
+ if (!devc) {
+ printk(KERN_WARNING "uart401: Can't allocate memory\n");
+ goto cleanup_region;
+ }
devc->base = hw_config->io_base;
devc->irq = hw_config->irq;
@@ -409,10 +326,67 @@ int probe_uart401(struct address_info *hw_config)
ok = reset_uart401(devc);
restore_flags(flags);
- if (ok)
- detected_devc = devc;
+ if (!ok)
+ goto cleanup_devc;
- return ok;
+ if (hw_config->name)
+ name = hw_config->name;
+
+ if (devc->irq < 0) {
+ devc->share_irq = 1;
+ devc->irq *= -1;
+ } else
+ devc->share_irq = 0;
+
+ if (!devc->share_irq)
+ 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();
+ enter_uart_mode(devc);
+
+ if (devc->my_dev == -1) {
+ printk(KERN_INFO "uart401: Too many midi devices detected\n");
+ goto cleanup_irq;
+ }
+ conf_printf(name, hw_config);
+ std_midi_synth.midi_dev = devc->my_dev;
+ midi_devs[devc->my_dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
+ if (!midi_devs[devc->my_dev]) {
+ printk(KERN_ERR "uart401: Failed to allocate memory\n");
+ goto cleanup_unload_mididev;
+ }
+ memcpy(midi_devs[devc->my_dev], &uart401_operations, sizeof(struct midi_operations));
+
+ if (owner)
+ midi_devs[devc->my_dev]->owner = owner;
+
+ midi_devs[devc->my_dev]->devc = devc;
+ midi_devs[devc->my_dev]->converter = kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
+ if (!midi_devs[devc->my_dev]->converter) {
+ printk(KERN_WARNING "uart401: Failed to allocate memory\n");
+ goto cleanup_midi_devs;
+ }
+ memcpy(midi_devs[devc->my_dev]->converter, &std_midi_synth, sizeof(struct synth_operations));
+ strcpy(midi_devs[devc->my_dev]->info.name, name);
+ midi_devs[devc->my_dev]->converter->id = "UART401";
+ hw_config->slots[4] = devc->my_dev;
+ sequencer_init();
+ devc->opened = 0;
+ return 1;
+cleanup_midi_devs:
+ kfree(midi_devs[devc->my_dev]);
+cleanup_unload_mididev:
+ sound_unload_mididev(devc->my_dev);
+cleanup_irq:
+ if (!devc->share_irq)
+ free_irq(devc->irq, devc);
+cleanup_devc:
+ kfree(devc);
+cleanup_region:
+ release_region(hw_config->io_base, 4);
+ return 0;
}
void unload_uart401(struct address_info *hw_config)
@@ -446,7 +420,6 @@ void unload_uart401(struct address_info *hw_config)
sound_unload_mididev(hw_config->slots[4]);
}
-EXPORT_SYMBOL(attach_uart401);
EXPORT_SYMBOL(probe_uart401);
EXPORT_SYMBOL(unload_uart401);
EXPORT_SYMBOL(uart401intr);
@@ -469,9 +442,8 @@ static int __init init_uart401(void)
to others */
if (cfg_mpu.io_base != -1 && cfg_mpu.irq != -1) {
printk(KERN_INFO "MPU-401 UART driver Copyright (C) Hannu Savolainen 1993-1997");
- if (probe_uart401(&cfg_mpu) == 0)
+ if (!probe_uart401(&cfg_mpu, THIS_MODULE))
return -ENODEV;
- attach_uart401(&cfg_mpu, THIS_MODULE);
}
return 0;