Skip to content

Conversation

@n-p-soft
Copy link
Contributor

@n-p-soft n-p-soft commented Nov 13, 2025

First, we try to better initialize the 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 trigger the interrupt handler which is using the Giant lock, probably to address very old (ISA ?) or spurious cards. Giant lock being removed, we disable this when our new init succeeds.

Rather old hardware is concerned; but a PCI soundcard may work fine using a PCIe-to-PCI bridge, and some cards have pretty decent chipsets.

Signed-off-by: Nicolas Provost [email protected]

Signed-off-by: Nicolas Provost <[email protected]>
@github-actions
Copy link

github-actions bot commented Nov 13, 2025

Thank you for taking the time to contribute to FreeBSD!
There are a few issues that need to be fixed:

Please review CONTRIBUTING.md, then update and push your branch again.

Copy link
Contributor

@christosmarg christosmarg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an initial review. Also note that I do not own a physical MIDI device (only USB ones), so I'm unable to test this.

I think it is necessary to update the commit message with an explanation of your approach and what these changes do, as they are not really obvious.

static void mpu401_mcallback(struct snd_midi *, void *, int);
static void mpu401_mcallbackp(struct snd_midi *, void *, int);
static const char *mpu401_mdescr(struct snd_midi *, void *, int);
static const char *mpu401_mprovider(struct snd_midi *, void *);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these needed somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not, I started working on 13.5 source tree..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have made a few cleanups in the MIDI codebase, so I'd strongly advise you do your development on main (-CURRENT)

}

#define MPU_TIMEOUT 50
#define MPU_PAUSE pause_sbt("mpusetup", SBT_1MS, 0, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest you define this as an inline function instead.

}
printf("mpu401_minit failed active sensing\n");
return 1;
return (0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the rationale for merging parts of this with mpu401_setup()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This init is now run before the interrupt handler is active. The function returns 0 even on failure because we may have a card that is always in UART mode.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should also definitely be documented, and also explain why this should run before the interrupt handler.

static int
mpu401_intr(struct mpu401 *m)
{
MIDI_TYPE b;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this type? What does it expand to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type was used in the file before (see midi.h) ! I agree it should be resolved to unsigned char.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said in a previous comment, please write the patches on top of main, not 13.5.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok ! Was wondering is someone was interested by these changes, and the starting point for me was a project under 13.5.

* Note that pending input may inhibits data sending.
* Spurious cards may also be sticky..
*/
for (i = 0; RXRDY(m) && i < 512; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose your comment about "pending input may inhibits data sending" is probably why you cap to 512 iterations, but why 512 iterations specifically? Same question applies to loop below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you say, it is an upper bound. I've really not idea what to set here -512 is probably too much. I've no such sticky card but I read that this may happen (probably no more nowadays -ISA cards ?).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should be documented IMHO.

if (midi_out(m->mid, &b, 1))
WRITE(m, b);
else
break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current mpu401_intr() returns in this case, is there a reason we break here instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the callout_reset be called in this case ?
Also, we can avoid missing one byte in this code but this case is tied to midi_in/midi_out functions in midi.c.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really sure about the callout to be honest.

#define MPU_INPUTBUSY 0x80
#define MPU_TRYDATA 50
#define MPU_DELAY 2500
#define MPU_INTR_BUF 64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current value is 16, why are you increasing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is related to the changes I'm currently working on in midi.c (functions midi_in and midi_out). I will probably publish changes for both midi.c and mpu401.c.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is needed by a follow-up patch, then that change should be in that patch instead, but also documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, to explain my goals: I noticed the MIDI support in sound/pci/emu10kx.c is not enabled for unknown reasons. I've enabled it for my SoundBlaster Audigy 2 (two fixes in the code) but this brings me to review midi.c and mpu401.c. In midi.c, there may be locking issues due to the two mutexes (one is probably enough) and perhaps buffering problems. In mpu401.c, the init was not optimal. My Audigy's MIDI-IN port is now working but some work is to be done. Is there a PCI card with a really working MIDI port under FreeBSD ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are locking issues indeed, and I'm pretty sure quite a few Lock Order Reversals. In fact, for months now my plan has been to scrap the whole current MIDI codebase and rewrite it cleanly. We could try to address some of the obvious issues temporarily at least, but do know that I will most likely rewrite this anyway. The current structure is rather obsolete and confusing, and does not work with USB MIDI.

If you do own physical MIDI devices, I would appreciate it a lot if we could do some testing together.

Copy link
Contributor

@christosmarg christosmarg Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a PCI card with a really working MIDI port under FreeBSD ?

Not really sure to be honest. Haven't checked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm currently planning:

  • mpu401.c: update changes to match branch 'main'.
  • midi.c: remove one of the two mutexes to avoid possible inter-locks. I think only midi.c and mpu401.are directly concerned in the whole kernel.
  • midi.c: rework midi_in and replace the current buffering queue with a simple buffer [currently testing]. Same thing for midi-out (is it currently working ?).
  • midi.c: code cleaning
  • pci/: enable MIDI for SoundBlaster Audigy 2 cards [currently testing]. Test other cards for MIDI support.
  • take care of not breaking too much OSS !

PCI devices that are concerned are quite old, but work well using a PCIe-to-PCI bridge, and some have pretty decent hardware.

@christosmarg
Copy link
Contributor

The new commits are confusing and quite hard to see what's going on. The second commit especially (35d1d1c) seems to be deleting what I already removed in e4b3198. The rest of the commits seem to be mixed up also.

Could you please clean this up first? That is, combine everything into one commit, and make sure your branch is tracking the most recent main. First git pull on main, and then in your branch (assuming you don't work on main directly): git rebase main.

@n-p-soft n-p-soft closed this Nov 19, 2025
@n-p-soft n-p-soft deleted the mpu-init branch November 19, 2025 13:06
@n-p-soft
Copy link
Contributor Author

n-p-soft commented Nov 19, 2025 via email

n-p-soft and others added 5 commits November 19, 2025 13:23
… 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 trigger the interrupt handler which is using the Giant lock, probably to address very old (ISA ?) or spurious cards. Giant lock being removed, we disable this when our new init succeeds.

Rather old hardware is concerned; but a PCI soundcard may work fine using a PCIe-to-PCI bridge, and some cards have pretty decent chipsets.

Signed-off-by: Nicolas Provost <[email protected]>
…ode 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 trigger the interrupt handler which is using the Giant lock, probably to address very old (ISA ?) or spurious cards. Giant lock being removed, we disable this when our new init succeeds.

Rather old hardware is concerned; but a PCI soundcard may work fine using a PCIe-to-PCI bridge, and some cards have pretty decent chipsets.

Signed-off-by: Nicolas Provost <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants