Hardware Ports

Atrevida Game Programming Tutorial #6
Copyright 1997, Kevin Matz, All Rights Reserved.

"Prerequisites":

  • Chapter 1: Introduction to Binary and Hexadecimal
  • Chapter 2: Binary Operations
  • Chapter 3: Binary Manipulations

       

What are hardware ports?

Hardware ports are the primary method of communication with external devices and the PC's support chips. (Reading and writing to specific memory locations, or memory-mapped I/O, is the other method; this method is applicable to very few devices, such as the video card. BIOS and DOS services that access hardware devices make use of either hardware ports or memory.)

We can read and write values to and from hardware ports. I like to think of ports as "portholes" or "doorways" through which information can be passed to or retrieved from "the outside world". The term "outside world" is actually quite commonly used, and it usually refers to everything outside of the processor (so the support chips inside the computer are often deemed part of the outside world). When we read from or write to a port, we are actually reading from or writing to memory locations that are not part of the main memory, but are a part of the device that we are programming.

There are 65536 possible hardware ports, although most of them are unused. They are always numbered using hexadecimal, so the range is 0 hex to FFFF hex.

Writing to hardware ports using C/C++

In Turbo/Borland C and C++, we can use the port input/output functions from either dos.h or conio.h.

If we "#include <dos.h>", then we can use the functions (or macros) outportb(), for writing a byte, and outport(), for writing a word.

If we "#include <conio.h>", we can use outp() for writing bytes and outpw() for writing words to hardware ports.

The prototypes for each are listed below:

int outportb (unsigned int port, int value);
unsigned int outport (unsigned int port, unsigned int value);
int outp (unsigned int port, int value);
unsigned int outportw (unsigned int port, unsigned int value);

Notice that outport() and outp() use int types in the places where I think that char types (bytes) would have been more appropriate.

So, as an example, say we wish to write the byte-sized value 85 hex to port number 9D4 hex. We could use either of the following statements:

outportb (0x9D4, 0x85);
outp (0x9D4, 0x85);

What happens if we write a word? Writing a word to a port results in writing a word to a particular device's memory, and that memory must use the little endian format for storing multiple-byte numbers. The least-significant (rightmost) byte of the word is stored in the first memory location, and the most-significant (leftmost) byte of the word is stored in the next memory location. The same effect can be achieved by writing the least-significant byte to a port number "x", and then writing the most-significant byte to the port "x + 1". So, the following code fragments for writing words to ports are equivalent:

outpw (0x9EB, 0x4D3C);

and

outp (0x9EB, 0x3C);
outp (0x9EC, 0x4D);             /* 0x9EB + 1 = 0x9EC */

(Of course, you could replace "outpw" with "outport" and "outp" with "outportb"; just be sure to include the correct header file.)

By writing values to ports, we can send commands or data to devices.

Reading from hardware ports in C/C++

Again, using Turbo/Borland C and C++, we have the choice of using the dos.h or the conio.h routines for accessing the hardware ports.

With dos.h, we can use the inportb() and inport() functions or macros; with conio.h, we can use the inp() and inpw() functions or macros. The syntaxes are listed below:

int inportb (unsigned int port);
unsigned int inport (unsigned int port);
int inp (unsigned int port);
unsigned int inpw (unsigned int port);

Suppose we wish to read a byte from port 76A hex, and store the result in a variable called value. We could use either of the following two statements:

value = inportb(0x76A);
value = inp(0x76A);

Reading a word from a port is similar to writing a word to a port. We must take into account the fact that little endian number storage is used. Reading a word from a port means that the word that is returned is constructed from two bytes: the least-significant byte will come from the first port address "x", and the most-significant byte will come from the next port address, "x + 1". So, the following two examples should be equivalent:

value = inpw(0x4000);

and

value = inp(0x4000) + (inp(0x4001) << 8);

An example of the usage of ports

For an interesting example of how ports can be used, we will construct a short program that accesses some of the VGA's registers. (If you do not have a VGA card (in this case, an EGA should work as well), this example will not work.) The example is fairly involved, but it demonstrates a fairly common situation that is encountered when programming devices through ports.

If you have done any programming in text mode (or drawing "ANSI art") using different colors and attributes, you are aware that each character can have one of sixteen foreground colors, one of eight background colors, and as well, that character's foreground can blink or remain solid. But by manipulating some of the VGA's registers by using ports, we can change this setup: we will be able to select from sixteen colors for the foreground (as usual), but we will be able to select from sixteen background colors instead of eight (but we give up blinking). We will gain access to the "high-intensity" colors, 8 dec through 15 dec, for use as background colors.

First, I'll give some brief background information for using colors in text mode. (Admittedly, this part is unrelated to ports.)

In Borland and Turbo C/C++, with conio.h, there are facilities for changing the foreground and background colors. The function textcolor() accepts an integer in the range 0..15 dec as a parameter, and sets the current color to that value. The function textbackground() accepts an integer in the range 0..7 dec as a paramter, and sets the current background color to that value. For example, to use a bright magenta (pink) foreground on a cyan background, we can use:

textcolor (13);                 /* 13 is the "code" for bright magenta */
textbackground (3);             /* 3 is the "code" for cyan */

Now, to use this tacky color combination, you use the cprintf() function, which works just like printf():

cprintf ("This text is bright magenta, with a cyan background.\n");

To use blinking, you can use a function called textattr(), which takes as its parameter an int in the range 0..255. Here is a bit diagram showing how to construct the color codes:

          7     6     5     4     3     2     1     0
       +-----+-----+-----+-----+-----+-----+-----+-----+
       |BLINK|  R  |  G  |  B  |  I  |  R  |  G  |  B  |
       +-----+-----+-----+-----+-----+-----+-----+-----+
             |<-- Background ->|<---- Foreground ----->|

       Bit 7:  1 = blinking on; 0 = blinking off
       Bit 6:  Background red component on/off
       Bit 5:  Background green component on/off
       Bit 4:  Background blue component on/off
       Bit 3:  High-intensity foreground on/off
       Bit 2:  Foreground red component on/off
       Bit 1:  Foreground green component on/off
       Bit 0:  Foreground blue component on/off

If we wanted blinking bright green text (blink bit + high intensity foreground + green foreground) on a purple background (green background + blue background), our attribute code would be 2^7 + 2^3 + 2^1 + 2^5 + 2^4, or 128 + 8 + 2 + 32 + 16 (decimal), which equals 186 dec. The faster method is to create the pattern 10111010 bin, which is BA hex:

textattr (0xBA);
cprintf ("This is bright green blinking text on a purple background.\n");

Note that when high-intensity backgrounds are enabled, bit 7, the "blinking on/off" bit, will instead be the "high-intensity background on/off" bit. This will allow 16 possible colors for the background.

Now we can return to our discussion of ports.

There is one bit in one of the VGA's registers which, if set, permits blinking, and if cleared, permits high-insensity backgrounds. The register that we need to modify is the "Attribute Controller Mode Control Register". Unfortunately, we cannot write directly to this register in one easy step.

On the VGA, and often with other devices, there are many registers available, but the VGA (or other device) only uses a few ports. The registers need to share the limited number of ports. To allow access to multiple registers, the following scheme is common: an "array" of registers exists that is accessible through an "address" or "index" port and read and/or write ports. You write a number to the index port, which tells the device which register you want to access. If there were, say, ten registers available, and you wanted to write a value to register number 8, you would usually write the number 8 to the index port. Then, you would write the value that you wish to put in register 8 to the write port. Or, if a read port was available, you could read a value from that read port, and you would get returned the current value of register number 8.

This is the way that you access most registers on the VGA. The VGA has several "families" of registers, such as the Sequencer Registers, the CRT Controller Registers, and so on. Each family of registers has an index port and a read and/or write port.

The Attribute Controller family of registers is slightly different, however. There is no real index port, just a write port and a separate read port. Here's how you use it: you first need to "reset" the circuitry controlling the write port. You do this by reading a byte from another VGA port, the "Input Status #1" register (you can throw away the returned byte). Then, you write a specially coded address byte (described shortly) to the write port to indicate which register you wish to access. In the Attribute Controller family, there are twenty registers available (0 hex through to 14 hex). Then, you can either write a value to the selected register through the write port, or you can read a value from that selected register from the read port.

The Input Status #1 register is located at port 3DA hex. The Attribute Controller family's write port is at port 3C0 hex, and its read port is at 3C1 hex.

Here is the format of the address byte for the Attribute Controller family of registers:

          7     6     5     4     3     2     1     0
       +-----+-----+-----+-----+-----+-----+-----+-----+
       | XXXXXXXXX | PAS |             ADR             |
       +-----+-----+-----+-----+-----+-----+-----+-----+

       Bits 6..7:  Unused
           Bit 5:  Palette Address Source bit.  (This should be left as
                   1; if it is 0, the screen goes blank, because the
                   VGA is not allowed to access the memory containing
                   palette information).
       Bits 0..4:  Address index (in the range 0 hex to 14 hex).

The Attribute Controller register we want to access, the Mode Control register, has the index 10 hex. If you're curious about the other nineteen registers in this family, I'd suggest taking a look at the books listed in the "references" section at the end of this article. Here is the format for the Mode Control register:

          7     6     5     4     3     2     1     0
       +-----+-----+-----+-----+-----+-----+-----+-----+
       | IPS | PCS | PPC | XXX | B/I | ELG | DT  | G/A |
       +-----+-----+-----+-----+-----+-----+-----+-----+

       Bit 3:  Blink/Intensity bit.  0 = permit high-intensity
                                         backgrounds
                                     1 = permit blinking (default)

You're probably curious about all of those other bits. I'd like to list them all, but that would take up too much space, and I'd probably be violating some copyrights. Again, if you're interested, check out the "references" section at the end of this article.

So, finally, here's our plan:

natalia paris, i thought paper would protect you asshole, ass in the face, sailor moon lesbian sex, rape me by nirvana, mature mom galleries, public, celebs upskirt, bitches and hoes, biggest tits in the world, asian speculum, tattoo skull art, thai bdsm, cartoon smoking weed, www forced witness, sexiest women of reality tv, skinny old, finger masturbation, pornstars, indian girls fucking, extreme systems forums, facial hair, sex machine movies, asian hardcore porn, ohio, free incest videos, girl with tran, dick in girls mouth, chicks doing it, paris hilton movie, nurse with penis, huge load jizz mouth face, bisexual sluts, dirty bare feet, bbw chat, shemale buffet, brunette facial, my mom is pierced, ethnic gay videos, gay youth nad younger, amature gangbang, Fetish, deap throat, big black cocks, pregnant bitch, xxx nylons, zoo animals cake, shemale cumshots, fantasy football draft picks, gay dad fucking son incest, male become female, upskirt voyeur, japanese upskirts, coeds tits, hottest tranny, naked teen, corset bondage, us military hand to hand combat video, mature sluts, black nipple, best music video clips, sexy latin brides, pussy hair, gang rape, gay nude men, milf maid, dad fucking young daughter, retro office supplies, juicy big melons, dirty sanchez on mtv, cfnm girl night, adult party games, cartoon kid, asian spanking, dildo, clit free picture xxx, jasmine aladdin nude toon, young teen girl fucks a dog, fucking in the office, adult schoolgirl punishment, online dating carrollton, celebreties naked, hairy, live nude webcams, women sex toys, kids winter boots, Porn, aubade lingerie, petite tanned ass, naked gay men, shaved eyebrows, topless housewives, redheads having sex, pre teen tiny models, suck me, Beach, swallowing sluts, female fingering, gay toon studs, adult group, nude resorts brazil, young teen models, is it ok to swallow your own cum, gothic girls boobs, xxx dvds, young teens in bikinis, dad fucks mom, outdoor spiral stairs, fat, hustler video on demand, her first lesbian sex, ffm video gallery, best spanking stories, wet blondes, cheerleaders fingering, wife swap pictures uk, penis domination, foxtrot uniform charlie kilo bloodhound gang, amateur lingerie models, gagging blowjob, massage handjob, oops paparazzi picture, masturbating wife, wife heels stockings out, milf big tits, gay male stories, outlaw star hentai, vet silicone lubricant to treat knee injuries in horses, oral deep throat, sylvia saint cum, anal cunt, butt banging, free nude midgets, beastiality blog, flexible female, liteon dvd rw, sexy mens underwear, latina creampie, long orgasm, big mature boobs, girls shower sex, Dick, very young twinks, gay scat ring, simulate a vagina, free sapphic erotica video, chubby teen tgp, rimjob gallery, adult penetration, free hentai gallery, crotchless sheer thongs, hot ebony, upskirt hidden cam, triple fisting, hot sexy legs, cock enormous huge, asian pussy closeup, college girls party, secretary fucks boss, peeps survival testing, large ass, kim possible xxx, mutual masturbation, adult comics, busty blonde bombshells, free hustler movie porn, cfnm facial, black chicks melons, free porn movies, fart face, spread asshole, ffm fucking stories, schoolgirl uniform bondage, outlaw biker gangs, girls facial cumshots, pierced gay, self suck you penis, girl forced girl, bobbi billard bikini, dad, nude latina maids, sex stockings, huge cocks and boobs, gay jock, drunk college chicks, feet in pussy, dick dale, logo retro, secretary suck, free rimjob video, gauge gangbang, creampie licking, tiny vessels, pamella trans anderson, tits nails skewers, Closeup, anal sex videos, straight naked military men, chinese tits, upskirt movies, free handjob video, dirty poems, teen male models, ebony thong models, nudism and teens, male medical fetish, exotic latin models, Movies, naked women in the shower, nice round tight asses, Coed, erotic silicone casting, speculum in pussy, nipple clamp, pregnancy as result of rape, Toys, blood clot leg pain, Celebreties, adult chi chi dragonball z incest, pussy spanking, extreme use of internet policy, sexy smoking women, pornstar caramel, black bitch, naked preteen girls, twila paris, hot tanned chicks, Twink, puss in throat, free anal videos, shaved pussy pics, nude gay studs, free porn downloads, milf archives, accounts enormous natural breasts, interracial sex, pussy cum, tattoo, group party orgies, black jizz, reality sex review, free midget xxx, slut, young cock, horse cock penetration, nurse orgy, moms sex, free oral sex videos, girl with dildo, toon, live web girls, big clit free video, squirting female ejaculation squirting orgasms, outdoor floor mat, cigarette making machine, Ethnic, beach casual wedding dress, free voyeur movies, female mixed wrestling domination, asian sluts, hentai clips, office whores, naked men in publiublic gangbang, tasteful erotica, wife swinging, nude chubby girls, indian gay, hardcore teacher sex, naked group sex, fanfiction body swap, men nude hunk, free cheerleader pussy, brittany spears nude, how many youths are in gangs in colorado, big tits blowjob, 38 weeks pregnant, teen schoolgirls, Tranny, flexible van contract hire, celeb, girls butts, hot lesbian dildo sex, nude mature women, free naked fat women, paris hilton pussy, forced sex fantasy, brunettes with big tits, vagina anatomy, butt to mouth, suck dad, free funny clips download, horse cum swallow, naughty adult lingerie, female gymnast, old hairy pussy, adult cartoon, anime fuck, free japanese scat, sylvia young dance school, hidden cam upskirt, bisexual sex tips, shemale comics, sex amateur, bbw masturbation, shemale nylon, Housewives, fuck zoo, gothic anime girls, girls wearing thongs, sexy skinny, no peep bow sights, hardcore brazil, redhead, young xxx, latina fisting, sexy wet muddy boots, beastiality mpgs, single parent dating, celebrity paparazzi photo, bdsm gallery, hardcore dvd, mom spanking, 2004 train show swap meet, hustler magazine .com, big breasted brunettes, pussy fart, nurses hentai, gay cocks, cock uncut, cheap porn dvds, ffm jpegs, pornstar index, bbw milf, pictures of pregnant women, office whore, free latin xxx, secretary panties, lose body fat, the simpsons porn, toon blowjob, huge floppy tits, latina tranny, tv news clips, suck tran, live sex webcams, robb's celebreties, free lesbian rimjob video, zoo gay, teen boobs, young ethnic boys, facial exercises, doggy style sex, up cheerleaders skirts, perfect vagina, teens wear thongs, henna tattoo kit, military gay men, free adult erotica, im rick james bitch, hot brunette stockings couch, oral contraceptives, shaved sluts, gang fucking, female feet licking, sexy gothic lesbians, with dumb blonde jokes, rape in action, milf melons, incest dvd, shaved chubby, midget sex video, silvia saint video, extreme body com, cfnm movie, quadruple fisting, xxx hardcore sex, infernal - from paris to berlin, interracial dating online, creampie housewives, male masturbation techniques, bdsm torture drawings, naked celeb fakes, cfnm video clips, footjobs pics, jizz face fuck, ebony creampies, teen spanking videos, lolita tiny, cock enormous free picture, just redheads pussies, housewife nude, asian dick, beastiality bulletin board, free online retro game, blonde closeup, domination fetish, final fantasy hentai gallery, indian girls actresses, group lesbian party, strep throat in adults, nylon dildo porn, hairy jock guys, soccer mom sex, cum face cuties, bbw mom, jessica simpson nipple, eye brow pierced, extreme sex toys, crest medical uniforms, orgasms in pubescent girls, sexy brazil women wanting, big dick in mouth, free nude pictures, twink piss, girls sading their legs, blow moulding machines for pet bottles, horny wifes, shower lesbians, gay men in thongs, forced hand job, cartoon nudes, horny frat studs, dads vs twinks, busty maid lingerie, dirty pic, nude college chicks, sylvia fine photo, sick sex fetishes, outdoor bronze water fountains, lesbian anime girls, youngest beach teens, male group masturbation, voyeur cameras, kingpin skinny pimp, purple nails handjob, teen youth centers, bdsm sex slaves, gay penetration, free adult strip games, boob slips, hentai school, lingerie topless, nudity in public gallery, ghetto ass, coeds masturbating, muscle xxx, bbs young model, free blowjob videos, underage schoolgirl, swallow wife, ebony reality porn, women fucking men with dildos, licked my asshole, girls upskirt, gynecologist speculum, asian street meat, free amateur pics, gangbang trailers, porn stars and silicone, nude smoking, fetish scat, xxx free, daddy's little slut, big clit free video, shemale thumbs, tight flexible nude girls, britney paparazzi pictures, fuck buddies, adult group activities, dad and little girl, mature slut, free gay bisexual sex, horse butt, free webcam chat live web cam chat, thigh boot galleries, tanned teen ass, college suck, busty bikini girls, horse anal, female wet dreams, jenna jameson naked, gay cum shots, little bo peep holloween costume

  1. Read in a byte from the Input Status #1 register (port 3DA hex).
  2. Construct an index or address byte. The register we want to access has the index 10 hex, and we want to turn on bit 5, which we can do by OR'ing the index number with 20 hex, like this: "index_byte = 0x10 | 0x20;"
  3. Output index_byte to the Attribute Controller family's write port (port 3C0 hex).
  4. Read in the value from the register we have selected by inputting a byte from the read port (port 3C1 hex). Store this value in a temporary variable such as x.
  5. Set (to permit blinking) or clear (to permit high-intensity background colors) the Blink/Intensity bit (bit 3) in x. To turn that bit on, we could use "x |= 0x80;". To turn that bit off, we could use "x &= 0xF7;".
  6. We want to write the value in x back to the Mode Control register, so to "reset" the write port's circuitry, read in a byte from the Input Status #1 register again (port 3DA hex).
  7. Output our index byte to the write port (3C0 hex) again.
  8. Write out the new value of x to the write port (3C0 hex).

Let's construct two functions in C using the above algorithm. EnableBlinking() will enable blinking, and EnableHighIntensityBackgrounds() will enable high-intensity backgrounds. While we're at it, let's write a short function to draw characters on the screen, using all of the different attribute codes from 0 to 255 dec. This will let us see the results of the change. In our main() function, we will draw the colored characters, wait for a keypress, switch to high-intensity background mode, wait for a keypress, and then return to blinking-enabled mode:

/* VGAREGS1.C: Quick VGA registers test program
   Copyright 1997, Kevin Matz, All Rights Reserved.

   This program displays some text-mode color patterns on the screen, and
   then switches between blinking and high-intensity modes.

   References used:
   - "Programmer's Guide to the EGA, VGA, and Super VGA Cards, Third
	 Edition", Copyright 1994, Richard F. Ferraro.  Addison-Wesley
	 Publishing Co., Inc., Reading, Massachusetts.  ISBN 0-201-62490-7.
   ------------------------------------------------------------------------*/

#include <stdio.h>
#include <conio.h>
#include <dos.h>

void DrawColorPatterns ();
void EnableBlinking ();
void EnableHighIntensityBackgrounds ();

main ()
{
    DrawColorPatterns ();

    printf ("This is the normal (blinking) state.\n");
    getch ();

    EnableHighIntensityBackgrounds ();
    printf ("This is the high-intensity background state.\n");
    getch ();

    EnableBlinking ();
    printf ("This is the blinking state again.\n");
    getch ();

    return 0;
}

void DrawColorPatterns ()
{
    int x, y, attribute;

    /* Draw the asterisk character with every possible text-mode
       attribute: */
    attribute = 0;
    for (x = 0; x <= 15; x++)
    {
        for (y = 0; y <= 15; y++)
        {
            textattr (attribute++);
            cprintf ("*");
        }

        textattr (0);
        printf ("\n");
    }

    /* Revert to the standard text colors: */
    textcolor (7);
    textbackground (0);
}


void EnableBlinking ()
{
    unsigned char old_mode_ctrl_reg;

    /* Read from the Input Status #1 register and throw away the returned
       value.  This is done to tell the Attribute Controller's write port
       to accept an index byte next. */
    inportb (0x3DA);
    /* Tell the VGA that we want to access the Attribute Controller's Mode
       Control Register (AC Index 10h); also, prevent the clearing of the
       screen, by setting bit 5 on: */
    outportb (0x3C0, 0x10 | 0x20);
    /* Get the current value: */
    old_mode_ctrl_reg = inportb(0x3C1);

    inportb (0x3DA);               /* Reset circuitry again. */
    outportb (0x3C0, 0x10 | 0x20); /* Indicate that we want AC Index 10h. */

    /* Turn on bit 4 (the Enable Blink or Intensity bit): */
    outportb (0x3C0, old_mode_ctrl_reg | 0x08);
}


void EnableHighIntensityBackgrounds ()
{
    unsigned char old_mode_ctrl_reg;

    /* Read from the Input Status #1 register and throw away the returned
       value.  This is done to tell the Attribute Controller's write port
       to accept an index byte next. */
    inportb (0x3DA);
    /* Tell the VGA that we want to access the Attribute Controller's Mode
       Control Register (AC Index 10h); also, prevent the clearing of the
       screen, by setting bit 5 on: */
    outportb (0x3C0, 0x10 | 0x20);
    /* Get the current value: */
    old_mode_ctrl_reg = inportb(0x3C1);

    inportb (0x3DA);               /* Reset circuitry again. */
    outportb (0x3C0, 0x10 | 0x20); /* Indicate that we want AC Index 10h. */

    /* Turn off bit 4 (the Enable Blink or Intensity bit): */
    outportb (0x3C0, old_mode_ctrl_reg & 0xF7);
}

/* End of listing */

Remember that you need to use the textattr() function to use blinking or high-intensity background characters. The bit diagram for determining color and attribute codes was described previously.

This example program shows that, by using ports (and systems programming in general), we can do many interesting and "amazing" things. For another program, I was able to shift the image on the screen back and forth (distorting some of the colors in the process) by changing the timing settings for a horizontal retrace counter register. Admittedly, this doesn't have any practical uses, but I think it does fall into the "cool" category.

Summary

Hardware ports allow us to access registers and memory locations on certain hardware devices. In C/C++, we can use functions such as inport(), inportb(), inp(), and inpw() to read from ports. To write to ports, we can use function such as outport(), outportb(), out(), and outw(). With some devices, you may need to set up an index through one port and read or write through another (or, in the example presented in this chapter, index and read/write ports may be shared).

References to material (sources used)

Ferraro, Richard F. "Programmer's Guide to the EGA, VGA, and Super VGA Cards, Third Edition". Reading, MA, USA: Addison-Wesley Publishing Co., Inc., 1994. ISBN: 0-201-62490-7.

(This rather thick book contains descriptions of all of the VGA's registers, as well as information on all of the major Super VGA chipsets. One of the chapters contains a decent selection of sample code. This book has been criticized as being full of minor errors, and while I have spotted a number of errors, I don't think the problem is too serious.)

There is an older book about the VGA and its registers that I am aware of. I believe the author's name is Wilton. I haven't seen this book, but when I find more information, I'll put it here.

  

Copyright 1997, Kevin Matz, All Rights Reserved. Last revision date: Wed. Jun. 04, 1997.

Go back

A project