PS/2 device detection strange output on Bochs
PS/2 device detection strange output on Bochs
Hi, this thread replaces old one "PS/2 Mouse help" as too much thread crapping was in it.
By some reason PS/2 returns 85 (0x55) as first identification byte response to 0xF2 command (identify command). It does not seem to be ACK, Resend, or anything like that. What I do is:
SendPort() and ReceivePort():
I post images instead of PHPBB3 code blocks since they are much more readable.
By some reason PS/2 returns 85 (0x55) as first identification byte response to 0xF2 command (identify command). It does not seem to be ACK, Resend, or anything like that. What I do is:
SendPort() and ReceivePort():
I post images instead of PHPBB3 code blocks since they are much more readable.
-
- Member
- Posts: 5587
- Joined: Mon Mar 25, 2013 7:01 pm
Re: PS/2 device detection strange output on Bochs
No they're not. Post your code as text.Lukand wrote:I post images instead of PHPBB3 code blocks since they are much more readable.
Re: PS/2 device detection strange output on Bochs
If you say so...
Code: Select all
inline void Ps2SendPort(uint8 i, uint8 data)
{
if(i==1)
{
WaitSignal();
outb(0x64, 0xD4);
}
WaitSignal();
outb(0x64,data);
}
inline uint8 Ps2ReceivePort(uint8 i=0)
{
WaitData();
return inb(0x60);
}
Code: Select all
uint8 rcv[2];
//Recognize first port
Ps2SendPort(0, 0xF2); //Identify command
Ps2ReceivePort(0); //Receive ACK
rcv[0]=Ps2ReceivePort(0); //Receive first identification byte
if(!WaitData())rcv[1]=inb(0x60); //Check if there is second identification byte
else rcv[1]=0x00; //there is not
DeviceInit(0,&rcv[0]); //Port 0 device initialization
//Recognize second port
Ps2SendPort(1, 0xF2); //Identify command
Ps2ReceivePort(1); //Receive ACK
rcv[0]=Ps2ReceivePort(1); //Receive first identification byte
if(!WaitData())rcv[1]=inb(0x60); //Check if there is second identification byte
else rcv[1]=0x00; //there is not
DeviceInit(1,&rcv[0]); //Port 1 device initialization
-
- Member
- Posts: 5587
- Joined: Mon Mar 25, 2013 7:01 pm
Re: PS/2 device detection strange output on Bochs
Lukand wrote:Code: Select all
inline void Ps2SendPort(uint8 i, uint8 data) { // snip outb(0x64,data); }
Re: PS/2 device detection strange output on Bochs
Finally I got something to work. Thank you a lot Octocontrabass, myself I would never find that .
But, due to some strange reason on Bochs now I got "MF2 keyboard with translation enabled in the PS/2" according to this table on first port.
(0xAB 0x41)
But, due to some strange reason on Bochs now I got "MF2 keyboard with translation enabled in the PS/2" according to this table on first port.
(0xAB 0x41)
-
- Member
- Posts: 5587
- Joined: Mon Mar 25, 2013 7:01 pm
Re: PS/2 device detection strange output on Bochs
What's strange about it? Were you not expecting to get that kind of response from the keyboard?
Re: PS/2 device detection strange output on Bochs
I should get normal MF2 keyboard, not the one with translation, right!?
-
- Member
- Posts: 5587
- Joined: Mon Mar 25, 2013 7:01 pm
Re: PS/2 device detection strange output on Bochs
Translation is enabled by default.
You may also want to look at initializing the PS/2 controller. (Note that the self-test command, 0xAA, will completely reset some keyboard controllers, so you must disable translation after the self-test to ensure it gets disabled properly.)
You may also want to look at initializing the PS/2 controller. (Note that the self-test command, 0xAA, will completely reset some keyboard controllers, so you must disable translation after the self-test to ensure it gets disabled properly.)
Re: PS/2 device detection strange output on Bochs
Hi,
However, the last time I messed around with PS/2 in Bochs (years ago now) I found that (unlike real hardware) Bochs didn't allow the translation to be disabled. I don't know if Bochs has been fixed since, but I suspect (assuming that you do try to disable translation) that perhaps it hasn't.
In general; I approach this sort of problem by doing it right (for correct hardware, or the majority of hardware) and then adding work-arounds for dodgy (real or emulated) hardware - I don't like the alternative (the "lowest common denominator" approach where you nerf the OS on all hardware to avoid problems on less common dodgy hardware).
For Bochs keyboard (back then), this meant a special keyboard driver that was only used if translation couldn't be disabled. Sadly, the translation is destructive (a "reverse translation" can't recover the original bytes) so the simpler option isn't viable.
Cheers,
Brendan
Should, yes (assuming that you do try to disable translation).Lukand wrote:I should get normal MF2 keyboard, not the one with translation, right!?
However, the last time I messed around with PS/2 in Bochs (years ago now) I found that (unlike real hardware) Bochs didn't allow the translation to be disabled. I don't know if Bochs has been fixed since, but I suspect (assuming that you do try to disable translation) that perhaps it hasn't.
In general; I approach this sort of problem by doing it right (for correct hardware, or the majority of hardware) and then adding work-arounds for dodgy (real or emulated) hardware - I don't like the alternative (the "lowest common denominator" approach where you nerf the OS on all hardware to avoid problems on less common dodgy hardware).
For Bochs keyboard (back then), this meant a special keyboard driver that was only used if translation couldn't be disabled. Sadly, the translation is destructive (a "reverse translation" can't recover the original bytes) so the simpler option isn't viable.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: PS/2 device detection strange output on Bochs
Translation can be disabled in the current version of Bochs, but I found that Parallels Desktop 7 always has it enabled no matter what. So, when Parallels Desktop is detected, I have to undo the translation before passing the data to the keyboard driver.
Re: PS/2 device detection strange output on Bochs
It seems I could not get input from mouse now. What does happens is that keyboard interferes mouse, eg. input from keyboard has interference with mouse input. Through moving mouse and clicking on it does nothing, but typing keys does.
Sadly there's no way to seperate keyboard input with mouse input except using semaphores as used in multithreading...
Sadly there's no way to seperate keyboard input with mouse input except using semaphores as used in multithreading...
Re: PS/2 device detection strange output on Bochs
I may be getting into something I shouldn't here, but I am going to try.
The PS/2 controller uses the exact same I/O port(s) for both mouse and keyboard. If a key is pressed on the keyboard, it sends the scan code to the exact same I/O port as it does when sending data from the mouse. i.e.: If the mouse sends a packet to the PS/2 controller, the controller sends it to the same I/O port as the one it sent for the keyboard. As for the PS/2 controller, this is called the Output Buffer and holds one byte at a time. It will hold this byte there until you read it, where it will then send another byte to that Output Buffer until all bytes are read.
At first you would think that this is confusing and how the heck do I determine which byte is for what.
For example, let's say that I type a key on the keyboard and that key produces a three byte code. At the exact same time, I move the mouse and that motion produces a 4 byte packet. The Output Buffer may look something like this:
So, how do I tell which bytes are the key scan code and which bytes are the mouse packet?
Simple!
The PS/2 controller will fire an interrupt each time it places a byte into the Output Buffer. The trick is, and here is the funny thing, it fires a different IRQ for the mouse than it does for the Keyboard.
Therefore, when the IRQ for the Mouse fires, have that Handler read from the Output Buffer, set a flag, send the EOI, and return. Nothing more.
When the IRQ for the Keyboard fires, have that Handler read from the Output Buffer, set a flag, send the EOI, and return. Again, nothing more.
Then your keyboard and mouse drivers watch for their respected flag. When set, it adds this byte to its internal buffer. When a full packet has been received from either the mouse or the keyboard, the corresponding driver does something with it.
It is really that simple. Really.
The PS/2 controller uses the exact same I/O port(s) for both mouse and keyboard. If a key is pressed on the keyboard, it sends the scan code to the exact same I/O port as it does when sending data from the mouse. i.e.: If the mouse sends a packet to the PS/2 controller, the controller sends it to the same I/O port as the one it sent for the keyboard. As for the PS/2 controller, this is called the Output Buffer and holds one byte at a time. It will hold this byte there until you read it, where it will then send another byte to that Output Buffer until all bytes are read.
At first you would think that this is confusing and how the heck do I determine which byte is for what.
For example, let's say that I type a key on the keyboard and that key produces a three byte code. At the exact same time, I move the mouse and that motion produces a 4 byte packet. The Output Buffer may look something like this:
Code: Select all
key[0] -> XX
XX <- Mouse[0]
key[1] -> XX
XX <- Mouse[1]
key[2] -> XX
XX <- Mouse[2]
XX <- Mouse[3]
Simple!
The PS/2 controller will fire an interrupt each time it places a byte into the Output Buffer. The trick is, and here is the funny thing, it fires a different IRQ for the mouse than it does for the Keyboard.
Therefore, when the IRQ for the Mouse fires, have that Handler read from the Output Buffer, set a flag, send the EOI, and return. Nothing more.
When the IRQ for the Keyboard fires, have that Handler read from the Output Buffer, set a flag, send the EOI, and return. Again, nothing more.
Then your keyboard and mouse drivers watch for their respected flag. When set, it adds this byte to its internal buffer. When a full packet has been received from either the mouse or the keyboard, the corresponding driver does something with it.
It is really that simple. Really.
Re: PS/2 device detection strange output on Bochs
Ben Lunt,
I'm trying to avoid overhauling I/O by interrupts. Doesn't mouse just send interrupts only when automatic packet interrupts are enabled? Or I'm wrong? And is it good idea to create semaphores (eg. when waiting for mouse input disable the port where keyboard is located in)?
I'm trying to avoid overhauling I/O by interrupts. Doesn't mouse just send interrupts only when automatic packet interrupts are enabled? Or I'm wrong? And is it good idea to create semaphores (eg. when waiting for mouse input disable the port where keyboard is located in)?
-
- Member
- Posts: 5587
- Joined: Mon Mar 25, 2013 7:01 pm
Re: PS/2 device detection strange output on Bochs
Why are you trying to avoid it?Lukand wrote:I'm trying to avoid overhauling I/O by interrupts.
The only way to tell which PS/2 device sent the data is using interrupts. If you're not using interrupts, then you can't tell if you're receiving data from the first port or the second port.
The mouse doesn't send interrupts at all, it send bytes. The PS/2 controller raises an interrupt request when it receives a byte. If you prevent the mouse from sending bytes, or you prevent the PS/2 controller from sending IRQs, then you won't receive any interrupts.Lukand wrote:Doesn't mouse just send interrupts only when automatic packet interrupts are enabled? Or I'm wrong?
No. That creates a race condition. The PS/2 controller can receive a byte from the keyboard at the same time you're disabling the keyboard port, so the next byte you receive comes from the keyboard even though you've just disabled it.Lukand wrote:And is it good idea to create semaphores (eg. when waiting for mouse input disable the port where keyboard is located in)?
Re: PS/2 device detection strange output on Bochs
Hi,
Mostly; there are 3 different devices, so you need 3 separate drivers (one for the PS/2 controller itself, and one for each type of device that could be plugged into a PS/2 port) in the same way that you'd have multiple drivers for USB (one for the USB controller, and one for each type of device that could be plugged into a USB port).
Note: By "3 separate drivers" I don't necessarily mean (e.g.) 3 separate processes (for micro-kernel) or 3 separate "kernel modules" (for monolithic). It could just be "logical separation" (where the source code is split into 3 separate directories, but it's all assembled/compiled/linked together and becomes a single executable/process/kernel module).
The "PS/2 controller driver" would initialise (and test) the controller, determine if there are any devices plugged into the PS/2 ports and get their "device ID", then use the "device ID" to determine which drivers are needed and start the right driver (note that you can have 2 keyboards and no mouse, or 2 mouse and no keyboards, or a bar-code scanner and a touch-pad and no keyboards and no mouse, or...).
The drivers for devices plugged into a PS/2 port (e.g. the keyboard driver and mouse driver) would ask the "PS/2 controller driver" to send bytes to whichever port it's connected to, and the "PS/2 controller driver" would tell the driver for a PS/2 port about any bytes received. The drivers for devices plugged into a PS/2 port would never use any IO ports or IRQs themselves. If you port your OS to a different type of computer (with a different type of PS/2 controller - e.g. the PL050 on some ARM SoCs) you only need to write a new "PS/2 controller driver" and (assuming C source code or something) will not need to change any driver for a PS/2 device (the keyboard, mouse, bar-code, touch-pad, touch-screen, .... drivers).
Another thing the "PS/2 controller driver" would do is handle "hot-plug" - if the user unplugs a device it'd tell (terminate?) whichever driver was using that PS/2 port, and if a user plugs a device into a previously empty PS/2 port the "PS/2 controller driver" would figure out the type of device that was plugged in and start an appropriate driver. The "PS/2 controller driver" could also (optionally) monitor the other drivers - e.g. if your keyboard driver crashes then "PS/2 controller driver" might notice and start another keyboard driver; and if you install a newer keyboard driver then "PS/2 controller driver" might notice and terminate the old driver and start the new one.
Finally; it'd probably be nice to build support for debugging into your "PS/2 controller driver"; so that anyone writing a driver for any PS/2 device can enable debugging for whichever port the device is connected to and see all bytes received by their driver and see all bytes sent by their driver (without having any code in their driver). This just makes it much easier for people (you) to write drivers for different PS/2 devices.
Cheers,
Brendan
I told you that would happen (that the drivers would interfere with each other) and how to avoid the problem last month.Lukand wrote:It seems I could not get input from mouse now. What does happens is that keyboard interferes mouse, eg. input from keyboard has interference with mouse input. Through moving mouse and clicking on it does nothing, but typing keys does.
Sadly there's no way to seperate keyboard input with mouse input except using semaphores as used in multithreading...
Mostly; there are 3 different devices, so you need 3 separate drivers (one for the PS/2 controller itself, and one for each type of device that could be plugged into a PS/2 port) in the same way that you'd have multiple drivers for USB (one for the USB controller, and one for each type of device that could be plugged into a USB port).
Note: By "3 separate drivers" I don't necessarily mean (e.g.) 3 separate processes (for micro-kernel) or 3 separate "kernel modules" (for monolithic). It could just be "logical separation" (where the source code is split into 3 separate directories, but it's all assembled/compiled/linked together and becomes a single executable/process/kernel module).
The "PS/2 controller driver" would initialise (and test) the controller, determine if there are any devices plugged into the PS/2 ports and get their "device ID", then use the "device ID" to determine which drivers are needed and start the right driver (note that you can have 2 keyboards and no mouse, or 2 mouse and no keyboards, or a bar-code scanner and a touch-pad and no keyboards and no mouse, or...).
The drivers for devices plugged into a PS/2 port (e.g. the keyboard driver and mouse driver) would ask the "PS/2 controller driver" to send bytes to whichever port it's connected to, and the "PS/2 controller driver" would tell the driver for a PS/2 port about any bytes received. The drivers for devices plugged into a PS/2 port would never use any IO ports or IRQs themselves. If you port your OS to a different type of computer (with a different type of PS/2 controller - e.g. the PL050 on some ARM SoCs) you only need to write a new "PS/2 controller driver" and (assuming C source code or something) will not need to change any driver for a PS/2 device (the keyboard, mouse, bar-code, touch-pad, touch-screen, .... drivers).
Another thing the "PS/2 controller driver" would do is handle "hot-plug" - if the user unplugs a device it'd tell (terminate?) whichever driver was using that PS/2 port, and if a user plugs a device into a previously empty PS/2 port the "PS/2 controller driver" would figure out the type of device that was plugged in and start an appropriate driver. The "PS/2 controller driver" could also (optionally) monitor the other drivers - e.g. if your keyboard driver crashes then "PS/2 controller driver" might notice and start another keyboard driver; and if you install a newer keyboard driver then "PS/2 controller driver" might notice and terminate the old driver and start the new one.
Finally; it'd probably be nice to build support for debugging into your "PS/2 controller driver"; so that anyone writing a driver for any PS/2 device can enable debugging for whichever port the device is connected to and see all bytes received by their driver and see all bytes sent by their driver (without having any code in their driver). This just makes it much easier for people (you) to write drivers for different PS/2 devices.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.