-
Notifications
You must be signed in to change notification settings - Fork 3.1k
sound/midi: Clarify MPU-401 init #1905
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
NOTE: this depends on pull requests freebsd#1905 and freebsd#1892. MIDI code in emu10kx driver was disabled due to possible locking problems in MIDI core, which should have been corrected by freebsd#1905. Here, we also fixed that the card interrupts were enabled too early and disabled too late. This was tested under FreeBSD 15.0 using a SoundBlaster Audigy (chipset CA0100, I will also try one Audigy2). Signed-off-by: Nicolas Provost <dev@nicolas-provost.fr>
NOTE: this depends on pull requests freebsd#1902 and freebsd#1905. MIDI code in emu10kx driver was disabled due to possible locking problems in MIDI core, which should have been corrected by freebsd#1902. Here, we also fixed that the card interrupts were enabled too early and disabled too late. This was tested under FreeBSD 15.0 using a SoundBlaster Audigy (chipset CA0100, I will also try one Audigy2). Signed-off-by: Nicolas Provost <dev@nicolas-provost.fr>
christosmarg
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly good, just some notes.
sys/dev/sound/midi/mpu401.c
Outdated
| for (i = 0; i < MPU_TRYDATA; i++) { | ||
| if (TXRDY(m)) | ||
| return (1); | ||
| else if (RXRDY(m)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I mentioned in the old PR, it'd be good to have a comment here explaining the reason for discarding input. It is not obvious to someone looking at this for the first time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll rework all these comments soon.
sys/dev/sound/midi/mpu401.c
Outdated
| return (0); | ||
| } | ||
|
|
||
| /* Some cards only support UART mode but others will start in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment should start on the next line. Same applies to other multi-line comments.
sys/dev/sound/midi/mpu401.c
Outdated
| } | ||
|
|
||
| /* Some cards only support UART mode but others will start in | ||
| * "Intelligent" mode, so we must try to switch to UART mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we say that "we must try to switch to UART mode" but I do not think it is entirely clear why we must do this. I'm not saying it's not correct to do this, but the comment should also explain the "why" in my opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I know, the intelligent mode may change on-the-fly the MIDI messages in some way, whereas in UART mode, the raw bytes are simply transmitted, then safely processed by userspace tools. When a card supports the intelligent mode, it is enabled by default.
sys/dev/sound/midi/mpu401.c
Outdated
| i++; | ||
| /* DELAY(100); */ | ||
| s = STATUS(m); | ||
| else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} else {
Same below.
sys/dev/sound/midi/mpu401.c
Outdated
| if ((m->flags & M_TXEN) && (m->si)) { | ||
| callout_reset(&m->timer, 1, mpu401_timeout, m); | ||
| /* Read and buffer all input bytes, then send data. | ||
| * Note that pending input may inhibits data sending. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inhibits -> inhibit
sys/dev/sound/midi/mpu401.c
Outdated
| callout_reset(&m->timer, 1, mpu401_timeout, m); | ||
| /* Read and buffer all input bytes, then send data. | ||
| * Note that pending input may inhibits data sending. | ||
| * Spurious cards may also be sticky, so limit the count of tries |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should explain what "sticky" means. Also "number of tries", not "count of tries".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed this because there is no spurious (for example: bad interrupts) card in the FreeBSD tree, to my knowledge.
sys/dev/sound/midi/mpu401.c
Outdated
| * (probably MPU cards have no more than 16 bytes as internal buffer). | ||
| */ | ||
| for (i = 0; RXRDY(m) && i < MPU_INTR_BUF; i++) { | ||
| /* XXX we should check midi_in has room in its buffer, else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this patch does not do what the comment here says?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the midi_in function (midi.c) should be modified to report when its buffer is full. Ideally we should ensure midi_in has room to store the byte before reading it from the MPU. MIDI commands are multi-byte (often 3 bytes) so each byte matters.
As I noticed you're working on midi.c, are you sure the data queues (midiq.h) are safe ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be more precise, to get the room available in the input queue, we need a lock on the midi device, which is taken in the function midi_in.
For example we could modify midi_in to return the number of bytes available in the input queue if it is passed a NULL buffer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE (25/12/10): there is a panic in midi_read/midi_write when opening in blocking mode, I think it is the msleep call.
3e283cd to
21b2ca2
Compare
NOTE: this depends on pull request freebsd#1905. MIDI code in cmi driver (C-Media sound cards) was disabled due to possible locking problems in MIDI core, which should have been corrected by freebsd#1902 (or another pending PR). This was tested under FreeBSD 15.0 against a CM8738 generic card. Signed-off-by: Nicolas Provost <dev@nicolas-provost.fr>
NOTE: this depends on pull requests freebsd#1902 (or similar pending PR) and freebsd#1905. MIDI code in emu10kx driver was disabled due to possible locking problems in MIDI core, which should have been corrected by freebsd#1902. Here, we also fixed that the card interrupts were enabled too early and disabled too late. This was tested under FreeBSD 15.0 using a SoundBlaster Audigy (chipset CA0100, I will also try one Audigy2). Signed-off-by: Nicolas Provost <dev@nicolas-provost.fr>
NOTE: this depends on pull request freebsd#1905. MIDI code in cmi driver (C-Media sound cards) was disabled due to possible locking problems in MIDI core, which should have been corrected by freebsd#1902 (or another pending PR). This was tested under FreeBSD 15.0 against a CM8738 generic card. Signed-off-by: Nicolas Provost <dev@nicolas-provost.fr>
NOTE: this depends on pull request freebsd#1905. MIDI code in cmi driver (C-Media sound cards) was disabled due to possible locking problems in MIDI core, which should have been corrected by freebsd#1902 (or another pending PR). This was tested under FreeBSD 15.0 against a CM8738 generic card. Signed-off-by: Nicolas Provost <dev@nicolas-provost.fr>
First, we try to better init MPU-401 chip so that it is put in UART mode using the recommended way: <reset><wait_for_ack><enable_uart_mode>. This must be done before the interrupt handler is active, so that the ACK is the only data received between the two commands. Actually this setup may occur after interrupts are enabled for the card. Second, there is a mechanism to periodically call the interrupt handler, probably to address very old or spurious cards. We remove this because all cards in the tree using MPU-401 (CSMedia chips, Crystal chips, and Soundblasters) have proper interrupt handling for MIDI events. Rather old hardware is concerned; but PCI soundcards may work fine using a PCIe-to-PCI bridge, and some have pretty decent chipsets. Signed-off-by: Nicolas Provost <dev@nicolas-provost.fr>
Only midi.c and mpu401.c files are modified.
- changes to MPU-401 published in freebsd#1905
- remove MPU_CALLBACKP from the MPU interface (same as MPU_CALLBACK)
- changes to midi.c published in freebsd#1902 (locks)
= midi.c: fix a kernel panic when opening a MIDI device in blocking mode
- midi.c: remove useless 'busy' field in MIDI device data
- midi.c: silently ignore errors when closing device (ex: process crash)
- midi.c: correct how to unload MIDI device when unloading a driver
- midi.c: clarify when rchan/wchan are set to 1 or 0
|
Thank you for taking the time to contribute to FreeBSD!
Please review CONTRIBUTING.md, then update and push your branch again. |
|
Made a test using the following:
MIDI reads and writes are well processed, in blocking and non-blocking mode, using my Soundblaster Audigy2 (emu10kx). |
First, we try to better init MPU-401 chip so that it is put in UART mode using the recommended way: <wait_for_ack><enable_uart_mode>. This must be done before the interrupt handler is active, so that the ACK is the only data received between the two commands. Actually this setup may occur after interrupts are enabled for the card.
Second, there is a mechanism to periodically call the interrupt handler, probably to address very old or spurious cards. We remove this because all cards in the tree using MPU-401 (CSMedia chips, Crystal chips, and Soundblasters) have proper interrupt handling for MIDI events.
Rather old hardware is concerned; but PCI soundcards may work fine using a PCIe-to-PCI bridge, and some have pretty decent chipsets.
25/12/09: testing against some hardware