I'm sure some will resent this post. But I've done plenty of Linux to 
Atmel and Arduino microcontroller programming, and I honestly find this 
old IBM PC DOS programming is educational. Why re-invent the wheel??

I have an old book with CD, "PC Intern System Programming," by Michael 
Tischer, 1995. And I have an old Intel P2 motherboard running FreeDOS, 
with TurboPascal6 (and other languages).

The particular program (I had to do a little clean-up) I'm studying is 
SERIRQ.EXE. It relies an several pascal unit files; including 
IRQUtil.pas, SERUtil.pas, and WIN.pas.

What is interesting to me is how these are not some API, but actually 
programming the registers of chips at their port address. The 
IRQUtil.pas programs the registers of the interrupt controller. 
SERUtil.pas programs the UART chip. WIN.pas programs video memory. 
Ultimately, a two side Interrupt controlled chat program over serial 
ports is (mostly) provided by SERIRQ.EXE.

The Linux serial port driver provides most of this in the Posix termios 
and IOCtl commands. But the microcontroller side computer on a chip is 
often remarkably similar to the design of the IBM PC.