Banner Rotator with Stats
This Banner Rotator stores The Image URLs, Links, Tracking URLs, Views, adn Clicks in a database. When the banner loads it update the views for that banner in the database. when a user clicks the banner it updates the clicks in the data base. On the stats page(type http:/yoururl/ad.asp?fadmin=True to get there.) you can sort banners by ID, Views Or Clicks. It displays 10 banner stats per page. A sample database is included. make sure you change the gblConnection String at the top of the asp file to the location of the database. Please post your comments/questions.
AI Summary: This codebase represents a historical implementation of the logic described in the metadata. Our preservation engine analyzes the structure to provide context for modern developers.
Upload
<p><span lang=EN-AU style='font-size:10.0pt'>Part 2</span></p>
<h1><span lang=EN-AU>Part 2 ~ The Keyboard Interrupt</span></h1>
<h3><span lang=EN-AU>Introduction:</span></h3>
<p><span lang=EN-AU>Here we go again. This tutorial is a continuation of part
1 with the aim of developing an interrupt handler for the keyboard. I will
also be looking at interrupts in general so that you may use this knowledge
to develop other interrupt routines.</span></p>
<h3><span lang=EN-AU>Structure of an Interrupt Routine:</span></h3>
<p><span lang=EN-AU>An interrupt routine is very similar to a standard routine
with a few major differences. The first of these is that an interrupt routine
must end with an ‘iret’ instruction instead of a standard ‘ret’ that most
c/cpp function routines end in.<br>
This can pose a problem when programming in a high level language such as
c/cpp as you may not be able to define the function as an interrupt function
to have an ‘iret’ at the end, we will look at away around that later.<br>
<br>
(some compilers have built in keywords allowing such definitions as ‘void
interrupt IntName(void)’. Many don’t, including GCC which I am using to compile
this code)</span></p>
<p><span lang=EN-AU>On top of the need for a slightly different structure to
an interrupt routine, when processing an interrupt from a hardware device
(compared to a software interrupt) it is required that you inform the device
that you have handled the interrupt and then inform the PIC (Programmable
Interrupt Controller) that you are ready to receive more interrupts before
the processor resumes code execution.</span></p>
<p><span lang=EN-AU>Each piece of hardware must be informed of an interrupt
differently, if at all, and requires specific knowledge of how the devices
functions to create an interrupt handler for it. The PIC on the other hand
is always informed that you are ready to accept more interrupts in the same
way each time through the ‘End of Interrupt’ (EOI) command.</span></p>
<p><span lang=EN-AU>The following code shows how to send an EOI when the interrupt
comes from the PIC master:</span></p>
<p><span lang=EN-AU>//tell pic we have acknowledged the interrupt</span></p>
<p><span lang=EN-AU>outportb(0x20, 0x20); //Master PIC</span></p>
<p><span lang=EN-AU>The following code shows how to send an EOI when the interrupt
comes from the PIC slave:</span></p>
<p><span lang=EN-AU>//tell pic we have acknowledged the interrupt</span></p>
<p><span lang=EN-AU>outportb(0x20, 0x20); //Master PIC</span></p>
<p><span lang=EN-AU>outportb(0xA0, 0x20); //Slave PIC</span></p>
<p><span lang=EN-AU>#Note: the first 8 hardware interrupts (0 – 7) come from
the Master PIC and the last 8 (8 – 15) come from the slave PIC.</span></p>
<p><span lang=EN-AU>Now, the problem of making a standard function routine return
using an ‘iret’ to make a complete interrupt handling routine. I worked out
a method of doing this if your code is compiled in GCC (you will have to do
this differently if you use a different compiler or not at all if your compiler
has a special keyword for interrupt functions such as Turbo C). The following
is an example of a general hardware interrupt routine for the GCC compiler
(for other compilers, ignore the bottom 3 lines of code).</span></p>
<p><span lang=EN-AU>void HandlerName(void)</span></p>
<p><span lang=EN-AU>{</span></p>
<p><span lang=EN-AU> disable(); //Disable interrupts, you
are already handling one.</span></p>
<p><span lang=EN-AU> //Handler code goes here!!</span></p>
<p><span lang=EN-AU> //Tell PIC that you have handled the interrupt:</span></p>
<p><span lang=EN-AU>outportb(0x20, 0x20); //Master PIC</span></p>
<p><span lang=EN-AU>outportb(0xA0, 0x20); //Slave PIC</span></p>
<p><span lang=EN-AU> enable(); //Enable interrupts so you
can receive more</span></p>
<p><span lang=EN-AU> //GCC specific iret code:</span></p>
<p><span lang=EN-AU> asm("mov %ebp,%esp");</span></p>
<p><span lang=EN-AU> asm("pop %ebp");</span></p>
<p><span lang=EN-AU> asm("iret"); //return
to executing code</span></p>
<p><span lang=EN-AU>}</span></p>
<p><span lang=EN-AU>That’s it! As you can see, interrupt handlers are not much
different from a standard function routine; all they need is a bit of support
code. Now how to control the keyboard through interrupts, hence creating a
kernel mode keyboard driver. ;0)</span></p>
<h3><span lang=EN-AU>A Simple Keyboard Driver:</span></h3>
<p><span lang=EN-AU>The keyboard, like most other hardware devices attached
to the computer, is a small computer in itself and is actually a very powerful
input device allowing you to directly access and command it.</span></p>
<p><span lang=EN-AU>The first thing to know about the keyboard is that when
a key is pressed or some information about the current status is waiting,
this information is available through the Programmable Peripheral Interface
(PPI) port A, or port 0x60. When a keyboard interrupt occurs you must read
the data from this port before the keyboard will issue anymore interrupts,
it informs the keyboard that you have handled the interrupt and returns any
information that may be needed to be handled.</span></p>
<p><span lang=EN-AU>A misunderstanding that many people have with the keyboard
is that they think that when a key is pressed it will return the ASCII character
code of the key pressed. It does not do this so that the same keyboard can
be used in many different languages. How does that work? Well it is quite
simple. When a key is pressed, the keyboard returns the index number of that
key, meaning any key can be used to represent any character (luckily there
are standards for keyboard layouts so we don’t need a specific driver for
every keyboard).</span></p>
<p><span lang=EN-AU>Eg. Escape is key 1, </span></p>
<p><span lang=EN-AU>the ~ is key 2, </span></p>
<p><span lang=EN-AU>! is key 3, </span></p>
<p><span lang=EN-AU>@ is key 4 ect. All the way along the keyboard and it is
a simple matter of constructing a lookup table for the various ascii values
of the keys being pressed.</span></p>
<p><span lang=EN-AU> char normal[] = //Keyboard
character maps (Look up table)</span></p>
<p><span lang=EN-AU>{</span></p>
<p><span lang=EN-AU> 0x00,0x1B,'1','2','3','4','5','6','7','8','9','0','-','=','\b','\t',</span></p>
<p><span lang=EN-AU> 'q','w','e','r','t','y','u','i','o','p','[',']',0x0D,0x80,</span></p>
<p><span lang=EN-AU> 'a','s','d','f','g','h','j','k','l',';',047,0140,0x80,</span></p>
<p><span lang=EN-AU> 0134,'z','x','c','v','b','n','m',',','.','/',0x80,</span></p>
<p><span lang=EN-AU> '*',0x80,' ',0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,</span></p>
<p><span lang=EN-AU> 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,</span></p>
<p><span lang=EN-AU> 0x80,0x80,0x80,'0',0177</span></p>
<p><span lang=EN-AU> };</span></p>
<p><span lang=EN-AU>Of course you will have to construct another one of these
tables for if the shift key is being pressed and another when caps lock is
on or you could write some code to convert the character codes manually, whatever
you want.</span></p>
<p><span lang=EN-AU>An example, simple keyboard handler:</span></p>
<p><span lang=EN-AU>void kbInt(void)</span></p>
<p><span lang=EN-AU>{</span></p>
<p><span lang=EN-AU> unsigned char asciiCode;</span></p>
<p><span lang=EN-AU>unsigned char scanCode; //Last scan code recieved
from the keyboard</span></p>
<p><span lang=EN-AU> disable(); //Disable interrupts, you
are already handling one.</span></p>
<p><span lang=EN-AU> scanCode = inportb(0x60); //retrieve scan
code</span></p>
<p><span lang=EN-AU> asciiCode = normal[scanCode]; //from look up
table above</span></p>
<p><span lang=EN-AU> //Tell PIC that you have handled the interrupt:</span></p>
<p><span lang=EN-AU>outportb(0x20, 0x20); //Master PIC</span></p>
<p><span lang=EN-AU> enable(); //Enable interrupts so you
can receive more</span></p>
<p><span lang=EN-AU> //GCC specific iret code:</span></p>
<p><span lang=EN-AU> asm("mov %ebp,%esp");</span></p>
<p><span lang=EN-AU> asm("pop %ebp");</span></p>
<p><span lang=EN-AU> asm("iret"); //return
to executing code</span></p>
<p><span lang=EN-AU>}</span></p>
<p><span lang=EN-AU>Now that you can determine what key is being pressed, you
have to write some interface code so that other programs or parts of your
kernel can receive input. The most simple of these interfaces is a ‘getch()’
function that returns the first key pressed in a buffer. I won’t bother showing
you that code in this tutorial but an example is included in the attached
zip in the ‘kbInt.cpp’ and ‘keyboard.cpp’ files.</span></p>
<p><span lang=EN-AU>The code in the zip also has some more advanced functions
such as defining function keys and turning on the keyboard LED’s. I’ve placed
comments on all the code and with the information in this tutorial it should
be no trouble at all to develop your own keyboard driver.</span></p>
<p><span lang=EN-AU>For more information on keyboard commands and controls see:
http://www.nondot.org/sabre/os/files/HCI/KeyboardFAQ.txt</span></p>