Overview

MS DOS was designed for 8086 processor. 8086 has 16bit data bus and 20bit address bus. It can have physical memory range from zero to 1MB(0x0 -0xFFFFF). It has general purpose CPU registers like AX, BX, CX, DX, SI, DI, SP, BP, IP, and segment registers CS,DS,ES,SS,GS,FS. All registers are 16 bit wide. CPU has 16bit data lines and 20bit address lines. It also has control lines like clock, MEMRead, MemWrite, I/O read/write and interrupt and DMA control lines. A preriferal like PS/2 keyboard controller, or mouse controller, VGA card etc can be connected to these bus lines via a bridge. This bridge steps down CPU clock to lower clock speed to match peripheral clock speed. CPU can access peripheral memory mapped registers via MOV instructions. CPU also can access I/O registers via IN/OUT instructions. Again peripheral can inform CPU about some events via interrupt lines.

MMIO Access

PC architecture has 640 Kb of conventional memory. This range is from 0x0-0x9FFFF) . Above this there is a memory hole till 0xE0000. Peripherals like VGA display card maps its internal video memory(VRAM) to the address fromm 0xA0000 to 0xBFFFF). Above this address there is a hole for BIOS ROM and ROM for addon card. BIOS takes address 0xE0000-0xFFFFF) Below this 0xC0000-DFFFF is for BIOS rom for add-on cards. CPU can also access peripheral registers like it access system memory.CPU has MOV instruction. MEMRD/MEMWR control line get activated depending on the direction of the data flow. This mechanism is simple and this can be done with simple pointers in C. Thus C runtime does not have any functions. We will access video memory of VGA card when it is in text mode. VGA card takes character array from location 0xB8000 and creates a 80x25 text console. Each character takes two bytes. First byte is the ASCII value of the. Second byte contains foreground and background color attribute. Here we will access starting of VRAM and copy ACSII character and color attribute one by one via memory pointer. We will see the output at the VGA monitor. This is the basic principle of giving output to VGA text screen which is used in printf.

I/O Access

MMIO is used when a large range of memory like VRAM is needed to be accessed. Peripherals often implement small range I/O control and status registers. These registers works in I/O address space. CPU can access I/O range via 16bit I/O address space. I/O read and write are control lines and 16bit lower bits of the same memory address lines are used for I/O access. CPU controls I/O trans via IN and OUT instruction. It generally puts 16bit I/O address in DX register and accumularor AX is used for data transfer. If instruction is IN then data flow would be from peripheral to AX. If instruction is OUT then value of AX would transfer to pheriferal. C library has a series of wrapper function like inport inb, inportb, inw, inl for reading I/O register and outport, outb, outportb outw, outl etc for writing to I/o re

Interrupt Access

We discussed till now is either reading or writing pheferal registers. Now there are situations when peripheral wants to inform CPU about some events like read completion, write completion or errors. These are asynchronous events. Each hardware has a interrupt line connected to interrupt controller. Finally there is INTR line from interrult controller is attached to CPU. Another line Inta is backfeed to interrupt controller which acts as a acknowledge line from CPU. Peripheral generates interrupts and interrupt controller feeds this signal to CPU. CPU changes context to interrupt and interrupt controller gives vector number to CPU and CPU jumps to the code for this vector. OS default Interrupt handler saves current user context to the stack and switches to kernel stack. Then it executes code inside interrupt vector. C library provides getvect and setvect routines. to get vector address of a interrupt number ansystem provides Getvect

Source Code

#include <stdio.h>
#include <dos.h>
unsigned char kbcode[128] =
{
    0,  27, '1', '2', '3', '4', '5', '6', '7', '8',  /* 9 */
  '9', '0', '-', '=', '\b',  /* Backspace */
  '  ',      /* Tab */
  'q', 'w', 'e', 'r',  /* 19 */
  't', 'y', 'u', 'i', 'o', 'p', '[', ']', '
10  ',  /* Enter key */
11      0,      /* 29 - Control */
12    'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',  /* 39 */
13   '\'', '`',   0,    /* Left shift */
14   '\', 'z', 'x', 'c', 'v', 'b', 'n',      /* 49 */
15    'm', ',', '.', '/',   0,        /* Right shift */
16    '*',
17      0,  /* Alt */
18    ' ',  /* Space bar */
19      0,  /* Caps lock */
20      0,  /* 59 - F1 key ... > */
21      0,   0,   0,   0,   0,   0,   0,   0,
22      0,  /* < ... F10 */
23      0,  /* 69 - Num lock*/
24      0,  /* Scroll Lock */
25      0,  /* Home key */
26      0,  /* Up Arrow */
27      0,  /* Page Up */
28    '-',
29      0,  /* Left Arrow */
30      0,
31      0,  /* Right Arrow */
32    '+',
33      0,  /* 79 - End key*/
34      0,  /* Down Arrow */
35      0,  /* Page Down */
36      0,  /* Insert Key */
37      0,  /* Delete Key */
38      0,   0,   0,
39      0,  /* F11 Key */
40      0,  /* F12 Key */
41      0,  /* All other keys are undefined */
42  };    
43 
44 
45  void interrupt far ( *oldhandler)(__CPPARGS);
46 
47  int count=0;
48 
49  void interrupt far handler(__CPPARGS)
50  {
51    unsigned char key;
52    char far* vga_text;
53    key = inportb(0x60);
54 
55    if(key < 0x80) {
56    vga_text = MK_FP(0xB800,0);
57    vga_text += count;
58    *vga_text++ = keycode[key];
59    *vga_text = 7;
60    count += 2;
61    }
62    outportb(0x20,0x20);
63  }
64  #define INTR 9
65  int main(void)
66  {
67  /* save the old interrupt vector */
68     oldhandler = getvect(INTR);
69 
70  /* install the new interrupt handler */
71    setvect(INTR, handler);
72 
73  /* loop until the counter exceeds 20 */
74     while (count < 80*25*2)
75        {
76        delay(10);
77        }
78 
79  /* reset the old interrupt handler */
80    setvect(INTR, oldhandler);
81 
82     return 0;
83  }
84 

Additional Functions

/* int86 also inclues segment registers */
int int86x( int intno, union REGS * inregs, union REGS *__outregs, struct SREGS *segregs );
/* Access DOS system interrupts vector 0x21*/
int intdos( union REGS *inregs, union REGS *outregs );
/* Access DOS system interrupts vector 0x21 with segment registers */
int intdosx( union REGS *inregs, union REGS *outregs, struct SREGS *segregs );

You have viewed 1 page out of 248. Your C learning is 0.00% complete. Login to check your learning progress.

 Vote 0

Similar topics related to this section

fputs,fgets,fgetc,fputc, printf, scanf, ioctl, mmap, DOS low level IO access, DOS BIOS int86, sleep/delay, sound, nosound,

# C Programming Language (Prentice Hall Software)
# Let Us C Paperback - 2006 by Yashavant Kanetkar
# Understanding and Using C Pointers Core techniques for memory management
# Data Structures Using C and C++ Paperback - 1998
# Data Structures In C Paperback - August 11, 2008 by Noel Kalicharan