keyboard/mouse input in pmode
keyboard/mouse input in pmode
how do i read data from the keyboard and mouse in protected mode? i have used int 16h in the past for keyboard input in real mode, but i dont know how to input anything in pmode, are there ports to read from or what?
RE:keyboard/mouse input in pmode
You have to have an IDT setup that has ISRs for the TIMER,KEYBOARD,etc.
the keyboard ISR needs to read port 0x60 on every KEYBOARD INT.
For the mouse, if its a serial mouse then you need to access the serial port directly (RS232 (i think)) or if its a PS2 mouse then it is also programmed through ports in the keyboard. get docs on keyboard and mouse hardware for more info, there is a lot of things needed to be done before they work well in Pmode. eg you will need to reprogram the PIC to use different INT numbers for the interrupts
the keyboard ISR needs to read port 0x60 on every KEYBOARD INT.
For the mouse, if its a serial mouse then you need to access the serial port directly (RS232 (i think)) or if its a PS2 mouse then it is also programmed through ports in the keyboard. get docs on keyboard and mouse hardware for more info, there is a lot of things needed to be done before they work well in Pmode. eg you will need to reprogram the PIC to use different INT numbers for the interrupts
RE:keyboard/mouse input in pmode
With all due respect, the idea that you need an IDT and a keyboard ISR in order to read the keyboard is -wrong-.
There is a wonderful concept out there known as a "polling-mode driver", which doesn't get nearly the attention it should. You just check the device every so often to see if it needs servicing.
The guts of my keyboard driver fit in about 2k of source (not including the keycode->ascii translation table), and includes hooks for a PS/2 mouse driver, yet doesn't have an interrupt handler. It wasn't needed when I wrote it, and it isn't needed now.
There is a wonderful concept out there known as a "polling-mode driver", which doesn't get nearly the attention it should. You just check the device every so often to see if it needs servicing.
The guts of my keyboard driver fit in about 2k of source (not including the keycode->ascii translation table), and includes hooks for a PS/2 mouse driver, yet doesn't have an interrupt handler. It wasn't needed when I wrote it, and it isn't needed now.
RE:keyboard/mouse input in pmode
would you mind explaining how the "polling-mode driver" works in more detail and how to check if the device needs servicing and input from it or include a little code?
RE:keyboard/mouse input in pmode
Okay, a little code and a little explanation.
Code is in a somewhat forth-like language, so it may not be what you're used to.
This is excerpted from the keyboard driver in my OS, the most relevant-seeming 4 lines, with explanations. All numbers below are in hexadecimal.
: kbwaitd BEGIN SLEEP 64 PC@ 1 AND END ;
This defines a function called "kbwaitd", which:
1. SLEEPs the current task (gives the other tasks in the system a chance to run).
2. Reads port 0x64 and checks the low bit.
3. If the low bit of port 0x64 was 0, loops back to step 1.
This function basically waits until there's a byte available to read from the keyboard.
: kback 61 PC@ DUP 80 OR 61 PC! 61 PC! ;
This defines a function to acknowledge the byte recieved from the keyboard. I have read conflicting reports as to it's neccessity, but haven't taken the time to experiment with it myself. It:
1. Reads port 0x61.
2. Writes the value back to port 0x61 with the high bit set.
3. Writes the value back to port 0x61 as it originally found it.
: kbread 60 PC@ ;
This defines a function to read a byte from the keyboard. It:
1. Reads port 0x60 and returns the value.
: kbnextevent kbwaitd kbread kback ;
This defines a function which waits for a byte from the keyboard, reads it, and acknowledges it, returning the byte read.
This is actually a simplified version of kbnextevent. The full version also checks for PS/2 mouse events and calls a special hook for the mouse driver.
That's basically how it all works. You sit in a loop checking the appropriate status port for each device (0x64 in the case of the keyboard), and handle things as they come up. The driver for the network card operates similarly, it has a task which basically loops over the network card status register waiting for something to happen.
Code is in a somewhat forth-like language, so it may not be what you're used to.
This is excerpted from the keyboard driver in my OS, the most relevant-seeming 4 lines, with explanations. All numbers below are in hexadecimal.
: kbwaitd BEGIN SLEEP 64 PC@ 1 AND END ;
This defines a function called "kbwaitd", which:
1. SLEEPs the current task (gives the other tasks in the system a chance to run).
2. Reads port 0x64 and checks the low bit.
3. If the low bit of port 0x64 was 0, loops back to step 1.
This function basically waits until there's a byte available to read from the keyboard.
: kback 61 PC@ DUP 80 OR 61 PC! 61 PC! ;
This defines a function to acknowledge the byte recieved from the keyboard. I have read conflicting reports as to it's neccessity, but haven't taken the time to experiment with it myself. It:
1. Reads port 0x61.
2. Writes the value back to port 0x61 with the high bit set.
3. Writes the value back to port 0x61 as it originally found it.
: kbread 60 PC@ ;
This defines a function to read a byte from the keyboard. It:
1. Reads port 0x60 and returns the value.
: kbnextevent kbwaitd kbread kback ;
This defines a function which waits for a byte from the keyboard, reads it, and acknowledges it, returning the byte read.
This is actually a simplified version of kbnextevent. The full version also checks for PS/2 mouse events and calls a special hook for the mouse driver.
That's basically how it all works. You sit in a loop checking the appropriate status port for each device (0x64 in the case of the keyboard), and handle things as they come up. The driver for the network card operates similarly, it has a task which basically loops over the network card status register waiting for something to happen.
RE:keyboard/mouse input in pmode
ok, that looks like it would work, but (in my very limited experience, mind you) that seems like it would waste more a lot cpu time than just sitting back and waiting for an interrupt to occur and then handling it appropriately. is that true? if not, why not?
RE:keyboard/mouse input in pmode
It only really wastes time that would otherwise be spent with the CPU halted. When every task is waiting for some I/O or other (be it the keyboard, the disk drive, or whatever), you normally HLT the CPU. This way, you sit in the task loop checking all the I/O devices in turn. The downside to this is that your CPU never gets HLTed, so it runs hotter than it might otherwise. The upside is that you don't need to set up an IDT or any interrupt handlers.
There's a small overhead involved in checking each device involved to see if it needs servicing, but that's fairly minimal.
Another upside (and downside) to this approach is that you don't need things like keyboard queues. You can set it up so that the keyboard is -only- polled when there's a task looking for keyboard input. No queues means that no queues can overflow, you don't need to keep them consistent, etc., etc.
You do have to remember to pause any CPU-intensive task periodically in order to let the device drivers have their fun, but you'd have the same issue in any co-operatively multitasked system.
Another interesting thing about this method is that it has an upgrade path to an interrupt-based system. You define your IDT and an ISR for the RTC interrupt (I forget exactly, but I know it's on PIC #2, probably IRQ
. Set your RTC to 1 MS operation, and put a task in the queue that just SLEEPs (to let the other tasks run) and then HLTs (to wait for the next interrupt). At this point, your CPU starts running a lot cooler. Plus, you can code the ISR in about 7 or so ASM instructions, which means you don't need to reflect it up to whatever high-level language you're using.
After you put that 1 MS timer interrupt in, you can update your task scheduler to have the concept of a "blocked" task, that doesn't get a timeslice until it's woken up again. Then you can define interrupt handlers to unblock certain tasks, and have the task block itself again once it's finished dealing with whatever caused the interrupt. Because interrupts are edge, rather than level, triggered, you can deal with most devices with interrupts -enabled- most of the time. Now you can write yourself a pre-emptive task scheduler if you want.
So, to continue my case for polling-mode drivers:
1. They're easier to write when you're first starting, because you don't need an IDT.
2. Because of (1), you can get something working to show off to your friends a lot quicker. ^_-
3. There's a reasonably well defined upgrade path to a more "traditional" system.
4. If you're using a programming language with a built-in or simple compiler (like Forth or maybe Lisp), you can write the code to define your IDT and ISRs -from within the running system-.
5. There's less management overhead involved keeping track of keyboard events and such.
6. About the only thing you -can't- do with them is sub-second delay timing (you need a timer interrupt for that).
Using polling-mode drivers may not be for everyone, but it's not something that should be dismissed out of paw, since it means you can get -some- things working sooner and with fewer headaches than with an interrupt-driven approach.
I think I'm going to turn these posts into a document for my website. It's something that needs saying in a more permanent place... Any objections?
There's a small overhead involved in checking each device involved to see if it needs servicing, but that's fairly minimal.
Another upside (and downside) to this approach is that you don't need things like keyboard queues. You can set it up so that the keyboard is -only- polled when there's a task looking for keyboard input. No queues means that no queues can overflow, you don't need to keep them consistent, etc., etc.
You do have to remember to pause any CPU-intensive task periodically in order to let the device drivers have their fun, but you'd have the same issue in any co-operatively multitasked system.
Another interesting thing about this method is that it has an upgrade path to an interrupt-based system. You define your IDT and an ISR for the RTC interrupt (I forget exactly, but I know it's on PIC #2, probably IRQ

After you put that 1 MS timer interrupt in, you can update your task scheduler to have the concept of a "blocked" task, that doesn't get a timeslice until it's woken up again. Then you can define interrupt handlers to unblock certain tasks, and have the task block itself again once it's finished dealing with whatever caused the interrupt. Because interrupts are edge, rather than level, triggered, you can deal with most devices with interrupts -enabled- most of the time. Now you can write yourself a pre-emptive task scheduler if you want.
So, to continue my case for polling-mode drivers:
1. They're easier to write when you're first starting, because you don't need an IDT.
2. Because of (1), you can get something working to show off to your friends a lot quicker. ^_-
3. There's a reasonably well defined upgrade path to a more "traditional" system.
4. If you're using a programming language with a built-in or simple compiler (like Forth or maybe Lisp), you can write the code to define your IDT and ISRs -from within the running system-.
5. There's less management overhead involved keeping track of keyboard events and such.
6. About the only thing you -can't- do with them is sub-second delay timing (you need a timer interrupt for that).
Using polling-mode drivers may not be for everyone, but it's not something that should be dismissed out of paw, since it means you can get -some- things working sooner and with fewer headaches than with an interrupt-driven approach.
I think I'm going to turn these posts into a document for my website. It's something that needs saying in a more permanent place... Any objections?
RE:keyboard/mouse input in pmode
Am I the only person missing the point of this thread ? What is the big deal with setting up the IDT and a keyboard ISR, with the possible exception of the system timer, it is the easiest ISR you can possibley write, why spend all this effort avoiding an interrupt driven keyboard and try to "sell" its virtues, when doing it the proper way is such a simple task - maybe I mising some vital portion of the argument - could someone enlighten me ?
RE:keyboard/mouse input in pmode
There are several points:
First, this illustrates the concept of a polling-mode driver. This is flat-out necessary in some cases, and the keyboard is one of the simpler cases to use for an explanation.
Second, the assertion made earlier, that you "need" to set up the IDT and a keyboard ISR is -wrong-, and this provides a counterexample.
Third, there are some cases where simply creating an ISR in a high-level language is not "such a simple task", for reasons to do with how the language is designed.
Fourth, for someone just getting started, figuring out how to create an IDT and ISR may -not- be "such a simple task".
Fifth, because this might be a far more natural way to think about the problem for some people.
Sixth, because there -are- virtues to this approach. I don't expect everyone to use it, but I would like them to at least consider it.
Seventh, because no technique is completely useless. Even if you don't use a technique, knowing it can be helpful.
And eighth, because there -is- no "proper way". There is only the way best suited to the present circumstance.
I'd add a quote here, probably by Robert Frost, but my memory fails me again. :-/
First, this illustrates the concept of a polling-mode driver. This is flat-out necessary in some cases, and the keyboard is one of the simpler cases to use for an explanation.
Second, the assertion made earlier, that you "need" to set up the IDT and a keyboard ISR is -wrong-, and this provides a counterexample.
Third, there are some cases where simply creating an ISR in a high-level language is not "such a simple task", for reasons to do with how the language is designed.
Fourth, for someone just getting started, figuring out how to create an IDT and ISR may -not- be "such a simple task".
Fifth, because this might be a far more natural way to think about the problem for some people.
Sixth, because there -are- virtues to this approach. I don't expect everyone to use it, but I would like them to at least consider it.
Seventh, because no technique is completely useless. Even if you don't use a technique, knowing it can be helpful.
And eighth, because there -is- no "proper way". There is only the way best suited to the present circumstance.
I'd add a quote here, probably by Robert Frost, but my memory fails me again. :-/
RE:keyboard/mouse input in pmode
Point taken, if this is an exercise in posibilities then there is value in what you say, I would postulate however that 90% of the time, setting up an IDT is the easier and most efficient method. I cannot comment on all high level languages, but MOST (I am prepared to be flamed on this, but I stand by it) OSs are written in assembler or C or a combination thereof, and setting up the relevant structures is straight forward enough, and even for beginners there are examples a plenty. I accept your points however and apologise for being so direct
RE:keyboard/mouse input in pmode
If you use this way to handle devices then you are going to LOOSE a lot of data when working with multiple devices eg network cards
Also the short comings of POLLING lead to the creation of Interrupts as a safe means of handling transmittion of data between devices and the CPU. Also it is a waste of valuable CPU cycles testing and testing and testing... until the device is ready when you can just attend to the device only when is signals that it is ready.
Every cpu cycle is precious especially in Multitasking environments.
This is just an example to show what i mean:
user's presses a key on the keyboard but the system is buzy running a task
with an interrupt system, the task will be suspended and the ISR will process the key press and the OS will returnn to the task that was running before the interrupt
but with a polling system, the key will be lost cause the system was busy running a task. the key can only be handled then the polling routine is called, so it will most likely be lost especially if the device, in this case the keyboard, on board buffer is full or non existant
READ UP ON HARDWARE AND SEE WHAT I MEAN, even on low end systems polling is seldomly used
Also the short comings of POLLING lead to the creation of Interrupts as a safe means of handling transmittion of data between devices and the CPU. Also it is a waste of valuable CPU cycles testing and testing and testing... until the device is ready when you can just attend to the device only when is signals that it is ready.
Every cpu cycle is precious especially in Multitasking environments.
This is just an example to show what i mean:
user's presses a key on the keyboard but the system is buzy running a task
with an interrupt system, the task will be suspended and the ISR will process the key press and the OS will returnn to the task that was running before the interrupt
but with a polling system, the key will be lost cause the system was busy running a task. the key can only be handled then the polling routine is called, so it will most likely be lost especially if the device, in this case the keyboard, on board buffer is full or non existant
READ UP ON HARDWARE AND SEE WHAT I MEAN, even on low end systems polling is seldomly used
RE:keyboard/mouse input in pmode
<Ahem>
With a polling interval of 1/1000 of a second, I'm not exactly worried about losing keystrokes or ethernet packets. It's not like the ethernet card doesn't have some memory on it to store packets for the couple thousanths of a second it takes to notice that there's data in the recieve buffer.
If every CPU cycle were precious, I'd be writing in ASM, not a higher-level language. CPU cycles aren't -that- precious, not even on a 68030. Even if you -are- multitasking.
User presses a key on the keyboard, but the system is busy running a task... which stops periodically to let the system poll the I/O devices, run other tasks, etc. Your example is a strawman argument because on a co-operatively multitasking system (which a polling-only system has to be if it multitasks at all), tasks are written to pause to check events quite often.
Low end systems where polling is seldom used? Like the NES? (poll all input devices every time the 60Hz VBL interrupt comes in.) Like the C64? (same thing.) Like the MSX? (same thing.) Like the SNES? (same thing.) Like the Genesis? (same thing.) Like the TI 99/4a? (same thing.) Like the TurboGrafx-CD? (same thing, running the CD drive in polling mode as well.) Like the Dr PC Jr? (same thing, running a PC floppy drive in polling mode and a PC keyboard on a "bit-banged" port.) Like the 68k-based Macintosh systems? (SCSI-Ethernet adaptors are polled, floppy disk controllers don't support interrupts and are polled for disk insert events, etc.) Like the Apple ][? (no interrupts -at all-.) That's four video game systems and six computer systems, most of which use 8-bit CPUs. Need I continue?
Gee, and I was only advocating almost the -exact same thing-, but with a faster polling interval.
So, with all due respect, I think you're full of it.
With a polling interval of 1/1000 of a second, I'm not exactly worried about losing keystrokes or ethernet packets. It's not like the ethernet card doesn't have some memory on it to store packets for the couple thousanths of a second it takes to notice that there's data in the recieve buffer.
If every CPU cycle were precious, I'd be writing in ASM, not a higher-level language. CPU cycles aren't -that- precious, not even on a 68030. Even if you -are- multitasking.
User presses a key on the keyboard, but the system is busy running a task... which stops periodically to let the system poll the I/O devices, run other tasks, etc. Your example is a strawman argument because on a co-operatively multitasking system (which a polling-only system has to be if it multitasks at all), tasks are written to pause to check events quite often.
Low end systems where polling is seldom used? Like the NES? (poll all input devices every time the 60Hz VBL interrupt comes in.) Like the C64? (same thing.) Like the MSX? (same thing.) Like the SNES? (same thing.) Like the Genesis? (same thing.) Like the TI 99/4a? (same thing.) Like the TurboGrafx-CD? (same thing, running the CD drive in polling mode as well.) Like the Dr PC Jr? (same thing, running a PC floppy drive in polling mode and a PC keyboard on a "bit-banged" port.) Like the 68k-based Macintosh systems? (SCSI-Ethernet adaptors are polled, floppy disk controllers don't support interrupts and are polled for disk insert events, etc.) Like the Apple ][? (no interrupts -at all-.) That's four video game systems and six computer systems, most of which use 8-bit CPUs. Need I continue?
Gee, and I was only advocating almost the -exact same thing-, but with a faster polling interval.
So, with all due respect, I think you're full of it.
RE:keyboard/mouse input in pmode
Hey Don't Insult ME!!!! Why so personal, are we here to share knowledge!!?
GROW UP!!!
GROW UP!!!
RE:keyboard/mouse input in pmode
Also How many devices ARE YOU GOING TO POLL continually 1/1000th of a second before you get a DEAD system!!!?
RE:keyboard/mouse input in pmode
You only need to poll the network card and COM ports at full speed when no tasks are blocked on keyboard input, and that assumes that you're using them.
All other devices can be polled more slowly, and the keyboard doesn't need to be polled unless some task is waiting for input.
You're far more likely to obtain a dead system by writing an infinite loop by accident than by overloading the task queue with device drivers.
All other devices can be polled more slowly, and the keyboard doesn't need to be polled unless some task is waiting for input.
You're far more likely to obtain a dead system by writing an infinite loop by accident than by overloading the task queue with device drivers.