And that unsafe, complex C API communicates with an even sketchier system made of registers, IO ports and nasty hardware details. Providing a higher level API for a nastier backend has always been a core feature of operating systems and programming languages.
Almost nothing is still I/O ports because it's more portable to use MMIO and if you're going to offer MMIO why bother also doing I/O ports. But yes, as a vague outline you're correct.