Hi, all,
I made a patch for proper Ctrl-Break handling. This is useful for MS-DOS or compatible operating systems like FreeDOS.
When Ctrl-Break is detected, it clears the keyboard buffer, sets the Ctrl-Break flag at [0040h:0071h], invokes int 1Bh and then adds 0000h to the keyboard buffer. If a non-enhanced keyboard is present, Ctrl-Scroll Lock works just like Ctrl-Break. This seems to be the "standard" BIOS behaviour, at least on the PCs I tested.
The patch was tested with MS-DOS 6.22, running under qemu.
I'm new to git (and this is my first SeaBIOS patch ever), so I'm not sure what's the preferred way to submit patches. I just did a "git diff" and attached the result. Sorry if that's not the best way :)
Nikolay
On Thu, Jul 21, 2011 at 02:49:08AM +0300, Nikolay Nikolov wrote:
Hi, all,
I made a patch for proper Ctrl-Break handling. This is useful for MS-DOS or compatible operating systems like FreeDOS.
When Ctrl-Break is detected, it clears the keyboard buffer, sets the Ctrl-Break flag at [0040h:0071h], invokes int 1Bh and then adds 0000h to the keyboard buffer. If a non-enhanced keyboard is present, Ctrl-Scroll Lock works just like Ctrl-Break. This seems to be the "standard" BIOS behaviour, at least on the PCs I tested.
The patch was tested with MS-DOS 6.22, running under qemu.
Thanks. Please see my comments below.
I'm new to git (and this is my first SeaBIOS patch ever), so I'm not sure what's the preferred way to submit patches. I just did a "git diff" and attached the result. Sorry if that's not the best way :)
Best way is to run "git format-patch", but "git diff" is also fine. Please do include a "Signed-off-by" line in your commit message or email message though.
diff --git a/src/kbd.c b/src/kbd.c index 1977c5d..e85f92d 100644 --- a/src/kbd.c +++ b/src/kbd.c @@ -406,7 +406,6 @@ __process_key(u8 scancode) }
// XXX - PrtScr should cause int 0x05
// XXX - Ctrl+Break should cause int 0x1B // XXX - SysReq should cause int 0x15/0x85
switch (scancode) {
@@ -474,12 +473,31 @@ __process_key(u8 scancode) flags1 &= ~KF1_NUM; break;
- case 0x46: /* Scroll Lock press */
flags1 |= KF1_SCROLL;
flags0 ^= KF0_SCROLLACTIVE;
- case 0x46: /* Scroll Lock or Ctrl-Break press */
if (flags2 & KF2_LAST_E0
|| (!(flags2 & KF2_101KBD) && (flags0 & KF0_CTRLACTIVE))) {
// Ctrl-Break press
flags2 &= ~KF2_LAST_E0;
SET_BDA(kbd_flag2, flags2);
SET_BDA(break_flag, 0x80);
SET_BDA(kbd_buf_tail, GET_BDA(kbd_buf_head));
asm volatile ("int $0x1B":::"memory");
Can this use call16_simpint() instead? If not, calling an interrupt should probably backup/restore the register state.
enqueue_key(0, 0);
RBIL implies the 0000 should be added to the keyboard buffer before the int 0x1B - though I'm not really familiar enough to say which is really correct.
-Kevin
Kevin O'Connor wrote:
]On Thu, Jul 21, 2011 at 02:49:08AM +0300, Nikolay Nikolov wrote: ]> Hi, all, ]> ]> I made a patch for proper Ctrl-Break handling. This is useful for ]> MS-DOS or compatible operating systems like FreeDOS.
...
]> + enqueue_key(0, 0); ] ]RBIL implies the 0000 should be added to the keyboard buffer before ]the int 0x1B - though I'm not really familiar enough to say which is ]really correct.
It looks like Phoenix legacy BIOS and AMI legacy BIOS add the 0000 after int 1b.
Thanks, Scott
] ]-Kevin
On Thu, Jul 21, 2011 at 12:56:05AM -0500, Scott Duplichan wrote:
Kevin O'Connor wrote: ]RBIL implies the 0000 should be added to the keyboard buffer before ]the int 0x1B - though I'm not really familiar enough to say which is ]really correct.
It looks like Phoenix legacy BIOS and AMI legacy BIOS add the 0000 after int 1b.
Okay. Thanks.
-Kevin
On 07/21/2011 03:51 AM, Kevin O'Connor wrote:
I'm new to git (and this is my first SeaBIOS patch ever), so I'm not sure what's the preferred way to submit patches. I just did a "git diff" and attached the result. Sorry if that's not the best way :)
Best way is to run "git format-patch", but "git diff" is also fine. Please do include a "Signed-off-by" line in your commit message or email message though.
ok:
Signed-off-by: Nikolay Nikolov nickysn@users.sourceforge.net
asm volatile ("int $0x1B":::"memory");
Can this use call16_simpint() instead? If not, calling an interrupt should probably backup/restore the register state.
I'm not sure if the registers need to be saved for int 1Bh. I don't know what the "spec" says about it. MS-DOS and FreeDOS by themselves certainly don't need it - they don't change any of the registers on return from their int 1B handlers. Also, the BIOSes I checked didn't seem to care about saving any registers before calling int 1B. On the other hand, potentially any DOS application might want to install its own int 1B handler and we don't know if some of them destroy the values in some registers but still happens to work with the most common BIOSes (by accident or otherwise). But saving all registers adds an extra overhead on the stack that may turn out to be unnecessary? What happens if we tell gcc in that inline asm block that all registers may be destroyed. Will it increase the overhead on the stack or will it just generate slightly less efficient code?
enqueue_key(0, 0);
RBIL implies the 0000 should be added to the keyboard buffer before the int 0x1B - though I'm not really familiar enough to say which is really correct.
I have tested this on several BIOSes and most of them add it after int 0x1B. These include:
an AWARD BIOS on a GA-K8NF9 mainboard Insyde H2o BIOS on a Sony VAIO laptop Microsoft Windows NT/2000/XP/Vista/7's dos box (NTVDM.EXE) MS-DOS 6.22's own keyb.exe driver, which replaces the BIOS' int 09h handler.
I have also found at least one BIOS, that adds it *before* int 0x1B. It's an IBM ThinkPad R30 laptop, with an IBM branded BIOS. Anyhow, I assumed that adding it after int 1B is more "standard", because it appears to be more common and at least that's what Microsoft does.
Nikolay
On Thu, Jul 21, 2011 at 07:51:12PM +0300, Nikolay Nikolov wrote:
On 07/21/2011 03:51 AM, Kevin O'Connor wrote:
asm volatile ("int $0x1B":::"memory");
Can this use call16_simpint() instead? If not, calling an interrupt should probably backup/restore the register state.
I'm not sure if the registers need to be saved for int 1Bh. I don't know what the "spec" says about it. MS-DOS and FreeDOS by themselves certainly don't need it - they don't change any of the registers on return from their int 1B handlers. Also, the BIOSes I checked didn't seem to care about saving any registers before calling int 1B. On the other hand, potentially any DOS application might want to install its own int 1B handler and we don't know if some of them destroy the values in some registers but still happens to work with the most common BIOSes (by accident or otherwise).
Right - no sane 1B handler would alter register state, but it would be safer to do a backup/restore.
But saving all registers adds an extra overhead on the stack that may turn out to be unnecessary? What happens if we tell gcc in that inline asm block that all registers may be destroyed. Will it increase the overhead on the stack or will it just generate slightly less efficient code?
There is a tool in SeaBIOS which attempts to calculate stack usage:
objdump -m i386 -M i8086 -M suffix -d out/rom16.o | tools/checkstack.py
A full backup can be done with:
asm volatile ( "pushl %%ebp\n" "sti\n" "int $0x1B\n" "cli\n" "cld\n" "popl %%ebp" : : : "eax", "ebx", "ecx", "edx", "esi", "edi", "cc", "memory");
Replacing just the above in your patch does seem to increase stack usage a bit. However, I was able to play with it (use tail-recursion, use "noinline") to the point where I suspect it's possible to do the backup with no additional stack usage.
enqueue_key(0, 0);
RBIL implies the 0000 should be added to the keyboard buffer before the int 0x1B - though I'm not really familiar enough to say which is really correct.
I have tested this on several BIOSes and most of them add it after int 0x1B. These include:
an AWARD BIOS on a GA-K8NF9 mainboard Insyde H2o BIOS on a Sony VAIO laptop Microsoft Windows NT/2000/XP/Vista/7's dos box (NTVDM.EXE) MS-DOS 6.22's own keyb.exe driver, which replaces the BIOS' int 09h handler.
I have also found at least one BIOS, that adds it *before* int 0x1B. It's an IBM ThinkPad R30 laptop, with an IBM branded BIOS. Anyhow, I assumed that adding it after int 1B is more "standard", because it appears to be more common and at least that's what Microsoft does.
Okay thanks. After is fine.
-Kevin