Page 1 of 1
Is it possible to replace I/O ports with memory mapped I/O?
Posted: Wed Jul 20, 2016 5:48 am
by jpaquim
Hey everyone,
I'm very new to operating system development, currently working on basic support for VGA and keyboard handling.
It is my understanding that I/O ports are considered old technology on x86, and that modern I/O is done through memory mapped I/O. Checking linux's source for x86, outb and inb are still defined using the corresponding assembly instructions for I/O port communication, instead of asm-generic which defines them as basically accessing the memory location (PCI_IOBASE+port).
For my particular application, I'm using outb and inb to communicate with the VGA CRTC registers to move the cursor, and to communicate with the keyboard controller. Is it possible to do these tasks by accessing memory directly, instead of with the in/out instructions?
Cheers
Re: Is it possible to replace I/O ports with memory mapped I
Posted: Wed Jul 20, 2016 6:01 am
by Octocontrabass
No.
Re: Is it possible to replace I/O ports with memory mapped I
Posted: Wed Jul 20, 2016 7:40 pm
by thepowersgang
To expand on that previous comment: It's not possible to do it for all IO ports.
But, most modern devices use MMIO instead of the IO space, notably some video devices will basically map the VGA registers into MMIO space (under a PCI BAR).
But in short - Legacy VGA can't just be remapped without knowing the actual device that is providing it.
Re: Is it possible to replace I/O ports with memory mapped I
Posted: Wed Jul 20, 2016 7:41 pm
by Brendan
Hi,
jpaquim wrote:For my particular application, I'm using outb and inb to communicate with the VGA CRTC registers to move the cursor, and to communicate with the keyboard controller. Is it possible to do these tasks by accessing memory directly, instead of with the in/out instructions?
In general: No.
For video cards specifically; VGA is obsolete crud from the about 30 years ago and almost all actual video cards (even ancient SVGA video cards from the 1990s) have a native interface (that isn't "VGA compatible" and includes extra things needed for higher resolutions) that is either always memory mapped or can (optionally) be memory mapped. Unfortunately; to avoid using obsolete VGA crud (and to avoid IO ports) means you need native drivers for each video card, which isn't so easy.
Far more sensible is to stop using the VGA hardware cursor itself. It doesn't work in graphics modes at all; and even for (disgustingly out-dated) text modes it's simpler, more reliable (no risk of "not quite 100% VGA compatible" hardware breaking it), faster (no IO ports) and can be more flexible (different blink speeds, colours, etc) to emulate a cursor in software.
Cheers,
Brendan
Re: Is it possible to replace I/O ports with memory mapped I
Posted: Wed Jul 20, 2016 7:56 pm
by alexfru
In theory, one could intercept memory accesses and translate them into port reads and writes, but in practice this adds complexity and overhead and solves no problem other than just providing a handy memory-based "API".
Re: Is it possible to replace I/O ports with memory mapped I
Posted: Wed Jul 20, 2016 8:22 pm
by Brendan
Hi,
alexfru wrote:In theory, one could intercept memory accesses and translate them into port reads and writes, but in practice this adds complexity and overhead and solves no problem other than just providing a handy memory-based "API".
It might solve a portability problem (so the same device driver's source code works "as is" on systems that don't have IO ports).
I've looked into it for other reasons (intercepting accesses to memory mapped IO for the purpose of transparent "virtualised devices"); and it's extremely complex to do it for 80x86. It's easy to determine the address being accessed (page fault handler's CR2) but determining the length (if they're access a byte, word, dword or larger) isn't trivial and there's multiple "pathological corner-cases" (e.g. instructions like "movsd" which access 2 locations within the memory mapped IO area at the same time). To handle all cases properly you'd probably have to emulate the instruction that caused the initial page fault in software.
Cheers,
Brendan
Re: Is it possible to replace I/O ports with memory mapped I
Posted: Wed Jul 20, 2016 11:18 pm
by alexfru
Brendan wrote:
alexfru wrote:In theory, one could intercept memory accesses and translate them into port reads and writes, but in practice this adds complexity and overhead and solves no problem other than just providing a handy memory-based "API".
It might solve a portability problem (so the same device driver's source code works "as is" on systems that don't have IO ports).
I've looked into it for other reasons (intercepting accesses to memory mapped IO for the purpose of transparent "virtualised devices"); and it's extremely complex to do it for 80x86. It's easy to determine the address being accessed (page fault handler's CR2) but determining the length (if they're access a byte, word, dword or larger) isn't trivial and there's multiple "pathological corner-cases" (e.g. instructions like "movsd" which access 2 locations within the memory mapped IO area at the same time). To handle all cases properly you'd probably have to emulate the instruction that caused the initial page fault in software.
It sure was a pain in the butt to deal with all this instruction decoding nonsense in Hyper-V (for 16-bit, 32-bit and 64-bit modes). I had also implemented LFB emulation on banked-only VESA cards (pre-VBE2.0) similarly via page faults. It's a special kind of fun, which is not universally understood or appreciated. The CPU's got the info. And yet we still need to go through this crap in software. I don't know if Intel or AMD has done VM exits right since then (haven't looked at the VMX/SVM docs for some 5+ years).
Re: Is it possible to replace I/O ports with memory mapped I
Posted: Thu Jul 21, 2016 7:26 pm
by jpaquim
Thank you all for your feedback
Brendan wrote:
For video cards specifically; VGA is obsolete crud from the about 30 years ago and almost all actual video cards (even ancient SVGA video cards from the 1990s) have a native interface (that isn't "VGA compatible" and includes extra things needed for higher resolutions) that is either always memory mapped or can (optionally) be memory mapped. Unfortunately; to avoid using obsolete VGA crud (and to avoid IO ports) means you need native drivers for each video card, which isn't so easy.
Far more sensible is to stop using the VGA hardware cursor itself. It doesn't work in graphics modes at all; and even for (disgustingly out-dated) text modes it's simpler, more reliable (no risk of "not quite 100% VGA compatible" hardware breaking it), faster (no IO ports) and can be more flexible (different blink speeds, colours, etc) to emulate a cursor in software.
Emulating the cursor in software seems like a great idea, thank you. I intend my OS to be text-based, for the time being, and I really have no intention of writing native drivers for each video card, I'd like to keep things generic. Would you recommend skipping VGA text mode entirely and instead use VGA/VESA graphics mode?
In any case, keyboard handling must be done via port reads and writes, is that correct?
Re: Is it possible to replace I/O ports with memory mapped I
Posted: Fri Jul 22, 2016 1:25 am
by Brendan
Hi,
jpaquim wrote:Emulating the cursor in software seems like a great idea, thank you. I intend my OS to be text-based, for the time being, and I really have no intention of writing native drivers for each video card, I'd like to keep things generic. Would you recommend skipping VGA text mode entirely and instead use VGA/VESA graphics mode?
I'd recommend the OS uses a framebuffer from "wherever" (VBE, UEFI) without caring how the bootloader setup the framebuffer (until/unless it starts a native driver). This allows you to do text properly (Unicode, different font sizes, bold/italic/underline, proportional fonts, etc), but also makes it easier to support UEFI later.
jpaquim wrote:In any case, keyboard handling must be done via port reads and writes, is that correct?
Keyboard handling never uses IO ports or memory mapped IO - a keyboard driver just talks to a PS/2 controller driver or a USB controller driver. A PS/2 controller driver uses IO ports, some (older) USB controllers use IO ports, and most (newer) USB controllers use memory mapped IO.
Cheers,
Brendan
Re: Is it possible to replace I/O ports with memory mapped I
Posted: Sat Jul 23, 2016 3:05 pm
by jpaquim
Brendan wrote:
I'd recommend the OS uses a framebuffer from "wherever" (VBE, UEFI) without caring how the bootloader setup the framebuffer (until/unless it starts a native driver). This allows you to do text properly (Unicode, different font sizes, bold/italic/underline, proportional fonts, etc), but also makes it easier to support UEFI later.
Keyboard handling never uses IO ports or memory mapped IO - a keyboard driver just talks to a PS/2 controller driver or a USB controller driver. A PS/2 controller driver uses IO ports, some (older) USB controllers use IO ports, and most (newer) USB controllers use memory mapped IO.
Ok, that makes sense. That got me thinking, is it worth the effort to support legacy hardware and interfaces, or should I strive from the start to support USB rather than PS/2, and UEFI rather than legacy BIOS?
Re: Is it possible to replace I/O ports with memory mapped I
Posted: Sat Jul 23, 2016 7:13 pm
by BrightLight
jpaquim wrote:That got me thinking, is it worth the effort to support legacy hardware and interfaces, or should I strive from the start to support USB rather than PS/2, and UEFI rather than legacy BIOS?
I'd say it is worth the effort. Most laptops' built-in keyboards and touchpads are PS/2. Other than that, the experience is never useless. USB is complex; I've never achieved anything with it personally. USB also needs more work: you'll need OHCI to run in VirtualBox, UHCI for QEMU and Bochs, EHCI probably for some real hardware, and xHCI for most newer hardware.