Sunday, 11 March 2012

Rebooting Operating System

Eva Os Reboot

                                 How To ReBooT??

Keyboard - reboot via the keyboard controller. The original IBM PC had the CPU reset line tied to the keyboard controller. Writing the appropriate magic value pulses the line and the machine resets. This is all very straightforward, except for the fact that modern machines don't have keyboard controllers (they're actually part of the embedded controller) and even more modern machines don't even pretend to have a keyboard controller. Now, embedded controllers run software. But i am using this method in my Eva Operating System because its the easiest way i came across and right now i dont have any other choice, but in future  i'll try my best to do it with PCI or ACPI.

 // eva.c 
 //      @author<Vishal Mishra><>
//           @change fri-Mar-11,19:01 
void reboot(void)
        char temp;

       asm volatile("cli");
        /* flush the keyboard controller */
                temp = inb(0x64);
                if (temp & 1)
        }while(temp & 2);

        /* send the CPU reset line */
        outb(0x64, 0xFE);

        asm volatile("hlt");

Triple Fault -A triple fault is a special kind of exception generated by the CPU when an exception occurs while the CPU is trying to invoke the double fault exception handler, which itself handles exceptions occurring while trying to invoke a regular exception handler.
x86 processors beginning with the 80286 will cause a shutdown cycle to occur when a triple fault is encountered. This typically causes the motherboard hardware to initiate a CPU reset which in turn causes the whole computer to reboot. attempt to generate a triple fault. This is done by loading an empty interrupt descriptor table and then calling int(3). The interrupt fails (there's no IDT), the fault handler fails (there's no IDT) and the CPU enters a condition which should, in theory, then trigger a reset. Except there doesn't seem to be a requirement that this happen and it just doesn't work on a bunch of machines.

PCI - Traditional PCI config space access is achieved by writing a 32 bit value to io port 0xcf8 to identify the bus, device, function and config register. Port 0xcfc then contains the register in question. But if you write the appropriate pair of magic values to 0xcf9, the machine will reboot. Spectacular! And not standardised in any way (certainly not part of the PCI spec), so different chipsets may have different requirements. 

EFI -The Unified Extensible Firmware Interface (UEFI) is a specification that defines a software interface between an operating system and platform firmware.
The original EFI (Extensible Firmware Interface) specification was developed by Intel. In 2005, development of the EFI specification ceased in favor of UEFI, which had evolved from EFI 1.10.
EFI runtime services provide an entry point to reboot the machine. It usually even works! As long as EFI runtime services are working at all, which may be a stretch.

ACPI -the Advanced Configuration and Power Interface (ACPI) specification provides an open standard for device configuration and power management by the operating system.
 Recent versions of the ACPI  let you provide an address (typically memory or system IO space) and a value to write there. The idea is that writing the value to the address resets the system. It turns out that doing so often fails. It's also impossible to represent the PCI reboot method via ACPI, because the PCI reboot method requires a pair of values and ACPI only gives you one.

Wednesday, 7 March 2012

Debug Your Operating System(Eva Os)

tty2 screenshot

qemu -s -S -kernel /home/vishal/evaos/working/22/kernel -gdb tcp::50022 -vnc :0

(gdb) target remote
Remote debugging using
0x0000fff0 in ?? ()
(gdb) file /home/vishal/evaos/working/22/kernel
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from /home/vishal/evaos/working/22/kernel...(no debugging symbols found)...done.
(gdb) break eva
Note: breakpoint 1 also set at pc 0x100032.
Breakpoint 2 at 0x100032


So that's how you can debug your own operating system .I known it gets really frustrating if some error occur and you dont known its location or how to remove it .I hope this will help you out to get out of such situations.

//please feel free to comment //

Thursday, 1 March 2012

How to make a Operating System ..The SCreeN(TEXT_MODE+VGA)

Well hello guys ones again!!.Well last time we learned how to make a hello-bootloader, but i'll be using from now on grub as my bootloader so that we can focus more on our kernel.Its also very safe to use grub because we dont have to worry about machine architecture before loading our kernel. 
So let start make our very first module of kernel ...

 The SCREEN Module:

Memory Layout

So we are here interested in 0xB8000-0xBFFFF which constitutes our video memory.Well its just a basic video area which have few  colors only. For VGA(vesa) we have to use A0000 but right now i dont want to discuss these things.
The area of memory known as the framebuffer is accessible just like normal RAM, at address 0xB8000 it controls a screen of characters (not pixels) 80 wide by 25 high.

Printing Character
Okay, so how do we print a character at any x/y location on screen?
A special property about memory is how it is linear. If we reach the end of a line being displayed, the next byte is on the line right below it. Because of linear addressing, we have to be able to convert an x/y location to a linear address to render it to screen. And, a special forumula to do that is: x + y * screen width.

Cursor Position

The framebuffer is just an array of 16-bit words about which we talked above, each 16-bit value representing the display of one character. The offset from the start of the framebuffer of the word that specifies a character at position xy is:

(y * 80 + x) * 2

If you are thinking why its multiplied by two then here is its answer
 because each element is 2 bytes (16 bits) long. If you're indexing an array of 16-bit values, for example, your index would just be x+(y*80)

4 bits for a colour code gives us 15 possible colours we can display:

  • 0 - Black
  • 1 - Blue
  • 2 - Green
  • 3 - Cyan
  • 4 - Red
  • 5 - Magenta
  • 6 - Brown
  • 7 - Light Gray
  • 8 - Dark Gray
  • 9 - Light Blue
  • 10 - Light Green
  • 11 - Light Cyan
  • 12 - Light Red
  • 13 - Light Magenta
  • 14 - Light Brown
  • 15 - White

The VGA controller also has some ports on the main I/O bus, which you can use to send it specific instructions. (Among others) it has a control register at 0x3D4 and a data register at 0x3D5. We will use these to instruct the controller to update it's cursor position.

Now Lets Move to the Implementation Part....

So first define some common things which we will need all the time like 
1:int,char, short long;
2:functions for reading from i/o bus;
3:string manipulation function like string copy,concatenate,compare etc..
4:memory comparison and copy function etc.

// common.h -- Defines typedefs and some global functions.
//           @author<Vishal Mishra><>
//           @change fri-Mar-2,12:01

#ifndef COMMON_H
#define COMMON_H

// Some nice typedefs, to standardise sizes across platforms.
// These typedefs are written for 32-bit X86.
typedef unsigned int   u32int;
typedef          int   s32int;
typedef unsigned short u16int;
typedef          short s16int;
typedef unsigned char  u8int;
typedef          char  s8int;

void outb(u16int port, u8int value);
void outw(u16int port, u16int value);
u8int inb(u16int port);
u16int inw(u16int port);
u32int zkmalloc(u32int sz);
u32int kmalloc_int(u32int sz, int align, u32int *phys);

#endif // COMMON_H

//common.c -- Defines some global functions.
//            @author<Vishal Mishra><>
//            @change fri-Mar-2,12:01

#include "common.h"

// Write a byte out to the specified port.
void outb(u16int port, u8int value)
    asm volatile ("outb %1, %0" : : "dN" (port), "a" (value));

//write a word to specific port
void outw(u16int port, u16int value)
    asm volatile ("outw %1, %0" : : "dN" (port), "a" (value));


//Read a byte from a Port
u8int inb(u16int port)
    u8int ret;
    asm volatile("inb %1, %0" : "=a" (ret) : "dN" (port));
    return ret;

//Read a word from a Port
u16int inw(u16int port)
    u16int ret;
    asm volatile ("inw %1, %0" : "=a" (ret) : "dN" (port));
    return ret;

// text_mode.h -- Defines the interface for text_mode.h
//           @author<Vishal Mishra><>
//           @change fri-Mar-2,12:01

#ifndef TEXT_MODE_H
#define TEXT_MODE_H

#include "common.h"

//Write a single charactere out to the screen of specific background and forecolour value
void eva_put(char c,u8int backColour,u8int foreColour);

// Write a single character out to the screen.
void eva_puts(char c);

// Clear the screen to 'bg' color code.
void eva_clear(int bg);

// Output a null-terminated ASCII string .
void eva_write(char *c);

#endif // TEXT_MODE_H

// text_mode.c -- Defines functions for writing to the text mode.
//           @author<Vishal Mishra><>
//           @change fri-Mar-2,12:01

#include "text_mode.h"

// The VGA framebuffer starts at 0xB8000.
u16int *video_memory = (u16int *)0xB8000;
// Stores the cursor position.
u8int cursor_x ;
u8int cursor_y ;

// Updates the hardware cursor.
static void move_cursor()
    // The screen is 80 characters wide...
    u16int cursorLocation = cursor_y * 80 + cursor_x;
    outb(0x3D4, 14);                  // Tell the VGA board we are setting the high cursor byte.
    outb(0x3D5, cursorLocation >> 8); // Send the high cursor byte.
    outb(0x3D4, 15);                  // Tell the VGA board we are setting the low cursor byte.
    outb(0x3D5, cursorLocation);      // Send the low cursor byte.

// Scrolls the text on the screen up by one line.
static void scroll()

    // Get a space character with the default colour attributes.
    u8int attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
    u16int blank = 0x20 /* space */ | (attributeByte << 8);

    // Row 25 is the end, this means we need to scroll up
    if(cursor_y >= 25)
        // Move the current text chunk that makes up the screen
        // back in the buffer by a line
        int i;
        for (i = 0*80; i < 24*80; i++)
            video_memory[i] = video_memory[i+80];

        // The last line should now be blank. Do this by writing
        // 80 spaces to it.
        for (i = 24*80; i < 25*80; i++)
            video_memory[i] = blank;
        // The cursor should now be on the last line.
        cursor_y = 24;

// Writes a single character out to the screen.
void eva_put(char c,u8int backColour,u8int foreColour)

    // The background colour is black (0), the foreground is white (15).

    // The attribute byte is made up of two nibbles - the lower being the 
    // foreground colour, and the upper the background colour.
    u8int  attributeByte = (backColour << 4) | (foreColour & 0x0F);
    // The attribute byte is the top 8 bits of the word we have to send to the
    // VGA board.
    u16int attribute = attributeByte << 8;
    u16int *location;

    // Handle a backspace, by moving the cursor back one space
    if (c == 0x08 && cursor_x)

    // Handle a tab by increasing the cursor's X, but only to a point
    // where it is divisible by 8.
    else if (c == 0x09)
        cursor_x = (cursor_x+8) & ~(8-1);

    // Handle carriage return
    else if (c == '\r')
        cursor_x = 0;

    // Handle newline by moving cursor back to left and increasing the row
    else if (c == '\n')
        cursor_x = 0;
    // Handle any other printable character.
    else if(c >= ' ')
        location = video_memory + (cursor_y*80 + cursor_x);
        *location = c | attribute;

    // Check if we need to insert a new line because we have reached the end
    // of the screen.
    if (cursor_x >= 80)
        cursor_x = 0;
        cursor_y ++;

    // Scroll the screen if needed.
    // Move the hardware cursor.


void eva_puts(char c)



// Clears the screen, by copying lots of spaces to the framebuffer.
void eva_clear(int bg)

    // Make an attribute byte for the default colours
    u8int attributeByte = (bg /*black*/ << 4) | (15 /*white*/ & 0x0F);
    u16int blank = 0x20 /* space */ | (attributeByte << 8);

    int i;
    for (i = 0; i < 80*25; i++)
        video_memory[i] = blank;

    // Move the hardware cursor back to the start.
    cursor_x = 0;
    cursor_y = 0;

// Outputs a null-terminated ASCII string to the monitor.
void eva_write(char *c)
    int i = 0;
    while (c[i])

void eva_write_hex(u32int n)

s32int tmp;


    char noZeroes = 1;

    int i;
    for (i = 28; i > 0; i -= 4)
        tmp = (n >> i) & 0xF;
        if (tmp == 0 && noZeroes != 0)
        if (tmp >= 0xA)
            noZeroes = 0;
            eva_puts (tmp-0xA+'a' );
            noZeroes = 0;
            eva_puts( tmp+'0' );
    tmp = n & 0xF;
    if (tmp >= 0xA)
        eva_puts (tmp-0xA+'a');
        eva_puts (tmp+'0');


void eva_write_dec(u32int n)
    if (n == 0)

    s32int acc = n;
    char c[32];
    int i = 0;
    while (acc > 0)
        c[i] = '0' + acc%10;
        acc /= 10;
    c[i] = 0;

    char c2[32];
    c2[i--] = 0;
    int j = 0;
    while(i >= 0)
        c2[i--] = c[j++];

Moving the cursor(In  move_cursor() Function)

To move the hardware cursor, we must firstly work out the linear offset of the x,y cursor coordinate. We do this by using the equation above. Next, we have to send this offset to the VGA controller. For some reason, it accepts the 16-bit location as two bytes. We send the controller's command port (0x3D4) the command 14 to tell it we are sending the high byte, then send that byte to port 0x3D5. We then repeat with the low byte, but send the command 15 instead.

 VGA mode(pixel):

#ifndef VGA_H
#define VGA_H

void VgaTest(void);
void VgaUpdateMouse(int x, int y);
void VgaDrawString(int x, int y, int reps, char font[8], char color);
void VgaDrawFont(int x, int y, char font[8], int c1);
void VgaDrawWindow(int x, int y, int size);
void VgaDrawRectangle(int x, int y, int w, int h, u8int color);
void vga_draw_vert(int x, int y, int length, u8int color);
void vga_draw_hort(int x, int y, int length, u8int color);
void VgaFillRectangle(int x, int y, int w, int h, u8int color);
void VgaGetFont(char *buffer);
void mode3(void);
void mode13(void);
void VgaClearScreen(void);
void VgaClear(u8int color);
u8int VgaReadPixel(int x, int y);
void VgaDrawPixel(unsigned x, unsigned y, unsigned c);
void VgaSetColor(u8int color, u8int red, u8int green, u8int blue);

// vga.c
//           @author<Vishal Mishra><>
//           @change fri-Mar-2,12:01
#include "common.h"

#include "vga.h"

int mx, my; // mouse data
char bg;

void VgaSetColor(u8int color, u8int red, u8int green, u8int blue)
outb(0x3C8, color);
outb(0x3C9, red);
outb(0x3C9, green);
outb(0x3C9, blue);

void VgaDrawPixel(unsigned x, unsigned y, unsigned c)
u8int *vga = (u8int*)0xA0000;
int offset = y * 320 + x;
vga[offset] = c;

u8int VgaReadPixel(int x, int y)
u8int *vga = (u8int*) 0xA0000;
int offset = y * 320 + x;
return vga[offset];

void VgaClear(u8int color)
int w, h;
for (w = 0; w < 320; w++)
for (h = 0; h < 200; h++)
VgaDrawPixel(w, h, color);

void VgaClearScreen(void)

void mode13(void)
const u8int w[7] = { 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x28 }; // width = 320
const u8int h[8] = { 0xBF, 0x1F, 0x41, 0x9C, 0x8E, 0x8F, 0x96, 0xB9 }; // height = 200
const u8int w_regs[7] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x13 };
const u8int h_regs[8] = { 0x6, 0x7, 0x9, 0x10, 0x11, 0x12, 0x15, 0x16 };
int i;

outb(0x3C2, 0x63); // mode switch
outw(0x3D4, 0x0E11); // enable registers

for (i = 0; i < 7; i++)
outw(0x3D4, (short)((w[i]<<8)+w_regs[i]));
for (i = 0; i < 8; i++)
outw(0x3D4, (short)((h[i]<<8)+h_regs[i]));
outw(0x3D4, 0x0008);
outw(0x3D4, 0x4014);
    outw(0x3D4, 0xA317);
    outw(0x3C4, 0x0E04);

outw(0x3C4, 0x0101);
    outw(0x3C4, 0x0F02); // enable writing to all planes

    outw(0x3CE, 0x4005); // 256color mode
outw(0x3CE, 0x0506); // graph mode & A000-AFFF

outb(0x3C0, 0x30); 
outb(0x3C0, 0x41);
outb(0x3C0, 0x33);
outb(0x3C0, 0x00);

// EGA Colors
for (i = 0; i < 16; i++)
outb(0x3C0, (u8int)i);
outb(0x3C0, (u8int)i);
outb(0x3C0, 0x20); // enable video

void VgaGetFont(char *buffer)
int i;
char *vga = (char *) 0xA0000;
outb(0x3CE, 0x0204);
for (i = 0; i < 0x2000; i++)
buffer[i] = vga[i];

void VgaFillRectangle(int x, int y, int w, int h, u8int color)
int a, b;
for (a = y; a < (y + h); a++)
for (b = x; b < (x + w); b++)
VgaDrawPixel(b, a, color);

//void VgaDrawRectangle(Rectangle_t *rect, int color)

void vga_draw_hort(int x, int y, int length, u8int color)
int a;
for (a = x; a < (x + length); a++)
VgaDrawPixel(a, y, color);

void vga_draw_vert(int x, int y, int length, u8int color)
int a;
for (a = y; a < (y + length); a++)
VgaDrawPixel(x, a, color);

void VgaDrawRectangle(int x, int y, int w, int h, u8int color)
vga_draw_hort(x, y, w, color); // Draw top border
vga_draw_hort(x, y+h, w, color); // Draw bottom border

vga_draw_vert(x, y, h, color); // Draw left border
vga_draw_vert(x+w, y, h, color); // Draw right border

void VgaDrawWindow(int x, int y, int size)
VgaFillRectangle(x, y, size, size, 2); // Green
VgaDrawRectangle(x, y, size, size, 0); // Black

void VgaDrawFont(int x, int y, char font[8], int c1)
int i, l;
int j = x;
int h = y;
int c;
for (l = 0; l < 8; l++)
for (i = 0; i < 8; i++)
if ((font[l] & (1<<i)))
c = c1; // New color
c = VgaReadPixel(j, h); // Don't overwrite background
VgaDrawPixel(j++, h, c);
j = x;

void VgaDrawString(int x, int y, int reps, char font[8], char color)
int i;
int a = x;
for (i = 0; i < reps; i++)
VgaDrawFont(a, y, font, color);
a += 8;

void VgaUpdateMouse(int x, int y)
VgaDrawPixel(mx, my, bg);
VgaDrawPixel(x, y, 0);
mx = x;
my = y;

void VgaTest(void)

char a[10]="hi wassup";

bg = 0;

VgaDrawWindow(96, 36, 128);

char font_a[8] = {0x18, 0x3C, 0x66, 0x7E,
0x66, 0x66, 0x66, 0x00};
char font_b[8] = {0x7E, 0x66, 0x66, 0x7E,
0x66, 0x66, 0x7E, 0x00 };



void init_vga(void)


Now our main file that will call all function

// eva.c -- Defines the C-code kernel entry point, calls initialisation routines.
//           @author<Vishal Mishra><>
//           @change fri-Mar-2,12:01 

#include "text_mode.h"
#include "vga.h"

int eva(struct multiboot *mboot_ptr)
    // Initialise the screen (by clearing it)
    // Write out a sample string
     eva_write(" Eva Operating System ....Loading   ");
   //uncomment above statement to switch to vga mode 
    return 0;

Output after compiling and linking ....

Eva Operating System

After uncommenting the VgaTest function output looks like...


To compile it use following commands in linux(ubuntu)

1: sudo make -f Makefile
2: qemu -kernel kernel


Thursday, 23 February 2012

Default x86 Port Address Assignments

Default x86 Port Address Assignments
Address RangeFirst QWORDSecond QWORDThird QWORDFourth QWORD
0x000-0x00FDMA Controller Channels 0-3
0x010-0x01FSystem Use
0x020-0x02FInterrupt Controller 1System Use
0x030-0x03FSystem Use
0x040-0x04FSystem TimersSystem Use
0x050-0x05FSystem Use
0x060-0x06FKeyboard/PS2 Moude (Port 0x60)
Speaker (0x61)
Keyboard/PS2 Mouse (0x64)System Use
0x070-0x07FRTC/CMOS/NMI (0x70, 0x71)DMA Controller Channels 0-3
0x080-0x08FDMA Page Register 0-2 (0x81 - 0x83)DMA Page Register 3 (0x87)DMA Page Register 4-6 (0x89-0x8B)DMA Page Register 7 (0x8F)
0x090-0x09FSystem Use
0x0A0-0x0AFInterrupt Controller 2 (0xA0-0xA1)System Use
0x0B0-0x0BFSystem Use
0x0C0-0x0CFDMA Controller Channels 4-7 (0x0C0-0x0DF), bytes 1-16
0x0D0-0x0DFDMA Controller Channels 4-7 (0x0C0-0x0DF), bytes 16-32
0x0E0-0x0EFSystem Use
0x0F0-0x0FFFloating Point Unit (FPU/NPU/Mah Copprocessor)
0x100-0x10FSystem Use
0x110-0x11FSystem Use
0x120-0x12FSystem Use
0x130-0x13FSCSI Host Adapter (0x130-0x14F), bytes 1-16
0x140-0x14FSCSI Host Adapter (0x130-0x14F), bytes 17-32SCSI Host Adapter (0x140-0x15F), bytes 1-16
0x150-0x15FSCSI Host Adapter (0x140-0x15F), bytes 17-32
0x160-0x16FSystem UseQuaternary IDE Controller, master slave
0x170-0x17FSecondary IDE Controller, Master driveSystem Use
0x180-0x18FSystem Use
0x190-0x19FSystem Use
0x1A0-0x1AFSystem Use
0x1B0-0x1BFSystem Use
0x1C0-0x1CFSystem Use
0x1D0-0x1DFSystem Use
0x1E0-0x1EFSystem UseTertiary IDE Controller, master slave
0x1F0-0x1FFPrimary IDE Controller, master slaveSystem Use
0x200-0x20FJoystick PortSystem Use
0x210-0x21FSystem Use
Sound Card
Non-NE2000 Network CardSystem Use
0x230-0x23FSCSI Host Adapter (0x220-0x23F), bytes 17-32)
Sound Card
Non-NE2000 Network CardSystem Use
NE2000 Network Card (0x240-0x25F) Bytes 1-16
0x250-0x25FNE2000 Network Card (0x240-0x25F) Bytes 17-32
Sound Card
Non-NE2000 Network CardSystem Use
NE2000 Network Card (0x240-0x27F) Bytes 1-16
System UsePlug and Play System DevicesLPT2 - Second Parallel Port
System UseLPT3 - Third Parallel Port (Monochrome Systems)
NE2000 Network Card (0x260-0x27F) Bytes 17-32
Sound Card
Non NE2000 Network CardSystem Use
NE2000 Network Card (0x280-0x29F) Bytes 1-16
0x290-0x29FNE2000 Network Card (0x280-0x29F) Bytes 17-32
Non NE2000 Network CardSystem Use
NE2000 Network Card (0x280-0x29F) Bytes 1-16
0x2B0-0x2BFNE2000 Network Card (0x280-0x29F) Bytes 17-32
0x2C0-0x2CFSystem Use
0x2D0-0x2DFSystem Use
0x2E0-0x2EFSystem UseCOM4 - Fourth Serial Port
0x2F0-0x2FFSystem UseCOM2 - Second Serial Port
Sound Card / MIDI PortSystem Use
Non NE2000 Network CardSystem Use
NE2000 Network Card (0x300-0x31F) Bytes 1-16
0x310-0x31FNE2000 Network Card (0x300-0x32F) Bytes 17-32
Sound Card / MIDI Port (0x330, 0x331)System Use
NE2000 Network Card (0x300-0x31F) Bytes 17-32
SCSI Host Adapter (0x330-0x34F) Bytes 1-16
Sound Card / MIDI PortSystem Use
Non NE2000 Network CardSystem Use
NE2000 Network Card (0x300-0x31F) Bytes 1-16
SCSI Host Adapter (0x330-0x34F) Bytes 17-32
SCSI Host Adapter (0x340-0x35F) Bytes 1-16
Non NE2000 Network CardSystem Use
NE2000 Network Card (0x340-0x35F) Bytes 1-16
SCSI Host Adapter (0x340-0x35F) Bytes 17-32
NE2000 Network Card (0x300-0x31F) Bytes 1-16
Tape Accelerator Card (0x360)System UseQuaternary IDE Controller (Slave Drive)(0x36E-0x36F)
Non NE2000 Network CardSystem Use
NE2000 Network Card (0x300-0x31F) Bytes 1-16
Tape Accelerator Card (0x370)Secondary IDE Controller (Slave Drive)LPT1 - First Parallel Port (Color systems)
System UseLPT2 - Second Parallel Port (Monochrome Systems)
NE2000 Network Card (0x360-0x37F) Bytes 1-16
0x380-0x38FSystem UseSound Card (FM Synthesizer)System Use
0x390-0x39FSystem Use
0x3A0-0x3AFSystem Use
0x3B0-0x3BFVGA/Monochrome VideoLPT1 - First Parallel Port (Monochrome Systems)
0x3C0-0x3CFVGA/CGA Video
0x3D0-0x3DFVGA/CGA Video
Tape Accelerator Card (0x370)System UseCOM3 - Third Serial Port
System UseTertiary IDE Controller (Slave Drive)(0x3EE-0x3EF)
Floppy Disk ControllerCOM1 - First Serial Port
Tape Accelerator Card (0x3F0)Primary IDE Controller (Slave Drive)(0x3F6-0x3F7)System Use