portman2x4.c
来自「linux 内核源代码」· C语言 代码 · 共 877 行 · 第 1/2 页
C
877 行
/* Wait for settling */ while ((portman_read_status(pm) & ESTB) == ESTB) cpu_relax();}static int portman_probe(struct parport *p){ /* Initialize the parallel port data register. Will set Rx clocks * low in case we happen to be addressing the Rx ports at this time. */ /* 1 */ parport_write_data(p, 0); /* Initialize the parallel port command register, thus initializing * hardware handshake lines to midi box: * * Strobe = 0 * Interrupt Enable = 0 */ /* 2 */ parport_write_control(p, 0); /* Check if Portman PC/P 2x4 is out there. */ /* 3 */ parport_write_control(p, RXDATA0); /* Write Strobe=0 to command reg. */ /* Check for ESTB to be clear */ /* 4 */ if ((parport_read_status(p) & ESTB) == ESTB) return 1; /* CODE 1 - Strobe Failure. */ /* Set for RXDATA0 where no damage will be done. */ /* 5 */ parport_write_control(p, RXDATA0 + STROBE); /* Write Strobe=1 to command reg. */ /* 6 */ if ((parport_read_status(p) & ESTB) != ESTB) return 1; /* CODE 1 - Strobe Failure. */ /* 7 */ parport_write_control(p, 0); /* Reset Strobe=0. */ /* Check if Tx circuitry is functioning properly. If initialized * unit TxEmpty is false, send out char and see if if goes true. */ /* 8 */ parport_write_control(p, TXDATA0); /* Tx channel 0, strobe off. */ /* If PCP channel's TxEmpty is set (TxEmpty is read through the PP * Status Register), then go write data. Else go back and wait. */ /* 9 */ if ((parport_read_status(p) & TXEMPTY) == 0) return 2; /* Return OK status. */ return 0;}static int portman_device_init(struct portman *pm){ portman_flush_input(pm, 0); portman_flush_input(pm, 1); return 0;}/********************************************************************* * Rawmidi *********************************************************************/static int snd_portman_midi_open(struct snd_rawmidi_substream *substream){ return 0;}static int snd_portman_midi_close(struct snd_rawmidi_substream *substream){ return 0;}static void snd_portman_midi_input_trigger(struct snd_rawmidi_substream *substream, int up){ struct portman *pm = substream->rmidi->private_data; unsigned long flags; spin_lock_irqsave(&pm->reg_lock, flags); if (up) pm->mode[substream->number] |= PORTMAN2X4_MODE_INPUT_TRIGGERED; else pm->mode[substream->number] &= ~PORTMAN2X4_MODE_INPUT_TRIGGERED; spin_unlock_irqrestore(&pm->reg_lock, flags);}static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *substream, int up){ struct portman *pm = substream->rmidi->private_data; unsigned long flags; unsigned char byte; spin_lock_irqsave(&pm->reg_lock, flags); if (up) { while ((snd_rawmidi_transmit(substream, &byte, 1) == 1)) portman_write_midi(pm, substream->number, byte); } spin_unlock_irqrestore(&pm->reg_lock, flags);}static struct snd_rawmidi_ops snd_portman_midi_output = { .open = snd_portman_midi_open, .close = snd_portman_midi_close, .trigger = snd_portman_midi_output_trigger,};static struct snd_rawmidi_ops snd_portman_midi_input = { .open = snd_portman_midi_open, .close = snd_portman_midi_close, .trigger = snd_portman_midi_input_trigger,};/* Create and initialize the rawmidi component */static int __devinit snd_portman_rawmidi_create(struct snd_card *card){ struct portman *pm = card->private_data; struct snd_rawmidi *rmidi; struct snd_rawmidi_substream *substream; int err; err = snd_rawmidi_new(card, CARD_NAME, 0, PORTMAN_NUM_OUTPUT_PORTS, PORTMAN_NUM_INPUT_PORTS, &rmidi); if (err < 0) return err; rmidi->private_data = pm; strcpy(rmidi->name, CARD_NAME); rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; pm->rmidi = rmidi; /* register rawmidi ops */ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_portman_midi_output); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_portman_midi_input); /* name substreams */ /* output */ list_for_each_entry(substream, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams, list) { sprintf(substream->name, "Portman2x4 %d", substream->number+1); } /* input */ list_for_each_entry(substream, &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams, list) { pm->midi_input[substream->number] = substream; sprintf(substream->name, "Portman2x4 %d", substream->number+1); } return err;}/********************************************************************* * parport stuff *********************************************************************/static void snd_portman_interrupt(void *userdata){ unsigned char midivalue = 0; struct portman *pm = ((struct snd_card*)userdata)->private_data; spin_lock(&pm->reg_lock); /* While any input data is waiting */ while ((portman_read_status(pm) & INT_REQ) == INT_REQ) { /* If data available on channel 0, read it and stuff it into the queue. */ if (portman_data_avail(pm, 0)) { /* Read Midi */ midivalue = portman_read_midi(pm, 0); /* put midi into queue... */ if (pm->mode[0] & PORTMAN2X4_MODE_INPUT_TRIGGERED) snd_rawmidi_receive(pm->midi_input[0], &midivalue, 1); } /* If data available on channel 1, read it and stuff it into the queue. */ if (portman_data_avail(pm, 1)) { /* Read Midi */ midivalue = portman_read_midi(pm, 1); /* put midi into queue... */ if (pm->mode[1] & PORTMAN2X4_MODE_INPUT_TRIGGERED) snd_rawmidi_receive(pm->midi_input[1], &midivalue, 1); } } spin_unlock(&pm->reg_lock);}static int __devinit snd_portman_probe_port(struct parport *p){ struct pardevice *pardev; int res; pardev = parport_register_device(p, DRIVER_NAME, NULL, NULL, NULL, 0, NULL); if (!pardev) return -EIO; if (parport_claim(pardev)) { parport_unregister_device(pardev); return -EIO; } res = portman_probe(p); parport_release(pardev); parport_unregister_device(pardev); return res ? -EIO : 0;}static void __devinit snd_portman_attach(struct parport *p){ struct platform_device *device; device = platform_device_alloc(PLATFORM_DRIVER, device_count); if (!device) return; /* Temporary assignment to forward the parport */ platform_set_drvdata(device, p); if (platform_device_add(device) < 0) { platform_device_put(device); return; } /* Since we dont get the return value of probe * We need to check if device probing succeeded or not */ if (!platform_get_drvdata(device)) { platform_device_unregister(device); return; } /* register device in global table */ platform_devices[device_count] = device; device_count++;}static void snd_portman_detach(struct parport *p){ /* nothing to do here */}static struct parport_driver portman_parport_driver = { .name = "portman2x4", .attach = snd_portman_attach, .detach = snd_portman_detach};/********************************************************************* * platform stuff *********************************************************************/static void snd_portman_card_private_free(struct snd_card *card){ struct portman *pm = card->private_data; struct pardevice *pardev = pm->pardev; if (pardev) { if (pm->pardev_claimed) parport_release(pardev); parport_unregister_device(pardev); } portman_free(pm);}static int __devinit snd_portman_probe(struct platform_device *pdev){ struct pardevice *pardev; struct parport *p; int dev = pdev->id; struct snd_card *card = NULL; struct portman *pm = NULL; int err; p = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) return -ENOENT; if ((err = snd_portman_probe_port(p)) < 0) return err; card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) { snd_printd("Cannot create card\n"); return -ENOMEM; } strcpy(card->driver, DRIVER_NAME); strcpy(card->shortname, CARD_NAME); sprintf(card->longname, "%s at 0x%lx, irq %i", card->shortname, p->base, p->irq); pardev = parport_register_device(p, /* port */ DRIVER_NAME, /* name */ NULL, /* preempt */ NULL, /* wakeup */ snd_portman_interrupt, /* ISR */ PARPORT_DEV_EXCL, /* flags */ (void *)card); /* private */ if (pardev == NULL) { snd_printd("Cannot register pardevice\n"); err = -EIO; goto __err; } if ((err = portman_create(card, pardev, &pm)) < 0) { snd_printd("Cannot create main component\n"); parport_unregister_device(pardev); goto __err; } card->private_data = pm; card->private_free = snd_portman_card_private_free; if ((err = snd_portman_rawmidi_create(card)) < 0) { snd_printd("Creating Rawmidi component failed\n"); goto __err; } /* claim parport */ if (parport_claim(pardev)) { snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base); err = -EIO; goto __err; } pm->pardev_claimed = 1; /* init device */ if ((err = portman_device_init(pm)) < 0) goto __err; platform_set_drvdata(pdev, card); /* At this point card will be usable */ if ((err = snd_card_register(card)) < 0) { snd_printd("Cannot register card\n"); goto __err; } snd_printk(KERN_INFO "Portman 2x4 on 0x%lx\n", p->base); return 0;__err: snd_card_free(card); return err;}static int __devexit snd_portman_remove(struct platform_device *pdev){ struct snd_card *card = platform_get_drvdata(pdev); if (card) snd_card_free(card); return 0;}static struct platform_driver snd_portman_driver = { .probe = snd_portman_probe, .remove = __devexit_p(snd_portman_remove), .driver = { .name = PLATFORM_DRIVER }};/********************************************************************* * module init stuff *********************************************************************/static void snd_portman_unregister_all(void){ int i; for (i = 0; i < SNDRV_CARDS; ++i) { if (platform_devices[i]) { platform_device_unregister(platform_devices[i]); platform_devices[i] = NULL; } } platform_driver_unregister(&snd_portman_driver); parport_unregister_driver(&portman_parport_driver);}static int __init snd_portman_module_init(void){ int err; if ((err = platform_driver_register(&snd_portman_driver)) < 0) return err; if (parport_register_driver(&portman_parport_driver) != 0) { platform_driver_unregister(&snd_portman_driver); return -EIO; } if (device_count == 0) { snd_portman_unregister_all(); return -ENODEV; } return 0;}static void __exit snd_portman_module_exit(void){ snd_portman_unregister_all();}module_init(snd_portman_module_init);module_exit(snd_portman_module_exit);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?